Open-source project
asyncapi/website avatar
asyncapi/website

asyncapi-website: the Next.js site behind the AsyncAPI specification

AsyncAPI specification website

718 stars1,245 forksTypeScriptApache-2.0

At a glance

What is it?
The AsyncAPI website repository holds the sources of asyncapi.com, a Next.js and Tailwind site deployed on Netlify with Storybook for component work, a docs pipeline built from MDX, and translation support through next-i18next. It suits contributors who want to fix a page or write a post for the project that maintains the AsyncAPI specification, and the build is script-driven enough that most content changes never touch a React component.
Who is it for?
Adopt this repository only if you intend to contribute to the AsyncAPI project site, since it is the site and documentation, not a reusable component library.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The site, the specification and where the content actually lives

This repository contains the sources of the AsyncAPI website, and the stack behind it is stated plainly: it is powered by Next.js, it uses the Tailwind CSS framework, it is built and deployed with Netlify, and it uses Storybook as a frontend workshop and for documenting UI components.

AsyncAPI is a specification for event-driven architectures, and the site is where that specification is documented, explained and discussed. So this repository is two things at once, which is the main thing to understand about it. There is the marketing and community surface, the landing pages, the blog, the tooling directory, and there is the documentation itself, the docs directory with the tutorial and specification pages that people actually read when they are learning the format.

The content is not all in the repository as prose files, though. The package scripts show a generation pipeline. `build:pages` runs `tsx scripts/build-pages.ts` and then formats the MDX, `build:posts` runs `tsx scripts/index.ts`, and `build-scripts` chains the two together with the MDX lint. There are further generators for specific sections: `generate:meetings` for the meetings page, `generate:dashboard` for a dashboard build, `generate:videos` for newsroom videos, and `generate:tools` for the tools directory.

So a page is a Markdown or MDX file plus, in some cases, a script that produces it. The `build-scripts` step runs before both `dev` and `build`, which means the generated content is refreshed automatically whenever you start the dev server rather than being committed as a build artefact.

The site is deployed on Netlify, and there is a `netlify/` directory with its own tests, run through Deno, with the test command invoked over the netlify directory's test files.

Running it locally, and the Docker watch mode

The local run is a fork, a clone, an install and a dev command, and the README is explicit that the clone URL needs your own GitHub username in place of `<username>`. For multiple contributions it recommends proper configuration of the forked repo, with a link to the project's own git workflow guidelines.

The commands are:

bash
    git clone https://github.com/<username>/website/
    cd website
    npm install
    npm run dev

After that you access the live development server at localhost:3000. The Storybook runs separately with `npm run dev:storybook` on localhost:6006, and the package manifest confirms the port, since the storybook dev script is `storybook dev -p 6006`.

The requirements are Node.js v20.12.0 or newer and npm v10.5.0 or newer, and there is a `.nvmrc` at the repository root to pin the version.

The Docker route is the one to use if you would rather not have Node on your machine, and it uses compose watch mode:

bash
docker compose up --watch

The container is mapped with your local copy of the website, and whenever you make changes to the code the website refreshes and the changes are visible on localhost:3000. The compose file expresses that as a `develop.watch` block with two rules: the path `.` syncs into `/async` inside the container, and a change to `package.json` triggers a rebuild rather than a sync, which is the right behaviour since a dependency change invalidates the install.

The Dockerfile behind it is a development one, and it is simpler than you might expect. It starts from `node:18-alpine`, sets the workdir to `/async`, copies the manifest files and runs `npm install`, copies the rest of the application, exposes port 3000, sets `NODE_ENV=development` and ends with `npm run dev`.

That node 18 base image is the one inconsistency in the setup, since the requirements say Node 20.12.0 or newer. It works for the development container, but it is not what the stated requirement asks for, and it is worth knowing if you hit anything odd in the container that does not happen locally.

Building, linting and the difference between a site and a document pipeline

There are three build and lint commands, and the distinction between them matters because this is a content site as much as an application.

A production build is `npm run build`, and the generated files of the website go to the `.next` folder. The Storybook has its own build, `npm run build:storybook`, with the output going to the `storybook-static` folder. And there is a separate `npm run start`, which is `npx serve@latest out`, serving a directory called `out` rather than a Next.js server, which tells you the deployment target is a static export rather than a Node server.

The linting is split three ways, which is unusual and reflects the content types in the repository. `npm run lint` runs `next lint` over the TypeScript and React, and `npm run lint:fix` applies the fixes. `npm run lint:mdx` runs `remark` over the MDX files, and `npm run format:mdx` runs `prettier --write` over them. The MDX is a separate linting pipeline because the MDX files contain React components mixed with Markdown, and the Markdown linters do not know what to do with the components.

There is a longer list of checks beyond those, and it shows what the project considers a regression. `test:md` runs a Markdown checker, `test:editlinks` checks the edit links, `test:locales` checks the locales, and `test:netlify` runs the Deno tests over the netlify directory. `test` is `jest --passWithNoTests`, and `test:e2e` runs Cypress against Chrome.

There is also a `write:blog` command, which runs `tsx ./scripts/compose.ts` and follows an interactive prompt to generate a post with pre-filled front matter. That is a small piece of tooling aimed squarely at contributors, and it is the one command in the list that exists to save somebody time rather than to build something.

The blog, the meetings page, the newsroom videos and the tools directory each have their own generator script, and the docs pages are built by `scripts/build-pages.ts`.

Shared Markdown fragments and the finance pages that are plain YAML

