Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/alineacms/alinea/llms.txt

Use this file to discover all available pages before exploring further.

Alinea integrates with Next.js through three exports from alinea/next: createCMS wraps your config into a Next.js-aware CMS instance, createHandler produces a single request handler function that you assign to the App Router GET and POST exports, and withAlinea patches your Next.js config to wire up dashboard routing. Together these three pieces are everything you need to run the Alinea editor alongside your application.

createCMS

createCMS accepts the same Config object documented in the configuration section and returns a NextCMS instance. NextCMS extends the base CMS class with Next.js-specific behaviour: it reads draft-mode cookies, uses the bundled local database during production builds, and exposes a previews() helper for rendering the floating preview widget. Place your CMS config in a dedicated file (conventionally src/cms.ts or src/cms.tsx) that can be imported by both your application code and the API route.
src/cms.ts
import {Config} from 'alinea'
import {createCMS} from 'alinea/next'
import * as schema from './schema'

export const cms = createCMS({
  schema,
  handlerUrl: '/api/cms',
  baseUrl: {
    development: 'http://localhost:3000',
    production: 'https://example.com'
  },
  preview: true,
  enableDrafts: true,
  workspaces: {
    main: Config.workspace('Main', {
      source: 'content',
      mediaDir: 'public',
      roots: {
        pages: Config.root('Pages', {
          contains: [schema.Page]
        }),
        media: Config.media()
      }
    })
  }
})
The handlerUrl in your CMS config must match the path where you mount the route handler. The default value is /api/cms. If you change one, change the other — a mismatch causes a 400 error at runtime.

createHandler

createHandler creates the standard Next.js App Router route handler for the Alinea editing API. It returns a single Handler function (request: Request) => Promise<Response> that handles both GET and POST requests. Create an API route at app/api/cms/route.ts (or wherever handlerUrl points) and assign the handler to both named exports:
app/api/cms/route.ts
import {cms} from '@/cms'
import {createHandler} from 'alinea/next'

const handler = createHandler({cms})

export const GET = handler
export const POST = handler
createHandler accepts either a NextCMS instance directly (shorthand) or a NextHandlerOptions object:
cms
NextCMS
required
The NextCMS instance created by createCMS. This is the only required field.
backend
BackendOptions
Optional self-hosted backend configuration. Provide this when you want Alinea to commit content directly to GitHub and store drafts in your own database, instead of routing through Alinea Cloud. See the Backend Options page for the full shape of this object.
remote
(context: RequestContext) => RemoteConnection
A factory function that receives the current request context and returns a custom RemoteConnection. Use this for advanced scenarios where neither Cloud nor the built-in GitHub backend fits. When omitted and no backend is provided, CloudRemote is used automatically.
beforeCreate
(entry: Entry) => Entry | void | Promise<Entry | void>
Called before a new entry is created. Return a modified entry to override it, or throw to abort the operation.
afterCreate
(entry: Entry) => void | Promise<void>
Called after a new entry is successfully created. Use for side effects.
beforeUpdate
(entry: Entry) => Entry | void | Promise<Entry | void>
Called before an existing entry is updated. Return a modified entry to override it, or throw to abort.
afterUpdate
(entry: Entry) => void | Promise<void>
Called after an entry is successfully updated. Use for side effects.
beforeArchive
(entryId: string) => void | Promise<void>
Called before an entry is archived. Throw to abort the operation.
afterArchive
(entryId: string) => void | Promise<void>
Called after an entry is successfully archived.
beforeRemove
(entryId: string) => void | Promise<void>
Called before an entry is permanently removed. Throw to abort.
afterRemove
(entryId: string) => void | Promise<void>
Called after an entry is permanently removed.

Handler behaviour

The handler performs two special tasks beyond forwarding API calls to the backend:
  1. Preview redirect — When a request arrives with a ?preview=<token> query parameter, the handler verifies the JWT, enables Next.js Draft Mode, and redirects to the target URL. This is the entry point for the iframe preview flow.
  2. Path enforcement — Requests whose path does not start with handlerUrl receive a 400 response immediately.

withAlinea

Wrap your next.config.ts export with withAlinea to enable dashboard routing:
next.config.ts
import {withAlinea} from 'alinea/next'

export default withAlinea()
You can pass your existing Next.js config as the first argument — withAlinea merges its additions non-destructively:
next.config.ts
import {withAlinea} from 'alinea/next'
import type {NextConfig} from 'next'

const config: NextConfig = {
  // your existing options
}

export default withAlinea(config)
withAlinea makes the following changes to your config:
  • Rewrites — In production, adds a rewrite so that a request to the dashboard path is served from the pre-built admin.html static file. In development, the request is proxied to the Alinea dev server.
  • Remote patterns — Adds uploads.alinea.cloud to images.remotePatterns so Next.js Image serves cloud-hosted media.
  • Server external packages — Marks @alinea/generated as a server external package (serverExternalPackages on Next 15+, serverComponentsExternalPackages on Next 14).
The dashboard path (defaulting to /admin) is read automatically from the generated @alinea/generated/settings.json file produced by alinea build. If the file is not present, dashboard routing is disabled and a warning is logged. You cannot override the dashboard path by passing an option to withAlinea — it is always derived from the generated settings.

Environment variables

VariableDescription
ALINEA_API_KEYYour Alinea Cloud project key. Used to authenticate the handler with Alinea Cloud. In development, Alinea falls back to "dev" when this is unset. Set it in production to connect to your Cloud project.
ALINEA_DEV_SERVERSet automatically by the Alinea CLI in development; proxies dashboard asset requests to the local dev server. Do not set manually.
Always run alinea build (or npx alinea build) before next build in your CI pipeline. Alinea build generates the @alinea/generated package that contains the bundled content database and dashboard settings that Next.js needs at build time and in production.

Build docs developers (and LLMs) love