Install in a Next.js app
Set up Systhema by hand in an existing Next.js App Router project.
On this page
These steps recreate the Next.js template 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.
PrerequisitesLink to this section
- Node.js 20.9 or newer and pnpm 10.
- Registry access to the private
@systhemaui/*packages. See Registry access. - Familiarity with the Next.js App Router.
StepsLink to this section
1. Scaffold the Next.js projectLink to this section
pnpm dlx create-next-app my-app --use-pnpm
cd my-appChoose TypeScript, the src/ directory and the App Router. You configure Tailwind CSS in the next steps.
2. Configure package registry accessLink to this section
Set up the .npmrc and GITHUB_TOKEN described in Registry access before installing.
3. Install Tailwind CSSLink to this section
pnpm add tailwindcss @tailwindcss/postcss postcssIf Next.js doesn't already have one, create postcss.config.js:
module.exports = {
plugins: {
'@tailwindcss/postcss': {},
},
}4. Add Systhema packagesLink to this section
# Required.
pnpm add @systhemaui/core
# Components for React + Next.js.
pnpm add @systhemaui/react @systhemaui/next5. Initialise Systhema configurationLink to this section
pnpm exec systhema-core init --ts --react --postcssCommon flags:
--ts, emit TypeScript versions of the config files.--src, place the Systhema config insidesrc/.--react, setpackages.react = trueso React/Next safelists are emitted.--postcss, also generate a PostCSS config.--tw-legacy, also create a legacytailwind.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 for the complete command reference.
6. Import Tailwind CSS via SysthemaLink to this section
Replace the default Tailwind import in your global stylesheet:
- @import 'tailwindcss';
+ @import '@systhemaui/core/tailwind';For a legacy config, use the generated tailwind.config.ts and point @config at it relative to your stylesheet. See Tailwind integration for the canonical setup.
7. Save Systhema-exported design tokensLink to this section
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 manifestLink to this section
Add the manifest to the generated config and retain React support:
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 configoptimization: true enables the structural CSS passes in production. Name obfuscation is off by default. Use Production CSS optimization for its configuration and restrictions; class obfuscation requires a fully prerendered site.
Wrap your existing Next.js config with the shipped integration:
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 assetsLink to this section
Run the sync command whenever tokens change, the config changes, or @systhemaui/core is updated:
pnpm systhema-core syncThis generates token artifacts, types, the safelist and agent references, then refreshes core's package cache.
10. Start buildingLink to this section
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:
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>
)
}