Two content mechanisms sit underneath the site, and they are worth understanding because they determine where a change belongs.

The first is shared Markdown fragments. To minimise duplication of content and make it easier to maintain, there are shared fragments you can use when working with Markdown files, stored in the `/assets/docs/fragments` directory. You import a fragment at the top of the file, below the frontmatter, with a line like `import DesiredFragmentName from '@/assets/docs/fragments/fragmentYouWantToImport.md';`, and then you add it at the desired location with a component-style line, `<DesiredFragmentName />`.

The syntax is a JavaScript import in a Markdown file, which works because the files are MDX rather than plain Markdown. That is a design decision with a cost: the fragments cannot be used in a plain Markdown file, and any tooling that treats the docs directory as ordinary Markdown will not resolve the import.

The second mechanism is the opposite, and it is for the financial pages. The AsyncAPI Financial Summary page aims to provide transparency and clarity regarding the organisation's financial activities, serving as a platform to show how donations are accepted, what the sponsorship options are and how the generated funds are used. The YAML files must be stored in the `config/finance` directory, with separate folders for each year, such as `config/finance/2023`, and inside each year's folder two YAML files, `Expenses.yml` and `ExpensesLink.yml`.

The rule is precise: in `Expenses.yml` you record expenses for each month, specifying the `Category` and `Amount`, and in `ExpensesLink.yml` you provide discussion links related to expense categories. The repository root has a `config/` directory, and the structure is per year, so a new year means a new directory with the same two files.

This is a good example of a site where a small amount of structured data drives a public page, and of how a project keeps financial transparency for a non-profit without turning the numbers into hand-edited prose.

Against a documentation generator and against a static site generator

The comparison worth making is with the other two ways to build a specification site like this one.

A documentation generator such as Docusaurus, Slate or Redoc is the first alternative, and it is a strong one. Those tools give you versioning, a search index, a sidebar model, an edit-this-page flow and a theme, all of which are solved problems. What they cost is that the content lives in a structure the tool dictates, and the site you get looks like every other site built with it. AsyncAPI's site is a custom Next.js application, which means every page is bespoke, and it also means the sidebar, the search, the versioning and the navigation are all things the project has to build and maintain itself. The repository shows the scale of that: there is a `dashboard.json`, a `cheatsheet/` directory, a `templates/` directory and a `context/` directory, none of which a generator would ask you to create.

The second alternative is a static site generator such as Hugo or Eleventy, which is what many specification sites use. The difference is where the interactivity lives. Next.js gives this site a live web interface, a dashboard built from the `dashboard.json` data, a search integration and MDX components, all of which run in the browser. A static generator would have shipped the same content with less machinery, and would have given up the interactive parts.

The third option is a hosted documentation platform, which is what many projects actually choose because it removes the maintenance entirely. The trade is ownership: the AsyncAPI site carries the AsyncAPI brand, the tooling directory, the community pages and the financial summary, and all of that belongs with the project rather than with a vendor's template.

The cost of the custom route is visible in the repository, and it is not only complexity. The build has grown a long tail of generator scripts, a separate MDX linting pipeline, a Deno test suite for the Netlify functions and a Cypress end to end suite. Each of those exists because the site is a real application rather than a document tree, and the maintenance commitment is the ongoing cost of owning it.

Editorial conclusion

Adopt this repository only if you intend to contribute to the AsyncAPI project site, since it is the site and documentation, not a reusable component library. Do not expect to lift a design system out of it, because the icons live in a Figma design system rather than in a published package, and check first that your Node version meets the stated requirement of 20.12.0 or newer with npm 10.5.0 or newer, because the development Dockerfile still uses node 18 alpine and would not satisfy that.

Frequently asked questions

What is the asyncapi/website repository?

It contains the sources of the AsyncAPI website, the site and documentation for the AsyncAPI specification. It is powered by Next.js, uses the Tailwind CSS framework, is built and deployed with Netlify, and uses Storybook as a frontend workshop and for documenting UI components.

How do I run the AsyncAPI website locally?

Fork the repository, clone it with your own GitHub username in place of <username>, then run npm install and npm run dev, and the site is at localhost:3000. The Storybook runs separately with npm run dev:storybook on localhost:6006. You can also use docker compose up --watch, which syncs your local copy into the container and rebuilds when package.json changes.

What Node version does the AsyncAPI website need?

The README states Node.js v20.12.0 or newer and npm v10.5.0 or newer, and there is a .nvmrc at the repository root. The development Dockerfile in the repository still uses node 18 alpine as its base image.

How are the AsyncAPI docs pages generated?

The package scripts run a build-scripts step before both dev and build, which chains build:pages, running tsx scripts/build-pages.ts and then formatting the MDX, with build:posts running tsx scripts/index.ts. Separate generators exist for meetings, the dashboard, newsroom videos and the tools directory.

How do shared Markdown fragments work in the AsyncAPI docs?

Fragments live in the /assets/docs/fragments directory. A Markdown file imports one below its frontmatter with an import line pointing at the fragment path, and then places it with a component-style tag such as <DesiredFragmentName />.

Is the AsyncAPI website still being maintained?

The repository is not archived and the last push was on 2026-10-19. There are no GitHub releases, since deployment runs through Netlify, and the code is Apache-2.0 licensed.

Official sources

  1. asyncapi/website on GitHub
  2. Issues
  3. License: Apache-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/asyncapi-website.svg)](https://hysenlabs.com/projects/asyncapi-website)

Was this useful?