Home

Awesome

IPFS Ecosystem Directory

Interactive IPFS ecosystem directory and showcase

Just want to add a new project to the IPFS ecosystem directory? Use this form.


Project Add/Change Workflow

The existing workflow for adding a project to the ecosystem directory, or amending an existing project, is as described below.

Adding a New Project

Amending an Existing Project


Generating the Showcase Grid

To view all projects in the ecosystem directory in a "logo parade" showcase format suitable for including in a slide deck, see the instructions below — this includes how to customize the grid to get the representation that's most useful for you.

TLDR: https://ecosystem.ipfs.tech/showcase/?category=focus is a general-purpose, useful grid if you don't want to build a custom one.

Behavior

Customization

Category

Customizing the view is done using GET parameters. You might notice that the base showcase link feels a little empty.

Adding a target top-level category param to showcase solves this issue. Examples:

Note: This category selection will work for both categories that allow one tag per project (category in which tags are mutually exclusive) and categories that allow multiple tags.

Containers

Instances of this app may have varying quantities of projects. To help the showcase address both large and small ecosystems, there are params that define container limits. These define what the limits are in terms of number of projects that fit into medium, or large containers.

Example use case: /showcase/?category=focus&md=5&lg=15

Note: The Showcase view is designed to support rows of 5 logos, so setting lg and md as multiples of 5 is recommended for the ideal visual appearance.

Location


General Developer Information

Deployment

This repo is currently deployed to Fleek on the following URLs:

main branch: https://ecosystem.ipfs.tech/

develop branch: https://ipfs-ecosystem-develop.on.fleek.co/

Pushes made to the main or develop branches of this repo will automatically be reflected in the URLs above. Please allow 2-5 minutes for the application to re-build before seeing changes in your browser.

Server

Ports

These apply to local development.

development: 20000
stable: 20001
production: 20002

Mode: static

Environment Variables

NODE_ENV → development|production
SERVER_ENV → development|stable|production

Getting Started

A. Get Repo

In a terminal, run the commands below to get set up

# Navigate to directory within which to clone the git repo.
$ cd ~/Desktop

# Clone the repo
$ git clone git@github.com:ipfs/ecosystem-directory.git

# Enter the repo directory
$ cd ecosystem-directory

# Add your user information
$ git config user.name "Your Name"
$ git config user.email "your.email@example.com"

# Install npm dependencies
$ npm ci

B. Generating a self-signed SSL certificate

Used for development in a local environment (such as on your personal computer). You only need to do this once. If you've already done this for a different project, just copy your existing localhost_cert.pem and localhost_key.pem files from ~/.ssh into the root directory of this repo and skip the rest of this step.

  1. Install mkcert and generate certificate by running the commands below, in that order:
$ cd ~/.ssh
$ brew install mkcert
$ mkcert -install
$ mkcert -key-file localhost_key.pem -cert-file localhost_cert.pem localhost 127.0.0.1
$ cat localhost_cert.pem > localhost_fullchain.pem
$ cat "$(mkcert -CAROOT)/rootCA.pem" >> localhost_fullchain.pem
  1. Copy the new localhost_cert.pem and localhost_key.pem files to the root directory of this repo
  2. Start the server and navigate to https://localhost:<your_port>

C. Environment variables

Create a file called .env and put it into the root directory of this repo. Add the following environment variables:

NODE_ENV=development
SERVER_ENV=development

D. Start the app

$ npm run dev

Project Model

Below is an outline of the project model. A boilerplate JSON file can be found in @/static/project-template.json. This template file can be duplicated, filled out and renamed to create a new project. It is not necessary to generate a project ID since the filename of each project will serve as a project slug. The project logo must be placed in the @/static/images/projects directory and committed to git. Just the logo name (ex: project-logo.svg) needs to be added to the project JSON file, no need to write out the full path.

Naming Convention

This means that file names must be named after project names, and use lowercase and kebab-case. For example, an appropriate project slug would be world-wide-web, and therefore the corresponding file would be world-wide-web.json. It's important to not deviate between the file name and the name of the project.

Keys

Keys should be retained when not in use. This ensures that if anyone wants to add to the project, they immediately see all keys available in other projects, rather than searching for the model or accidentally using a data structure that doesn't match the model perfectly. This means empty and type checking is done by the app in a strict fashion.

Schema

The schema can be found here and must be updated if the schema ever changes. The $setProjectDefaults() global method (found here) uses project-schema.json in order to perform type checking.

{
  display: Boolean,
  featured: Boolean,
  sortNumbers: {
    label: Number
  },
  logo: {
    icon: String,
    full: String
  },
  name: String,
  org: [String],
  description: {
    short: String,
    long: String
  },
  primaryCta: {
    url: String,
    text: String
  },
  links: [ {
    label: String,
    links: [ {
      url: String,
      text: String
    } ]
  } ],
  keyInfo: [ {
    label: String,
    value: String
  } ],
  video: String,
  stats: [ {
    label: String,
    value: String
  } ],
  ctaCard: {
    title: String,
    description: String,
    buttonText: String,
    url: String
  },
  taxonomies: [{
    slug: String,
    tags: [String]
  }]
}

