Important
This boilerplate is no longer maintained and the repository is archived.
The live IPFS Ecosystem Directory at ecosystem.ipfs.tech is not built from this repository. It lives in ipfs/ecosystem-directory, which is maintained. Go there for anything to do with the real site, including adding a project.
What is left here is the abstracted, clone-and-reuse version, last worked on in early 2022. The Nuxt module it is built around, nuxt-module-ecosystem-directory, is archived as well, so expect to do some work before this builds.
The repository can be unarchived, but only for a named maintainer who commits to keeping it up. If that is you, reach out to the IPFS Foundation. Forking is fine too.
This is the Shipyard repo for the Interactive Ecosystem Directory and Showcase. This is an abstracted repo, intended to be cloned and re-used. It is builds into a static site with VueJS and Nuxt.
Just want to add a new project to an existing directory? Use these links
- Form to add a new project to the IPFS Ecosystem Directory**
- Form to add a new project to the Filecoin Ecosystem Directory**
Note: The workflows and docs below contain IPFS-specific links, examples and procedures, but also generally apply to any instantiation of this Ecosystem app.
The existing workflow for adding a project to the ecosystem directory, or amending an existing project, is as described below.
- Project info is added to the master IPFS project database in one of two ways:
- Directly in the base as a new row
- By requesting a project's representative fill in the IPFS Ecosystem Directory Submission Form
- Once a record is added to the database, an IPFS core team member reviews the record for accuracy, consistency, typos, etc, as well as determining whether the project should be included in the directory (a decision largely based on project maturity)
- If the project is approved to be included in the directory, directions for adding the data to the repo can be found here
- Project info should be amended in the master IPFS project database as a single source of truth
- From there, un-tick and re-tick the
Include in directory?box to regenerate the JSON - Replace the JSON and/or images in the repo as indicated in the instructions
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: The showcase grid is a general-purpose, useful grid if you don't want to build a custom one.
Demo link on the IPFS Ecosystem site.
- The showcase view is visible in its bare form at ecosystem.ipfs.tech/showcase
- It provides a logo-based visual summary of the projects in the app by category
- Each tag within the selected category is assigned a block
- The container for the tag is sized based on whether there's a small, medium, or large quantity of projects within it
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.
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.
mdminimum projects with a tag to display in a medium container (default is 10, if no value is provided)lgminimum projects with a tag to display in a large container ((default is 25, if no value is provided)
Example use case: /showcase/?category=focus&md=5&lg=15
Note: The Showcase view is designed to support rows of 5 logos, so setting
lgandmdas multiples of 5 is recommended for the ideal visual appearance.
- The showcase path may be redefined in the app's
settings.jsonunder the keyshowcaseBaseRoute- Currently implemented as:
"showcaseBaseRoute": "/showcase"
- Currently implemented as:
- The showcase has no links, and is not discoverable by search engines
This repo no longer deploys anywhere. It was wired to Fleek, with main
publishing to https://ecosystem.ipfs.tech/ and develop to
ipfs-ecosystem-develop.on.fleek.co. That site is now built from
ipfs/ecosystem-directory instead.
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
In a terminal, run the commands below to get set up
# Navigate to directory within which to clone the git repo. A new directory is created within this one called ecosystem-directory
$ 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@ipfs.io"
# Install npm dependencies
$ npm ciUsed 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.
- 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- Copy the new
localhost_cert.pemandlocalhost_key.pemfiles to the root directory of this repo - Start the server and navigate to
https://localhost:<your_port>
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
$ npm run devBelow is an outline of the project model. An empty JSON file can be found in @/content/projects/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.
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 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.
-
display: toggle whether or not to display or hide the project from the results -
featured: toggle whether this appears in the featured slider -
sortNumbers: these labels and numbers will be used in the sort-by filter -
logo: all logos will be in SVG format and must be placed in thestaticdirectory -
name: name of the product -
org: a product can belong to multiple organizations -
description: 2 descriptions are needed. A long description that will be visible on the Project Single page and a short description that is visible in the card format (such as the Featured slider). If none provided, a truncated version of the long description will be used. -
primaryLink: this is the 1st link found directly under the project description -
links: these links will always appear at the top of the Key Info section, however, these links could be extended to use elsewhere in the future -
keyInfo: these key/value pairs will always appear below the links in the Key Info section -
video: can be a URL to either a YouTube or Vimeo video, the video must be publicly accessible and embeddable -
stats: general statistics with short descriptions, also known as "big numbers" -
ctaCard: this card will always be displayed as the last block in the stats section. The button text can be changed in@/content/pages/project.json -
taxonomies: the taxonomies contain aslugthat will match a master taxonomy object (found in:@/content/pages/general.json); if none match, this taxonomy and its tags will not be displayed
The schema can be found in @/content/data/project-schema.js and must be updated if the schema ever changes. The $setProjectDefaults() global method (found in @/plugins/global-methods.js) uses project-schema.js 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]
}]
}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.
The primary source of truth for the Ecosystem Directory is the master IPFS project database, which has a field Include in directory? that indicates whether a project is ready for inclusion. A script has been added there, which converts that ecosystem entry to json, per the project model described. This script runs each time a project is checked for inclusion in the Ecosystem Directory.
Alternatively, any of the existing projects in content/projects can be copied, and the new json file can be altered to create a new project.
When either transferring or inputting a project from a copied json, the following process should be observed:
- Copy the generated JSON output
- Create a new file in
content/projects/.. with the project name inkebab-caseas the file name, (with a.jsonextension) - Make sure the project's contents look correct, and ideally ensure that
jsonformatting is preserved, including an empty line at the end of the file- Using a code editor's prettify function for
jsoncan correct this
- Using a code editor's prettify function for
- Download the images (icon and full logo) from the CRM or from the project organization, and place them in
static/images/projects/. - Ensure any of the
stats (also known as "big numbers") have the correct values, as the CRM script is not good at recognizing where to split the big number - Pull request the new projec(s) into the repository and use the build preview to see how it looks—or check locally
This process could be further automated with a variety of tooling at a later date.
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: {
debug: Boolean,
disableInDevelopment: Boolean,
suppressErrorLogs: Boolean
}
}Below is a breakdown of all events captured by Countly.
Countly.track_sessions()
Countly.track_pageview()
Countly.track_links()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 })Project card clicked
name: <project_name>
slug: <project_slug>
from: Home Page | Detail Page
Countly.trackEvent('Featured Slider | Project Card Clicked', { name, slug, from })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 })Links get automatically tracked by Countly.track_links()
Countly.trackEvent('404_NOT_FOUND', {
path: this.$route.path,
referrer: document.referrer
})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 })