Self-hosted Quickstart
Install Airdraft in your own Next.js project in under 5 minutes using the CLI.
Self-hosting Airdraft means running the CMS backend inside your own application. Your content, your server, your database — zero dependency on Airdraft's cloud infrastructure.
Using Airdraft Cloud instead? See Getting Started with Airdraft Cloud.
Prerequisites
- Node.js 18+
- A Next.js 14+ project (App Router recommended)
npm,pnpm, oryarn
Step 1 — Run the initialiser
In your project root:
npx airdraft init
The CLI walks you through a short setup wizard:
- Mode — choose
Own app (auto)to scaffold everything automatically, orOwn app (manual)if you prefer to wire things yourself. - Database — choose a storage backend:
Local files(default, zero config — MDX/JSON on disk, great for development)SQLite— single-file database, ideal for VPS deploymentsPostgreSQL— production-ready, requires a connection stringMongoDB— production-ready, requires a connection string
- Plugins — select capabilities to add (authentication, media, SEO, audit log, schema editor).
- Blog scaffold — optionally generate a
postscollection and sample blog pages.
The CLI writes:
| File | What it does |
|---|---|
airdraft.config.ts |
Main config — adapter, plugins, schema path |
airdraft.schema.json |
Collection definitions |
app/api/cms/[...cms]/route.ts |
Next.js catch-all API route |
instrumentation.ts |
Database migration on server start |
.env.local |
Environment variable placeholders |
Step 2 — Fill in environment variables
Open .env.local and set the required values:
# Generate with: npx airdraft generate-secret
AIRDRAFT_JWT_SECRET=your-secret-here
# Your CMS API URL (same origin in development)
NEXT_PUBLIC_CMS_API_URL=http://localhost:3000/api/cms
# For SQLite:
DATABASE_URL=.airdraft.db
# For PostgreSQL:
# DATABASE_URL=postgresql://user:password@localhost:5432/mydb
# For MongoDB:
# MONGODB_URI=mongodb://localhost:27017/mydb
Generate a secure JWT secret:
npx airdraft generate-secret
Step 3 — Understand the generated config
The CLI produces a config like this:
// airdraft.config.ts
import { defineConfig, LocalAdapter } from '@airdraft/core'
import { withAutoAuth } from '@airdraft/plugin-auth'
import { withAutoMedia } from '@airdraft/plugin-media'
import { withSeo } from '@airdraft/plugin-seo'
import { withSchemaEditor } from '@airdraft/plugin-schema-editor'
import { withAuditLog } from '@airdraft/plugin-audit-log'
const adapter = new LocalAdapter({ root: './content' })
const media = await withAutoMedia({ storageAdapter: adapter })
const auth = withAutoAuth() // returns null if AIRDRAFT_JWT_SECRET not set
export default defineConfig({
adapter,
schemaPath: 'airdraft.schema.json',
plugins: [
withAuditLog({ logFilePath: './logs/audit.log' }),
media,
withSeo(),
withSchemaEditor({ adminKey: process.env.CMS_ADMIN_KEY }),
...(auth ? [auth] : []),
],
})
The withAutoMedia call requires { storageAdapter: adapter } — this is the content adapter used to store media sidecar metadata alongside files.
Step 4 — Start the dev server
npm run dev
Your CMS API is live at http://localhost:3000/api/cms. Visit http://localhost:3000/api/cms/docs for the auto-generated API reference.
Step 5 — Create the first admin user
npx airdraft create-user
The CLI prompts for email, password, and role. Choose admin for the first user.
For a database-backed adapter, the generated startup migration creates the user
and invite indexes and create-user writes through adapter.userStore(). The
default .airdraft/users.json store is appropriate only for local development or
servers with persistent disks; use a database-backed user store on serverless or
horizontally scaled deployments.
Step 6 — Open the admin UI
If you selected the Schema editor plugin, mount CMSAdmin from @airdraft/react-ui:
// app/admin/[[...segments]]/page.tsx
import { CMSAdmin } from '@airdraft/react-ui'
import '@airdraft/react-ui/styles.css'
export default function AdminPage() {
return (
<CMSAdmin
basePath="/admin"
apiUrl={process.env.NEXT_PUBLIC_CMS_API_URL!}
/>
)
}
Step 7 — Query your content
Use createCmsClient from @airdraft/next in Server Components — it calls the engine directly, no HTTP:
// lib/cms.ts
import { createCmsClient } from '@airdraft/next'
import airdraft from '@/airdraft.config'
export const cms = createCmsClient(airdraft)
const { entries } = await cms.listEntries('posts', { status: 'published' })
Manual setup (advanced)
If you prefer to wire things manually, install the packages directly:
npm install @airdraft/next @airdraft/core @airdraft/plugin-auth @airdraft/plugin-media
// app/api/cms/[...cms]/route.ts
import { createCmsHandler } from '@airdraft/next'
import airdraft from '@/airdraft.config'
export const { GET, POST, PATCH, PUT, DELETE } = createCmsHandler(airdraft)
See Using Airdraft in Next.js for the complete setup.
Resources
@airdraft/nexton npm — handler, server client@airdraft/coreon npm —defineConfig, adapters, types@airdraft/plugin-authon npm — auth plugin@airdraft/plugin-mediaon npm — media plugin@airdraft/react-uion npm — admin UI- GitHub — aevrHQ/airdraft