Documentation
Next.js

Next.js

This guide covers how to integrate React Cosmos with Next.js 13.4+. It includes support for React Server Components. The Cosmos Renderer switches seamlessly between Server and Client components in the same project.

Also check out react-cosmos/nextjs-example (opens in a new tab), which features both Server and Client fixtures of the glorious react-tweet (opens in a new tab) component.

Getting Started

Create a new Next.js project (opens in a new tab) or open an existing one.

Install the required packages:

npm i -D react-cosmos react-cosmos-next

Create cosmos.config.json and point rendererUrl to your renderer (we'll get to it in a moment):

cosmos.config.json
{
  "rendererUrl": {
    "dev": "http://localhost:3000/cosmos/<fixture>",
    "export": "/cosmos/<fixture>.html"
  }
}

Add cosmos and cosmos-export scripts to package.json:

package.json
"scripts": {
  "cosmos": "cosmos --expose-imports",
  "cosmos-export": "cosmos-export --expose-imports"
}

Create a basic fixture at src/Hello.fixture.jsx:

src/Hello.fixture.jsx
export default <h1>Hello World!</h1>;

If you're using TypeScript replace .jsx file extensions with .tsx.

Create a Next.js page at src/app/cosmos/[fixture]/page.tsx:

src/app/cosmos/[fixture]/page.tsx
import { nextCosmosPage, nextCosmosStaticParams } from 'react-cosmos-next';
import * as cosmosImports from '../../../../cosmos.imports';
 
export const generateStaticParams = nextCosmosStaticParams(cosmosImports);
 
export default nextCosmosPage(cosmosImports);

This is your Cosmos Renderer.

Start Next.js:

npm run dev

Start React Cosmos (in a 2nd terminal):

npm run cosmos

You'll notice cosmos.imports.js was generated. This module is a dependency of the Cosmos Renderer. The Cosmos Server updates this file automatically. You can add it to .gitignore.

🚀 Open localhost:5000 (opens in a new tab) in your browser.

That's it. You're now running Server fixtures in React Cosmos!

You can import both Server and Client components in your fixtures, which run on the server by default. You can also add the 'use client' directive to a fixture module (or decorator) if you want use Hooks inside it.

Limitations

  • Only Component Fixtures fixtures can be exported from a fixture module with the 'use client' descriptor. That's because Client fixture modules are passed as is to the Server render tree and their exports are expected to be components by design. While Node Fixtures and Multi-Fixtures cannot be used in Client fixtures, all Cosmos fixture formats are supported in Server fixtures.

Static Export

The cosmos-export command creates a static export of the Cosmos UI shell, which expects a corresponding static Renderer to connect with. Generating the complete export requires stringing a few simple commands together:

# Build Cosmos
npm run cosmos-export
# Build Next.js
npm run build
# Copy Next.js build into Cosmos export
cp -R ./out/_next ./cosmos-export
cp -R ./out/cosmos ./cosmos-export

At this point your static export is ready to be served:

npx http-server ./cosmos-export

👀 Live demo (opens in a new tab)

Further Integration

Separate React Cosmos from Next.js app

One approach for building Cosmos independently in a Next.js app is to organize the Cosmos component library as a separate project within a dedicated cosmos subfolder. Cosmos files will have access to the main app through the parent folder and it will only import necessary components.

You can take it a step further and deploy your app and Cosmos separately to two different vercel projects from the same codebase.

Check this repo for more information and an example of this setup: https://github.com/scorado-ltd/scorado-examples-nextjs-cosmos/tree/main (opens in a new tab)

On making a plugin (Next.js insider help needed)

Running Server Components in Cosmos is awesome but a plugin could take this integration to the next level (no pun intended).

Similar to the Vite and Webpack plugins, a Next.js plugin would:

  • Remove the need to wire up the Cosmos Renderer (the /cosmos page).
  • Hide the user module mappings (the cosmos.imports file generated with the --expose-imports flag).
  • Set the renderer URL automatically with no Cosmos config needed.
  • Support static exports out of the box with the cosmos-export command.

Making a Cosmos plugin is easy-peasy. Plugging into Next.js is the missing link for a seamless integration.

Ideally we would call the dev and build Next.js commands programatically. But I don't know if Next.js supports this at the moment. There is a Custom Server (opens in a new tab) API but I'm not sure if it works with the App Router architecture and the build part is missing.

In the meantime we can remove the /cosmos page from the out dir when deploying our app. Another option is a monorepo with a main Next.js app and a Cosmos Next.js app.

💡

If you or someone you know has Next.js expertise please don't be shy and reach out. Help is appreciated!