Install in a Payload project
Add Systhema to an existing Payload and Next.js project, then generate its routes and artifacts.
On this page
Use this guide for an existing Payload App Router project. For a new site, the Payload template configures the adapters and scripts for you.
PrerequisitesLink to this section
- Node.js 20.9 or newer and pnpm 10. The global CLI needs Node.js 22 or newer.
- Registry access.
- An existing Payload app with a working database adapter.
- A clean branch and backups of any existing content.
StepsLink to this section
1. Install the packagesLink to this section
pnpm add @systhemaui/core @systhemaui/react @systhemaui/next @systhemaui/payload
pnpm add -D tailwindcss @tailwindcss/postcss postcss
pnpm add -D @payloadcms/next @payloadcms/plugin-nested-docs \
@payloadcms/plugin-redirects @payloadcms/plugin-seo \
@payloadcms/richtext-lexical @payloadcms/ui
pnpm add @payloadcms/plugin-import-exportRetain your existing payload, database adapter, graphql, sharp, Next.js and React dependencies. Keep all Payload packages on the same supported version. See Payload installation for the peer requirements and Lexical patch setup. Do not remove existing collections or frontend routes before reviewing how they will be integrated.
2. Add design inputs and configurationLink to this section
Place your exported tokens and manifest.json in src/tokens/. Use Figma export or Systhema Design.
For an existing app, generate only the core config first:
pnpm exec systhema-core init --ts --react --postcssThe --payload shortcut also creates Payload config and routes and cleans default files. Use it only when you have reviewed those writes. This procedure integrates your existing app explicitly instead.
import type { SysthemaConfig } from '@systhemaui/core'
import manifest from './src/tokens/manifest.json'
const config: SysthemaConfig = {
manifest,
packages: { react: true, payload: true },
optimization: process.env.NODE_ENV === 'production',
}
export default configImport Systhema's Tailwind entry from your public stylesheet:
@import '@systhemaui/core/tailwind';This minimal config uses the default spacing rules. If you adopt the starter's fluid %screen% rule, retain its companion wide-screen overrides. See Responsive sizing and Production CSS optimization.
3. Wrap the Payload configLink to this section
The following complete example uses SQLite. Keep your existing adapter if it differs:
import { sqliteAdapter } from '@payloadcms/db-sqlite'
import { buildConfig } from 'payload'
import { withSysthema, type SysthemaPayloadPluginOptions } from '@systhemaui/payload'
import systhemaConfig from '../systhema.config'
const userSysthemaConfig: SysthemaPayloadPluginOptions = {
locales: systhemaConfig.locales,
livePreview: { mode: 'client' },
}
export default buildConfig(
withSysthema(
{
secret: process.env.PAYLOAD_SECRET || '',
db: sqliteAdapter({ client: { url: process.env.DATABASE_URI || '' } }),
},
userSysthemaConfig,
),
)Set real PAYLOAD_SECRET, SYSTHEMA_API_SECRET, DATABASE_URI, NEXT_PUBLIC_SERVER_URL and APP_ENVIRONMENT values in your environment. Keep secrets out of version control. Do not replace the database adapter to move content; that requires a separate data migration.
withSysthema builds its own collections and globals. Move your existing custom definitions into customCollections and customGlobals, and review their access rules. Preserve existing storage, email and other plugins in the base config. Use withSysthema and Plugin options for the full contract.
Wrap your existing Next.js config as well:
import type { NextConfig } from 'next'
import { withPayload } from '@payloadcms/next/withPayload'
import { withSysthema } from '@systhemaui/next/config'
const nextConfig: NextConfig = {}
export default withPayload(withSysthema(nextConfig), { devBundleServerPackages: false })Merge your current Next.js settings into nextConfig. Keep the TypeScript @payload-config alias pointing at src/payload.config.ts.
4. Generate the public routesLink to this section
Review Project structure, then:
pnpm exec systhema-core payload create-app-filesThis supplies the public shell, CMS catch-all, sitemap, gateway and missing Payload route group. Existing scaffold files are preserved. Review the generated files and resolve any collisions with your existing routes, especially the home page and /robots.txt.
Configure your branding and fonts in src/app/(site)/template.tsx. It uses Payload's RootLayout, RootHeader and RootFooter; retain its provider and consent wiring. Keep code-owned routes outside (systhema).
5. Add scripts and syncLink to this section
Merge these scripts into your existing package.json:
{
"scripts": {
"sync": "systhema-core sync && payload generate:types && payload generate:importmap",
"generate:types": "payload generate:types",
"generate:importmap": "payload generate:importmap"
}
}pnpm sync
pnpm exec tsc --noEmitBefore starting against existing data, follow Database migrations. Adding Systhema collections changes the schema.
Moving a customised robots.ts to the route handlerLink to this section
Older projects can have src/app/robots.ts instead of src/app/robots.txt/route.ts. The host-aware-robots codemod migrates an unchanged scaffold; it preserves a customized file for you to review.
- Create
src/app/robots.txt/route.tsfrom the current Payload starter, for example from a separate project scaffolded withsysthema create --template payload. - Port your existing Allow and Disallow rules into its
bodyarray. - Delete
src/app/robots.tsafter transferring those rules. Both files resolve to/robots.txt; do not keep both.
Retain export const dynamic = 'force-dynamic' and resolveSysthemaPublicOrigin(request) from @systhemaui/next/origin. The helper accepts only the configured public origin or locale domains; do not build a cached Sitemap directive from an unvalidated Host header. Keep the environment check that blocks indexing outside production.
The robots-host-allowlist codemod replaces the old header-derived origin in an unchanged route and reports a customized route for manual review. See Deploying for environment and caching behavior.
VerifyLink to this section
Start with your existing development script. Confirm /admin, create or select a homepage in General Settings, and verify the published page while signed out. Test unsaved live preview separately; custom blocks need client registration.
Use Forms, SEO, Localization and Cookie consent to configure those features. Follow Deploying before launch.