Skip to content

Latest commit

 

History

4,720 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm install size license

Alinea is an open source, Git-based headless CMS for Next.js. You define your content model in TypeScript, editors work in a dashboard that ships with your app, and every entry is stored as a JSON file in your repository.

Docs · Demo · Alinea Cloud · Changelog

The Alinea dashboard editing a product entry, with a live preview of the page next to the form
  • Content in git: every entry is a JSON file in your repository. Review, branch and roll back content like code.
  • Typed, no codegen: query types come straight from your schema.
  • No database server for content: content is indexed in SQLite and bundled with your site, with full text search in the dashboard.
  • Live previews: add one component to your layout and pages preview drafts as editors type, rendered by your server components.
  • Instant publishing: every publish is a git commit, and deployed sites pick up new content without waiting for a rebuild.
  • An accessible dashboard: built on React Aria Components, with dark mode, entry history, roles and permissions, and per-field translations.
  • Self-host or Cloud: run the backend on your own database, or let Alinea Cloud handle sign-in and publishing.

Quick start

Alinea requires Node.js 24 or higher, React 19 and the Next.js App Router. In a Next.js project:

npm install alinea@preview
npx alinea@preview init

alinea init creates cms.ts with your schema and settings, the API route the dashboard talks to (app/(alinea)/api/cms/route.ts), a first entry in content/pages, and rewrites your dev and build scripts to run through Alinea. Then wrap your Next.js config:

// next.config.ts
import {withAlinea} from 'alinea/next'

export default withAlinea({
  // Your Next.js options
})

Start the dev server with npm run dev and open the dashboard at http://localhost:3000/admin.

Read the full quickstart →

Define your content

Types and fields are plain TypeScript in cms.ts. Every document gets a title and a path.

// cms.ts
import {Config, Field} from 'alinea'
import {createCMS} from 'alinea/next'

export const BlogPost = Config.document('Blog post', {
  fields: {
    publishDate: Field.date('Publish date'),
    cover: Field.image('Cover image'),
    body: Field.richText('Body')
  }
})

export const Blog = Config.document('Blog', {
  contains: [BlogPost]
})

export const cms = createCMS({
  schema: {Blog, BlogPost},
  workspaces: {
    main: Config.workspace('My site', {
      source: 'content',
      mediaDir: 'public/media',
      roots: {
        pages: Config.root('Pages', {contains: [Blog]}),
        media: Config.media()
      }
    })
  },
  baseUrl: {
    development: 'http://localhost:3000',
    production: 'https://example.com'
  },
  handlerUrl: '/api/cms',
  adminPath: '/admin'
})

Schema and fields →

Query it

Query content in server components. Results are typed from your schema, and select returns exactly the shape you ask for, including related entries.

// app/blog/page.tsx
import {Blog, BlogPost, cms} from '@/cms'
import {Query} from 'alinea'

export default async function BlogPage() {
  const blog = await cms.get({
    type: Blog,
    select: {
      title: Query.title,
      posts: Query.children({
        type: BlogPost,
        select: {title: Query.title, url: Query.url, date: BlogPost.publishDate},
        orderBy: {desc: BlogPost.publishDate}
      })
    }
  })
  return (
    <main>
      <h1>{blog.title}</h1>
      {blog.posts.map(post => (
        <a key={post.url} href={post.url}>
          {post.title}
        </a>
      ))}
    </main>
  )
}

Queries → · Live previews → · Deploy →

The Alinea dashboard listing products in a sortable table with image, price, material and stock columns

Coding agents

The npm package includes the documentation of its version as Markdown in node_modules/alinea/docs/ (start at index.md), and the website lists every page in /llms.txt. alinea init adds a marked section to your AGENTS.md that points agents to both, and registers an MCP server in .mcp.json. While alinea dev runs, agents use it to read your schema and create, edit and publish entries through the same save path as the dashboard.

{
  "mcpServers": {
    "alinea": {"command": "npx", "args": ["alinea", "mcp"]}
  }
}

AI agents →

Upgrading from 1.x

See the upgrade guide and the changelog.

Contributing

Have a question or an idea? Found a bug? Read how to contribute.

License

MIT

Releases

Packages

Used by

Contributors

Languages