---
title: "Install in a Next.js app"
description: "Set up Systhema by hand in an existing Next.js App Router project."
requested_language: nl
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/nl/getting-started/installation/nextjs
version: unreleased (main)
docs_index: https://docs.systhema.app/nl/llms.txt
---
> This page isn't translated yet. Showing English.


These steps recreate the [Next.js template](https://docs.systhema.app/nl/getting-started/templates/nextjs.md) by hand. Follow them if you want to scaffold a new project with your own modifications, or if you want to understand how Systhema, Tailwind, and Next.js fit together.

## Prerequisites

- Node.js 20.9 or newer and pnpm 10.
- Registry access to the private `@systhemaui/*` packages. See [Registry access](https://docs.systhema.app/nl/getting-started/registry-access.md).
- Familiarity with the Next.js App Router.

## Steps

### 1. Scaffold the Next.js project

```bash
pnpm dlx create-next-app my-app --use-pnpm
cd my-app
```

Choose TypeScript, the `src/` directory and the App Router. You configure Tailwind CSS in the next steps.

### 2. Configure package registry access

Set up the `.npmrc` and `GITHUB_TOKEN` described in [Registry access](https://docs.systhema.app/nl/getting-started/registry-access.md) before installing.

### 3. Install Tailwind CSS

```bash
pnpm add tailwindcss @tailwindcss/postcss postcss
```

If Next.js doesn't already have one, create `postcss.config.js`:

```js title="postcss.config.js"
module.exports = {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}
```

### 4. Add Systhema packages

```bash
# Required.
pnpm add @systhemaui/core

# Components for React + Next.js.
pnpm add @systhemaui/react @systhemaui/next
```

### 5. Initialise Systhema configuration

```bash
pnpm exec systhema-core init --ts --react --postcss
```

Common flags:

- `--ts`, emit TypeScript versions of the config files.
- `--src`, place the Systhema config inside `src/`.
- `--react`, set `packages.react = true` so React/Next safelists are emitted.
- `--postcss`, also generate a PostCSS config.
- `--tw-legacy`, also create a legacy `tailwind.config.{js,ts}` (most projects don't need this).

The command produces `systhema.config.{js|ts}`.

The `--react` flag enables the component safelist. Preserve that setting when you connect your manifest below. See [systhema-core](https://docs.systhema.app/nl/cli/systhema-core.md) for the complete command reference.

### 6. Import Tailwind CSS via Systhema

Replace the default Tailwind import in your global stylesheet:

```diff
- @import 'tailwindcss';
+ @import '@systhemaui/core/tailwind';
```

> [!NOTE]
> With Tailwind v4 a `tailwind.config.*` is optional. If you don't generate one, you can skip the rest of this step.
>
> If you _do_ generate a config (e.g. `pnpm exec systhema-core init --ts --tw-legacy`), Tailwind v4 won't auto-detect it. Load it explicitly from CSS using `@config`.

For a legacy config, use the generated `tailwind.config.ts` and point `@config` at it relative to your stylesheet. See [Tailwind integration](https://docs.systhema.app/nl/styling/tailwind.md) for the canonical setup.

### 7. Save Systhema-exported design tokens

Place your exported token JSON files in `src/tokens/` (or another path; keep `systhema.config.*` consistent). Check the folder into source control so every environment has the same baseline.

### 8. Connect the token manifest

Add the manifest to the generated config and retain React support:

```ts title="systhema.config.ts"
import type { SysthemaConfig } from '@systhemaui/core'
import manifest from './src/tokens/manifest.json'

const config: SysthemaConfig = {
  manifest,
  packages: { react: true },
  optimization: process.env.NODE_ENV === 'production',
}

export default config
```

`optimization: true` enables the structural CSS passes in production. Name obfuscation is off by default. Use [Production CSS optimization](https://docs.systhema.app/nl/styling/optimization.md) for its configuration and restrictions; class obfuscation requires a fully prerendered site.

Wrap your existing Next.js config with the shipped integration:

```ts title="next.config.ts"
import type { NextConfig } from 'next'
import { withSysthema } from '@systhemaui/next/config'

const nextConfig: NextConfig = {}

export default withSysthema(nextConfig)
```

Merge your existing settings into `nextConfig`. This connects configured locales and the Server Action origin allowlist.

### 9. Sync tokens and generated assets

Run the sync command whenever tokens change, the config changes, or `@systhemaui/core` is updated:

```bash
pnpm systhema-core sync
```

This generates token artifacts, types, the safelist and agent references, then refreshes core's package cache.

> [!NOTE]
> Re-run this:
>
> - When the Systhema config changes.
> - When `@systhemaui/core` is upgraded.
> - On a fresh install (e.g. CI deploy).

### 10. Start building

```tsx title="src/app/page.tsx"
import { Article, Section, Button, Heading, Paragraph } from '@systhemaui/next'

export default function Home() {
  return (
    <main id="main-content">
      <Article theme="default" layoutBackground="main">
        <Section>
          <Heading.h1>Hello world</Heading.h1>
          <Paragraph type="lead">This is a paragraph.</Paragraph>
          <Paragraph>
            <Button.a href="/about" variant="primary">
              About us
            </Button.a>
          </Paragraph>
        </Section>
      </Article>
    </main>
  )
}
```

Don't forget to render `SysthemaProvider` in your root layout, it mounts the Next-aware listeners required for animations, parallax, and scroll classes:

```tsx title="src/app/layout.tsx"
import type { ReactNode } from 'react'
import { SysthemaProvider } from '@systhemaui/next'

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body data-theme="default" className="bg-layout-main">
        <a className="skip-link" href="#main-content">
          Skip to content
        </a>
        <SysthemaProvider>{children}</SysthemaProvider>
      </body>
    </html>
  )
}
```
