This repository contains the source code and assets for the Fleek.xyz website, which is built using the Astro.js framework for enhanced performance and speed. The project leverages Tailwind CSS for styling, providing a modern and responsive design, and TypeScript for type safety and scalability, ensuring a robust and maintainable codebase.
- Nodejs + Bun
- NPM, Yarn or PNPM
- Some experience with CLI
- Docker (optionally, if you want to run search server locally)
Learn how to install NodeJS in your operating system by following the instructions here and Bun here.
Install the project dependencies in your local environment.
npm install
Start a local HTTP server for development work. It supports hot-reload, so you'll be able to see your edits each time you save a file:
npm run dev
If you'll be interacting with services, you'll need to set up the environment variables.
Create a local file named .env
and declare the following
PUBLIC_MEILISEARCH_HOST=localhost:7700
PUBLIC_MEILISEARCH_INDEX_BLOG="fleekxyz_website_blog"
PUBLIC_MEILISEARCH_INDEX_DOCS="fleekxyz_website_docs"
PUBLIC_MEILISEARCH_INDEX_GUIDES="fleekxyz_website_guides"
PUBLIC_MEILISEARCH_INDEX_REFERENCES="fleekxyz_website_references"
PRIVATE_MEILISEARCH_MASTER_KEY=***
PRIVATE_MEILISEARCH_DOCUMENTS_ADMIN_API_KEY=***
PUBLIC_MEILISEARCH_DOCUMENTS_CLIENT_API_KEY=***
PUBLIC_SUPPORT_API_HOST="localhost:3331"
SUPPORT_ALLOW_ORIGIN_ADDR="http://localhost:4321,https://fleek-xyz-staging.on-fleek.app"
SUPPORT_RATE_LIMIT_WINDOW_MINUTES=60
SUPPORT_RATE_LIMIT_MAX_REQ=15
SUPPORT_RATE_LIMIT_PATHS="/tickets"
NODE_ENV=develop
π‘ The SUPPORT_ALLOW_ORIGIN_ADDR and SUPPORT_RATE_LIMIT_PATHS are comma separated values (csv). the MEILISEARCH_DOCUMENTS_CLIENT_API_KEY is required when querying staging, production environments which should be provided in the headers.
Run the build command to create the distribution version. The files will be saved in the /dist
directory by default.
npm run build
π‘ By default, the development server is available in the address http://localhost:4321.
Tweak environment settings (src/settings.json), such as the site URL. Declare the NODE_ENV
with value prod
or production
to switch environment target settings.
You can preview the distribution build locally by starting the preview HTTP server:
npm run preview
π‘ By default, the local site will be available in the address http://localhost:4322.
You can preview the develop branch version by visiting the preview here.
Code formatter is available by executing the command:
npm run fmt
Changes will be written in file. Alternatively, you can run a code format check by running a dry-run, which doesn't make changes in-file:
npm run fmt:check
Create branches from the develop
branch and name it in accordance with conventional commits here.
Here's an example:
test: π Adding missing tests
feat: πΈ A new feature
fix: π A bug fix
chore: π€ Build process or auxiliary tool changes
docs: βοΈ Documentation only changes
refactor: π‘ A code change that neither fixes a bug or adds a feature
style: π Markup, white-space, formatting, missing semi-colons...
Find more about contributing TODO:OPEN-SOURCE-CONTRIBUTION-DOC, please!
Instructions for common tasks.
A blog post is organized as a directory that should include all the necessary image assets.
The directory should be named after the slug, a system-friendly name, e.g. "My short title" would become "my-short-title". Additionally, the markdown filename containing all the text should be named as "index.md".
For example, let's assume the creation of an hypothetical blog post named "My Blog post".
1) Create the directory with corresponding slug "my-blog-post" in the src/content/blog
location, as follows:
src/content/blog/my-blog-post
src/content/blog/my-blog-post/index.md
The "index.md" is a markdown file where the text content and story is going to be stored.
---
title: My Blog post
slug: my-blog-post
category: Announcements
date: 2024-01-31
desc: A short description about my blog post
thumbnail: "./thumbnail.jpg"
image: "./main-image.jpg"
author: "Fleek"
---
---
title: My Blog post
slug: my-blog-post
category: Announcements
date: 2024-01-31
desc: A short description about my blog post
thumbnail: "./thumbnail.jpg"
image: "./main-image.jpg"
author: "Fleek"
---
Dive into a world of concise knowledge and thought-provoking ideas. Whether you're a seasoned reader or a curious newcomer, this blog post promises to captivate your mind and leave you pondering long after you've finished reading. So grab your favorite beverage, find a cozy spot, and let's explore together!
## My subtitle 1
In the world where text is text, I show you an image:
![My image](./my-image.jpg)
π‘ Would like to place static video content? Learn how to work with video content here.
Creating a document in the Docs section is similar to Blog.Learn how to create a document by using the instructions for blog.
Editing the menu and sidebar is crucial. These elements serve as the primary navigation for your visitors, guiding them through your content.
To reorder menu items, edit the docs -> menu -> order section in the settings file located in src/settings.json.
Here's an example where we order the categories accounts, projects and storage by naming the category name and order numerical value. If you don't order, the system will fallback to ordering it alphabetically or randomly.
"docs": {
"menu": {
"order": [
{
"category": "accounts",
"order": 1,
}, {
"category": "projects",
"order": 2,
}, {
"category": "Storage",
"order": 3,
}
]
}
}
π‘ In the example above, the categories are the "directory", while Content documents (.md files) have a numerical order value that is also computed when ordering the sidebar items. For example, the src/content/docs/index.md is the landing page document, while src/content/Accounts is a directory that has one or more markdown documents.
You can override the docs sidebar titles, but it's not recommended due to the way the content automation process generates the final URLs, etc. We should prefer convention over configuration!
Suppose that you have the directory names:
βββ CLI
βΒ Β βββ Applications
βΒ Β βββ verify-domain.png
βββ My-Menu-Item
βΒ Β βββ index.mdx
βΒ Β βββ Sites
βββ index.mdx
Let's say that you'd like to override the name "My-Menu-Item" to "Custom name".
You'd have to locate docs -> customTitlesByDirectoryName
field in the src/settings.json
file and declare a new property name and the value, e.g. "My-Menu-Item" and "Custom Name" as follows:
"docs": {
"menu": {
"customTitlesByDirectoryName": {
"My-Menu-Item": "Custom name"
}
}
}
This is not recommended because the final URL will contain the original directory name, e.g. https://fleek.xyz/docs/my-menu-item instead of https://fleek.xyz/docs/custom-name.
Considering the normalization conventions of the directory names, it'd be much preferred to rename the original directory to "custom_name".
βββ CLI
βΒ Β βββ Applications
βΒ Β βββ verify-domain.png
βββ Custom_name
βΒ Β βββ index.mdx
βΒ Β βββ Sites
βββ index.mdx
π‘ Bear in mind that underscores (_) are replaced by white-space when humanized by default. The dashes are kept to comply with terms or names, e.g. "pre-release".
You can create a PR (pull request) programmatically or by using the GitHub web interface.
In order to create a pull request (PR), you have to understand that the project has a file structure architecture, containing source-files for components, images, stylesheets and much more.
For our example we are going to create new content. The content is placed in the src/content
directory for blog or docs.
Here's how to create a new blog post content using the GitHub web interface:
src/content/blog
βββ announcements
βββ changelog-march-11
βΒ Β βββ fleekchangelog01mar11.png
βΒ Β βββ index.md
βββ fleek-release-notes-v004
βββ Log-in-connections.png
βββ fleekreleasenotes06.jpg
βββ index.md
4 directories, 5 files
Click on the file tree icon to expand it.
Once expanded you should see the file tree.
Click on the drop-down menu and type a new name. Make sure that you follow the naming conventions in the Contribution guidelines.
For example, in the image we see the creation of a branch named docs/my-new-branch
Click in the "Create branch docs/my-new-branch from develop".
To create a new directory in a repository click βcreate a new file.β Type your new directory's name in the area where you would write the file name, and at the end of the file name type a "/" to initialize it as a directory. After this you can create a new file in the directory.
Type the name "index.md" for the new filename.
Type a brief commit message following the Contribution guidelines, such as:
docs: βοΈ Created document in post directory
If you wish, you can add more details in the "Extended description".
Select the option "Commit directly to the docs/my-new-branch branch" and commit it by pressing "Commit changes".
In the right side of the window, locate the pencil icon and click it to start editing the file.
Add content to the file. For example, here we have put the markdown header and some text.
---
title: "Put a title here"
slug: "put-a-title-here"
category: "Name of category"
date: 2024-03-11
desc: "A short description"
thumbnail: "./a-local-image.png"
image: "./a-local-image.png"
author: "Your name"
---
The content goes here
Learn more by reading the New post section.
Every time there's a new change, you can commit it. It'll store the changes in the repository branch you have created.
You can create a pull request by visiting the compare.
Use the second drop box to select the branch name you have just created for your post content.
Press the "Create pull request" and fill up the following fields by providing a title for your pull request and a description.
To complete select "Create pull request".
You can release to production following a linear strategy. This assumes that the convention "main" branch is of linear history and is a subset of the "develop" branch commit history. For example, the team is happy to have "develop" as where the latest version of the project exists, that "main" shouldn't diverge and only contain commits from "develop".
Use-case examples:
- The team has merged some feature branches into develop identified as commit hash "abc123" and want to release upto to the commit history hash "abc123" onto "main". By doing this they expect the build process to occur and deploy into the Fleek Platform
- The team has merged several feature branches into develop identified as commit hashes
commitFeat1
,commitFeat2
andcommitFeat3
by this historical order. It's decided to release everything in commit history untilcommitFeat1
, but notcommitFeat2
andcommitFeat3
. Although, it'd be wiser to keep the feature branches in pending state as "develop" should always be in a ready state for testing and release as the team may want to release some quick hotfixes, etc
To release to production open the actions tab here.
Select the "π Release by develop hash" job in the left sidebar. Next, select the "Run workflow" drop-down and provide the required details.
A spell checker will verify the markdown (.md, .mdx) file content for any typos. The spell checker is an automated process that is active during the pull request (PR).
Find the spell checker among other checks, under the checks component at the very bottom of the conversation tab, in the Github pull request (PR) dashboard. To learn more about the spell check process, open "details".
It should be similar to the following:
The Announcement Marquee is placed at the very top of the site. To enable
- Open the settings file located at
/src/settings.json
. - Locate the
announcementMarquee
under "site"
"site": {
...
"annoucementMarquee": {
"message": "Introducing Fleek Functions: lightning-fast edge functions built on Fleek Networkβs onchain cloud infrastructure. Read more here.",
"url": "/blog/announcements/introducing-fleek-functions",
"visible": true
},
...
}
- Edit the message and url
- Set "visible" to true
The concept of admonitions is often used in documentation and content creation to highlight important notes, warnings, tips, or other types of information in a distinctive way.
Here's the syntax to create admonitions in markdown content, such as a docs post:
:::note
This is a note
:::
:::success
This is a success
:::
:::warn
This is a warning
:::
:::danger
This is a danger
:::
:::info
This is a info
:::
To learn more read the directives here
The main Navigation bar can be configured by editing the file located in src/components/NavBar/config.ts.
Each menu item is represented by an object with the following properties:
- label: A string that defines the text displayed for the menu item.
- url: A string that specifies the URL to navigate to when the menu item is clicked.
- open in new tab (optional): A boolean value (true or false) that determines whether the link should open in a new browser tab.
Example of a basic menu item:
{
"label": "Blog",
"url": "/blog",
"openInNewTab": true
}
For more complex menus, you can include submenus. A submenu is defined by an object with a label and an items array, which contains a list of menu items.
Example of a menu item with a submenu:
{
"label": "Products",
"items": [
{
"label": "Product A",
"url": "/products/a"
},
{
"label": "Product B",
"url": "/products/b"
}
]
}
The menu configuration is divided into two main sections: main and side. Both sections are arrays that contain objects representing menu categories. Each category object can have a label and an items array, similar to the submenu example above.
- main: This section is for the primary menu items. It's an array of category objects.
- side (optional): This section is for secondary or additional menu items. It follows the same structure as the main section.
Example of a menu configuration with both main and side sections:
{
"main": [
{
"label": "Products",
"items": [
{
"label": "About Us",
"url": "/about"
}
]
},
{
"label": "Resources",
"items": [
{
"label": "Templates",
"url": "/templates"
}
],
},
],
"side": [
{
"label": "Protocols",
"items": [
{
"label": "Fleek Network",
"url": "https://fleek.network",
"openInNewTab": true,
}
]
}
]
}
In addition to the main and side menus, you can define a list of Call to Action (CTA) items. These are typically used for promotional or important actions. Each CTA is an object with a label and a url.
Example of a CTA configuration:
{
"ctas": [
{
"label": "Sign Up",
"url": "/signup"
}
]
}
When configuring your menu, ensure that the structure and properties of your objects match the guidelines provided. This will help maintain consistency and ensure that your menu is displayed correctly. Remember, the appearance of your menu is limited by the styles or components you use, so adjust your configuration or business logic accordingly.
Metadata is important for search engines, social media platforms, and others to understand the content and purpose of a page.
The main location for the metadata is in the head element of the main base layout for our pages. At time of writing, is located as BaseHtml.astro
in the src/layouts
:
src/layouts
βββ ...
βββ BaseHtml.astro
You'll find the elements in the HEAD section of the HTML document. For example:
...
<head>
...
<meta property="og:url" content={`${baseUrl}/${ogMeta?.slug || ''}`} />
<meta property="og:type" content="website" />
<meta
property="og:title"
content={ogMeta?.title || settings.site.metadata.title}
/>
...
<meta
name="twitter:title"
content={ogMeta?.title || settings.site.metadata.title}
/>
...
</head>
One of the key components of HTML metadata is the Open Graph meta tags originally created by Facebook to enable them to become rich objects in a social graph.
By using Open Graph meta tags, you can control how your website's links appear when shared on social media platforms such as Facebook, Twitter, LinkedIn, and others.
To discover how the site page's are perceived by social media platforms use a meta tag previewer.
For example, let's say that you want to preview the Blog post for "Introducing Fleek Functions". You'd copy the URL https://fleek.xyz/blog/announcements/introducing-fleek-functions and paste it in the previewer address of your preference, e.g., opengraph.xyz.
It's important to note that if you encounter issues with Open Graph meta tags not displaying correctly on a platform, the first step should be to utilize a validator tool, similar to the one provided in the URL above. This is because our system automatically provides the metadata content, but discrepancies may arise if certain requirements are overlooked by the platform, e.g., persistent cache. Additionally, if a specific URL encounters problems due to previous issues, you can circumvent caching by appending a query parameter to the end of the URL. For example, modifying https://fleek.xyz/blog/announcements/introducing-fleek-functions to https://fleek.xyz/blog/announcements/introducing-fleek-functions?202406101836. This method is recommended as a preliminary troubleshooting step to identify the source of the problem.
You can customize the Blog category list page metadata fields by editing the settings file in [./src/settings.json].
"blog": {
...
"category": {
"category-name-here": {
"title": "My title",
"description": "My description"
}
}
You can extend the category field with any category name. Notice that category names should match the system name or directory name, e.g. announcements.
"blog": {
...
"category": {
"announcements": {
"title": "Announcements",
"description": "The announcements description"
}
}
The project services have the following naming convention:
<service-type>-<environment>-<region>-<instance-number>.<domain>
Support's based in ZenDesk, as an external provider that provides an API to interact with the service. The following documentation provides information to interact with the proxy server.
The application should get the endpoint URL from an environment variable named PUBLIC_SUPPORT_API_HOST
.
Learn how to setup by reading the section environment variables.
The environment should have the following variables set up for the corresponding account.
You may want to create a .env
file to hold these environment variables, or in your shell profile.
PRIVATE_ZENDESK_EMAIL="xxxx"
PRIVATE_ZENDESK_API_KEY="xxxx"
PRIVATE_ZENDESK_HOSTNAME="xxxx"
A proxy service to interact with ZenDesk is available and can be run locally.
Start the local API by running:
npm run support:local_api
π‘ During implementation the API URL should be provided as an environment variable.
/health
Hit the /health endpoint for health checks
curl -X GET 'localhost:3331/health
/ticket
Hit the /ticket endpoint to create a ticket for a user email, particular topic and comment query.
curl \
-X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "email=<CLIENT-EMAIL-ADDRESS>&subject=<SYSTEM-TOPIC>&comment=<USER-QUERY>"" http://localhost:3331/ticket
The email is a valid email address, the topic should be related to the query template. The query should correspond and be of a well-known format or template.
Here's an example for query template:
subject: <System Support Topic> | <User title>
description: <User text>
attachments: <User attachments>
A result ticket could look like:
subject: Billing | Inquiry Regarding Unprocessed USDC Token Transfer
description: Dear Fleek, I hope this message finds you well. I am writing to seek clarification regarding an outstanding transaction related to my account. On xxx, I initiated a transfer of xxx USDC tokens from my account to xxx. However, upon checking my transaction history, it appears that this transfer has not been processed.
attachments: https://fleek-storage/user-file.png
The support service hostname is support-prod-eu-lon-1-01.flkservices.io
(endpoint URL).
The production environment variable should be set. Declare the hostname:
PUBLIC_SUPPORT_API_HOST="https://support-prod-eu-lon-1-01.flkservices.io"
The default location of the service file is /lib/systemd/system/support-prod-eu-lon-1-01.flkservices.io.service
.
To configure Support with environment variables in a cloud-hosted instance, modify the Support's env file. Its default location is ~/fleek-platform/website/.env
.
After editing your configuration options, reload the daemon:
sudo systemctl daemon-reload
Restart the service:
sudo systemctl restart support-prod-eu-lon-1-01.flkservices.io.service
Check the status:
sudo systemctl status support-prod-eu-lon-1-01.flkservices.io.service
The search service is based on Meilisearch here.
The search service hostname is meilisearch-prod-eu-lon-1-01.flkservices.io
. The default location of the service file is /etc/systemd/system/meilisearch.service
.
To configure Meilisearch with environment variables in a cloud-hosted instance, modify Meilisearch's env file. Its default location is /var/opt/meilisearch/env
.
DNS Record
A meilisearch-prod-eu-lon-1-01.flkservices.io 165.232.41.164
After editing your configuration options, relaunch the Meilisearch service:
systemctl restart meilisearch
curl \
-X GET 'http://localhost:7700/health'
Otherwise:
curl \
-X GET '<PROTOCOL>://<ADDRESS>:<PORT>/health'
The Indexer's job referred to as indexation is the process of organizing and storing data in a structured manner to facilitate efficient search and retrieval.
If you're running the search server via Docker container, data has to be indexed.
Provide data by running the command:
npm run search:index_all
A quick way to query the server is by using cURL.
In the following example, we query changelogs in the index name blog, on the local server, running on port 7700.
curl "localhost:7700/indexes/blog/search?q=changelogs"
Otherwise, for production server:
curl \
-X POST '<PROTOCOL>://<ADDRESS>:<PORT>/indexes/<INDEX_NAME>/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <API_KEY>' \
--data-binary '{ "q": "<SEARCH_QUERY>" }'
Here's an example of how to perform multiple search queries on one or more indexes:
curl \
-X POST 'http://localhost:7700/multi-search' \
-H 'Content-Type: application/json' \
--data-binary '{
"queries": [
{
"indexUid": "fleekxyz_website_docs",
"q": "something",
"limit": 5
},
{
"indexUid": "fleekxyz_website_guides",
"q": "something",
"limit": 5
},
{
"indexUid": "fleekxyz_website_references",
"q": "something",
"limit": 5
}
]
}'
Delete Index data by running the command:
npm run search:delete_indexes
Search is provided by Meilisearch. The local search server is provided as a Docker image, which you have to have installed and running.
You can start a server locally by running the command:
npm run search:serve
search:serve
script to include it.
The indexation service should trigger on push
to main
branch. Alternatively, the repo admin can trigger the job manually.
-
Open the Job runner here
-
Locate the row "This workflow has a workflow_dispatch event trigger." and open the Run workflow dropdown. In the option "Use workflow from" select
main
branch.
The Job will index data that exists in the selected main
branch. Learn how to release to production (main branch) here.
The build process can optimize the images but that requires the user to use the correct image components. Use the instructions provided to optimize the images.
For astro components (.astro) do:
---
import { Image } from 'astro:assets';
import localBirdImage from '../../images/subfolder/localBirdImage.png';
---
<Image src={localBirdImage} alt="A bird sitting on a nest of eggs." />
To learn more read here
Local images are kept in src/images
when possible so that the build process can transform, optimize and bundle them. Files in the /public
directory are always served or copied into the build folder as-is, with no processing.
When importing images, you have to provide query parameters such as width, height and format. This settings are used by the build process to generate optimized images. Also, the optimizer doesn't have support for Typescript, meaning that you have to use the // @ts-ignore
to ignore the import line.
The import name convention is camel-case and to use the prefix img, e.g. imgMyImage.
// @ts-ignore
import imgFleekLogo from "@images/globe-with-bolt.jpg?w=480&h=480&format=webp";
Place the image in the source field:
<img src={imgFleekLogo} alt="Image text replacement" />
To generate responsive images, e.g. SrcSet:
// @ts-ignore
import avif from '@images/example.jpg?w=500;900;1200&format=avif&as=srcset'
// @ts-ignore
import webp from '@images/example.jpg?w=500;900;1200&format=webp&as=srcset'
// @ts-ignore
import fallback from 'example.jpg?w=700'
const html = `<picture>
<source srcset="${avif}" type="image/avif" />
<source srcset="${webp}" type="image/webp" />
<img src="${fallback}" />
</picture>
`
Learn more here
This section provides detailed instructions on how to execute the script for migrating markdown files from one location to another. The script is designed to organize markdown files into a structured directory based on their category, extracted from the file content.
To execute the script, you need to pass two parameter arguments: the origin path and the target path. The origin path is where your source markdown files are located, and the target path is where you want the migrated files to be placed.
Example usage:
./scripts/migration/blog_content_from_gatsby \
../gatsby-blog/src/posts/post \
./src/content/blog
Custom data is available as static data. The data is provided by a static file endpoint, placed inside the /api
directory.
Note that the custom data is static, as the project is fully static (it means that the data is computed ahead of time and not dynamically on runtime), but can be utilized by external applications as any other endpoint. For example, the Fleek Platform application dashboard requires the latest blog posts data.
Make a HTTP GET request to the path /api/latestBlogposts.json
for the target environment, e.g. production as https://fleek.xyz
.
In the example we make a HTTP GET request and parse the body text as JSON data.
const res = await fetch('https://fleek.xyz/api/latestBlogPosts.json');
const json = await res.json();
console.log(json);
You'd get a list to iterate over as the following:
{
data: [
{
date: "1972-01-01",
path: "/blog/my-category/my-blog-post-1",
title: "My title 1",
description: "My description 1"
slug: "my-title-1"
},
{
date: "1972-01-02",
path: "/blog/my-category/my-blog-post-2",
title: "My title 2"
description: "My description 2"
slug: "my-title-2"
},
...
]
}
Everytime a build happens, the static JSON data should be updated.
Place video content relative to the content. We must keep it in context of the content due to portability. At time of writing, Astro doesn't optimize video and suggests placing these in the public directory which would break the portability requirement.
π‘ Video should be web optimized. Keep it short. At time of writing the maximum video file size is 6 MB. If lengthy, it's much preferred to distribute it on YouTube or similar.
To mitigate it, the Fleek Website build process includes handling of video files (mp4). It copies the content into the distribution directory to allow us to access it relatively. It doesn't optimize the files, thus video files should be web encoded by the author. For example, if you are on MacOS use Handbrake to optimize the videos, or ffmpeg for any operating system.
A video can be declared in the markdown as follows:
<video width="100%" height="auto" autoplay loop>
<source src="./ens_automatic_setup.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
π‘ Including a ./
, which means relative to the current file, the path will be replaced by its absolute pathname.
When visiting the site content, the file will be surfaced absolutely, e.g. <source src="https://fleek.xyz/blog/announcements/fleek-release-notes-v004/ens_automatic_setup.mp4" type="video/mp4">
.
<video width="100%" height="auto" autoplay loop>
<source src="ens_automatic_setup.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
β If missing a trailing slash it'll look for the file in the wrong location. At time of writing, trailing slash is not required to resolve the site sections, thus its best practice to declare the file location with ./
as in <source src="./my-video-filename.mp4">
to avoid confusion.
π‘ At time of writing its assumed that video files are put in the directory of a markdown file named index.md(x)
, e.g. src/content/guides/my-guide/index.md
and src/content/guides/my-guide/my-video.mp4
. It's also expected that the base path is the directory of the content and not cross content. It's important to respect the convention for portability, otherwise you'll find unexpected results.
The repositories contain a CHANGELOG.md
file, which is generated automatically. Find the files in the root of the repositories, for example for @fleek-platform/cli:
- SDK changelog