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 separates two concerns: the canonical content store (your git repository) and the editing backend (draft storage, publishing, and authentication). By default, Alinea Cloud handles the editing backend for you. If you prefer to self-host, you can supply a BackendOptions object to createHandler that points to your own GitHub repository and a database of your choice.

Architecture

When an editor saves a draft, Alinea writes it to the configured database. When they publish, Alinea calls the GitHub API to commit the changed files to your repository. Your Next.js build then picks up those committed files on the next deployment. The database is used only for ephemeral draft state and is never the source of truth for published content.

BackendOptions

Pass BackendOptions to createHandler via the backend field:
app/api/cms/route.ts
import {cms} from '@/cms'
import {createHandler} from 'alinea/next'

const handler = createHandler({
  cms,
  backend: {
    github: {
      owner: 'your-org',
      repo: 'your-repo',
      branch: 'main',
      authToken: process.env.GITHUB_TOKEN!,
      rootDir: '',
      contentDir: 'content'
    },
    database: {
      driver: 'd1',
      client: process.env.DB as any
    },
    auth(username, password) {
      return (
        username === process.env.CMS_USER &&
        password === process.env.CMS_PASSWORD
      )
    }
  }
})

export const GET = handler
export const POST = handler
github
GithubOptions
required
Connection details for the GitHub repository where Alinea commits published content. See GithubOptions below.
database
DatabaseDeclaration
required
The database to use for draft storage. Specify a driver string and a client instance matching that driver. See Supported database drivers for the full list.
auth
(username: string, password: string) => boolean | Promise<boolean>
Optional basic authentication callback. Receives the username and password from the login form and should return true to allow access. Use this for simple single-user setups. Omit when using oauth2.
oauth2
OAuth2Options
Optional OAuth2 configuration for delegating authentication to an external provider. When both auth and oauth2 are absent, createBackend throws at request time. Provide exactly one of the two.
At least one of auth or oauth2 must be provided. createBackend asserts this at runtime and will throw an error if neither is present.

GithubOptions

GithubOptions extends GithubSourceOptions with an optional author field:
owner
string
required
The GitHub organisation or user that owns the repository, e.g. "acme-corp".
repo
string
required
The repository name, e.g. "my-website".
branch
string
required
The branch to read from and commit to, e.g. "main".
authToken
string
required
A GitHub personal access token or app installation token with read and write access to repository contents.
rootDir
string
required
The path within the repository to treat as the project root. Pass an empty string ("") when your content lives at the repository root.
contentDir
string
required
The directory (relative to rootDir) where Alinea stores content files, e.g. "content".
author
{ name: string; email: string }
Default commit author. When a logged-in user has a name and email set, Alinea uses their identity instead and appends the configured author as a Co-authored-by trailer.
The authToken must have write access (repo scope for classic tokens, or Contents: Read and write for fine-grained tokens) to the target repository. A read-only token will cause publish operations to fail with a 403 error.

Supported database drivers

DatabaseDeclaration is a discriminated union — set driver to one of the strings below, and set client to the corresponding database client instance for that driver.
driverClient typeTypical use
"d1"Cloudflare D1 bindingCloudflare Workers / Pages
"mysql2"mysql2 connection or poolMySQL on any host
"@neondatabase/serverless"Neon serverless clientNeon Postgres (serverless)
"@vercel/postgres"@vercel/postgres clientVercel Postgres
"pg"pg Client or PoolStandard PostgreSQL
"@electric-sql/pglite"PGlite instanceIn-process SQLite-compatible Postgres
"sql.js"sql.js DatabaseIn-memory SQLite (testing)
"@libsql/client"libSQL clientTurso / libSQL

D1 example (Cloudflare)

app/api/cms/route.ts
import {cms} from '@/cms'
import {createHandler} from 'alinea/next'

// In a Cloudflare Workers environment, D1 bindings are available
// on the incoming request context.
const handler = createHandler({
  cms,
  backend: {
    github: {
      owner: process.env.GITHUB_OWNER!,
      repo: process.env.GITHUB_REPO!,
      branch: 'main',
      authToken: process.env.GITHUB_TOKEN!,
      rootDir: '',
      contentDir: 'content'
    },
    database: {
      driver: 'd1',
      client: process.env.DB as any
    },
    auth(username, password) {
      return (
        username === process.env.CMS_USER &&
        password === process.env.CMS_PASSWORD
      )
    }
  }
})

export const GET = handler
export const POST = handler

Neon / Vercel Postgres example

app/api/cms/route.ts
import {cms} from '@/cms'
import {createHandler} from 'alinea/next'
import {neon} from '@neondatabase/serverless'

const sql = neon(process.env.DATABASE_URL!)

const handler = createHandler({
  cms,
  backend: {
    github: {
      owner: process.env.GITHUB_OWNER!,
      repo: process.env.GITHUB_REPO!,
      branch: 'main',
      authToken: process.env.GITHUB_TOKEN!,
      rootDir: '',
      contentDir: 'content'
    },
    database: {
      driver: '@neondatabase/serverless',
      client: sql
    },
    oauth2: {
      clientId: process.env.OAUTH_CLIENT_ID!,
      clientSecret: process.env.OAUTH_CLIENT_SECRET,
      jwksUri: process.env.OAUTH_JWKS_URI!,
      authorizationEndpoint: process.env.OAUTH_AUTH_ENDPOINT!,
      tokenEndpoint: process.env.OAUTH_TOKEN_ENDPOINT!
    }
  }
})

export const GET = handler
export const POST = handler

OAuth2Options

clientId
string
required
The OAuth2 client identifier issued by your identity provider.
clientSecret
string
Client secret. Required for client_secret_basic authentication methods such as client_credentials and password flows, but not for authorization_code.
jwksUri
string
required
The JWKS endpoint URI used to verify access token signatures.
authorizationEndpoint
string
required
The /authorize endpoint. Required for the browser-side of the authorization_code flow.
tokenEndpoint
string
required
The /token endpoint. Required for most grant types and for refreshing tokens.
revocationEndpoint
string
The /revoke endpoint. Used to revoke tokens on logout. Not supported by all providers.
validateClaims
(claims: JWTPayload) => void
Optional callback to enforce extra JWT claim checks such as iss or aud. Throw an error inside the callback to reject the token.

Build docs developers (and LLMs) love