Deploying
Deploying an Alinea site means deploying your Next.js app. In production the dashboard is served by your site on /admin, and your handler route saves the editors' changes as commits to your git repository. To do that it needs a backend that signs users in and talks to your repository: Alinea Cloud or your own.
Prepare your project
Config
Tell Alinea where your site lives, where the handler is and on which path the dashboard is served, in your CMS config:
import {createCMS} from 'alinea/next'
export const cms = createCMS({
// schema and workspaces ...
baseUrl: {
development: 'http://localhost:3000',
production: 'https://example.com'
},
handlerUrl: '/api/cms',
adminPath: '/admin'
})baseUrl.production is required: the handler URL is resolved against it. Your config is also bundled into the dashboard, where only environment variables starting with NEXT_PUBLIC_ or PUBLIC_ exist. Use one of those if you read the URL from the environment, for example production: process.env.NEXT_PUBLIC_SITE_URL.
Build scripts
Run Next.js through the Alinea CLI. alinea build bundles your content, generates the dashboard and then runs the command after --:
{
"scripts": {
"dev": "alinea dev -- next dev",
"build": "alinea build -- next build",
"start": "next start"
}
}Wrap your Next.js config in withAlinea from alinea/next. It serves the dashboard on adminPath, routes media URLs (/admin/file/...) to your handler and allows them in next/image:
import {withAlinea} from 'alinea/next'
export default withAlinea({
// your Next.js config
})The build writes the dashboard to your public folder: an admin.html file and an admin folder with its assets, named after adminPath. They are generated on every build, so leave them out of git (alinea init adds these lines to .gitignore):
/public/admin.html
/public/admin/The handler route
The route you created with alinea init handles every request of the dashboard:
import {cms} from '@/cms'
import {createHandler} from 'alinea/next'
const handler = createHandler({cms})
export const GET = handler
export const POST = handlerWithout a backend option the handler connects to Alinea Cloud. Pass backend to host it yourself. Static pages are revalidated in the background after editors publish, see Instant publishing.
Commit hooks
Two hooks on the handler run for every commit, whatever it contains. beforeCommit receives the changes before they are committed: inspect or rewrite them and return the mutations to commit, or return nothing to keep them as they are. afterCommit runs once the commit is made, with the mutations, the sha of the new commit, the changed entries as they are after the commit and the removed entries with the url they had: revalidate caches of your own, notify your team or trigger a deploy.
import {cms} from '@/cms'
import {createHandler} from 'alinea/next'
import {revalidateTag} from 'next/cache'
const handler = createHandler({
cms,
beforeCommit({mutations}) {
// Inspect or rewrite the changes, return the mutations to commit
return mutations
},
afterCommit({entries, removed}) {
// Pages that query content refresh on their own, revalidate your own
// caches, eg. a feed that lists products
const changed = [...entries, ...removed]
if (changed.some(entry => entry.type === 'Product'))
revalidateTag('products', 'max')
}
})
export const GET = handler
export const POST = handlerBoth hooks also receive the user making the commit, with their roles. In development that is the local user: an admin, or the roles you pass to alinea dev --role. Both hooks can be async. Errors thrown in afterCommit are logged and don't fail the commit.
Hosting requirements
Node.js 24 or higher where your site runs, not only where it builds: the bundled content database is opened with Node's built-in SQLite.
The Node.js runtime for the handler route. The handler refuses to run on the Edge runtime.
Server rendering. The handler is an API route, so a static export (
output: 'export') can't run the dashboard or serve media.
Deploy
Push your code and deploy it as usual. Then open /admin on your deployed site:
Without a backend, the dashboard walks you through connecting the site to Alinea Cloud.
With a self-hosted backend, editors sign in with the method you configured.
After the first publish, check that the change shows up on your site and that a commit appeared in your repository.