Transforming Project Data

Each project that is to be included in the ecosystem must have a json file in @/content/projects, with the project name in kebab-case. For instance, @/content/projects/foo-bar.json.


Embeddable View

An interactive summary of the state of the app can be injected into external sites. It contains a slider with sample projects that can be filtered by one dimension, and sorted. This view is embeddable in 2 steps:

  1. Include a single Javascript file in the external site, from the path /embeddable-view.js

  2. Specify a target container on the external site, with either a class or id as follows

Customization

The content for the embeddable view, and target category for the dropdown, can be specified in the embeddable-view-settings.json file.

The embeddable view inherits the theming from the Ecosystem itself, but is also available in a light and a dark mode

On the external site, it might be useful to provide a max-width for the container

.ipfs-ecosystem-embed, #ipfs-ecosystem-embed {
  max-width: 600px;
}

If a class is used, multiple embeddable views can be instantiated on a single page. This is also useful for support of single page applications. The following HTML will call in two embeddable views, one light, and the other dark.

  <div class="ipfs-ecosystem-embed" data-theme="light"></div>
  <div class="ipfs-ecosystem-embed" data-theme="dark"></div>

Showcase

This application is shipped with an alternative data visualization, for the purpose of use in presentations and other media where a visual summary of the projects in the ecosystem is needed.

By default this view is called the Showcase, which is also the URL through which it's accessed. This path can be changed.

Behavior

Customization

Category

Customizing the view is done using GET parameters. The base showcase path will render projects, but may seem bare if no arguments are passed in the URI.

Adding a target top-level category param to showcase solves this issue. Examples:

Note: This category selection will work for both categories that allow one tag per project (category in which tags are mutually exclusive) and categories that allow multiple tags.

Containers

Instances of this app may have varying quantities of projects. To help the showcase address both large and small ecosystems, there are params that define container limits. These define what the limits are in terms of number of projects that fit into medium, or large containers.

Example use case: /showcase/?category=focus&md=5&lg=15

Note: The Showcase view is designed to support rows of 5 logos, so setting lg and md as multiples of 5 is recommended for the ideal visual appearance.

Location


Analytics

Analytics are implemented through Countly, using the Web SDK.

The following environment variables are required:

NODE_ENV=<production|development>
COUNTLY_APP_KEY=<key>
COUNTLY_SITE_URL=<url>

The following nuxt.config.js entries are required:

{
  countly: {
    initialize: true, // if set to false, Countly will be DISABLED
    debug: Boolean,
    disableInDevelopment: Boolean,
    suppressErrorLogs: Boolean
  }
}

Below is a breakdown of all events captured by Countly.

→ General

Countly.track_sessions()
Countly.track_pageview()
Countly.track_links()

→ Segment Chart

Segment clicked

name: <category_label>

slug: <category_slug>

Countly.trackEvent('Segment Chart | Segment Clicked', { label, slug })

View All button clicked

name: <category_label>

slug: <category_slug>

Countly.trackEvent('Segment Chart | View All Button Clicked', { label, slug })

→ Featured Slider

Project card clicked

name: <project_name>

slug: <project_slug>

from: Home Page | Detail Page

Countly.trackEvent('Featured Slider | Project Card Clicked', { name, slug, from })

→ Events

Filter Panel Toggled

button: filters | x-icon | done

state: open | closed

Countly.trackEvent('Filter Panel Toggled', { button, state })

Sort-By Dropdown Toggled

state: open | closed

Countly.trackEvent('Sort-By Dropdown Toggled', { state })

Sort-By Option Selected

label: <sort_option_label>

slug: <sort_option_slug>

Countly.trackEvent('Sort-By Option Selected', { label, slug })

Pagination Button Clicked

page: <number>

Countly.trackEvent('Pagination Button Clicked', { page })

Results-Per-Page Dropdown Toggled

state: open | closed

Countly.trackEvent('Results-Per-Page Dropdown Toggled', { state })

Results-Per-Page Option Selected

option: <number>

Countly.trackEvent('Results-Per-Page Option Selected', { option })

Grid-List View Toggled

view: list | grid

Countly.trackEvent('Grid-List View Toggled', { view })

Filter Chiclet Clicked

tag: all | <tag>

category: <parent_category>

state: on | off

Countly.trackEvent('Filter Chiclet Clicked', { tag, category, state })

Clear Filters Button Clicked count: <number>

Countly.trackEvent('Clear Filters Button Clicked', { count })

Filter Panel Search Input

There exists a 500ms debounce function in the search input so as to provide a greater chance of capturing a full rather than partial search query.

query: <search_term>

Countly.trackEvent('Filter Panel Search Input', { query })

→ Header/Footer

Links get automatically tracked by Countly.track_links()

→ 404

Countly.trackEvent('404_NOT_FOUND', {
  path: this.$route.path,
  referrer: document.referrer
})

→ Query params

Track URL entire query param object when interacting with project filtering system. Since every param change is already tracked individually as per the list above, this tracker exists as an added layer for testing.

query: Object

Countly.trackEvent('Query Param Debug', { query })