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.

A workspace is a named collection of roots that maps to a specific directory on disk where Alinea stores its JSON entry files. Every Alinea project needs at least one workspace. Larger projects — for example, a monorepo that hosts a marketing site and a docs site — can declare multiple workspaces in a single config, each with its own source directory, media folder, and dashboard color.

Creating a workspace

Use Config.workspace(label, config) to create a workspace. The first argument is the human-readable label shown in the dashboard sidebar. The second argument combines a WorkspaceMeta descriptor with a required roots map.
cms.ts
import {Config, Field} from 'alinea'
import {createCMS} from 'alinea/next'

const BlogPost = Config.document('Blog post', {
  fields: {
    body: Field.richText('Body')
  }
})

export const cms = createCMS({
  schema: Config.schema({types: {BlogPost}}),
  workspaces: {
    main: Config.workspace('Main', {
      source: 'content/main',
      mediaDir: 'public',
      color: '#3D5AFE',
      roots: {
        pages: Config.root('Pages', {
          contains: [BlogPost]
        }),
        media: Config.media()
      }
    })
  }
})
The roots object is the only required field beyond source. Every key in roots becomes the root’s identifier and must be a valid [A-Za-z0-9_] identifier.

WorkspaceMeta properties

source
string
required
Path to the directory that holds the JSON entry files for this workspace, relative to the project root. For example 'content/main' or 'content/docs'.When a project has multiple workspaces, each workspace’s source directory must be a sub-directory of a shared parent, and the sub-directory name must match the workspace key in workspaces. For example:
content/
  primary/     ← workspace key "primary", source "content/primary"
  secondary/   ← workspace key "secondary", source "content/secondary"
roots
Record<string, Root>
required
A map of root keys to root objects created with Config.root() or Config.media(). Every workspace must contain at least one root and exactly one media root (see Roots).
mediaDir
string
The directory where uploaded media files are written when using a local file backend. Typically set to 'public' so that Next.js serves them statically. If omitted, uploads are stored in the cloud backend only.
color
string
A hex color string used as the workspace’s accent color in the dashboard sidebar. If not provided, a color is derived deterministically from the workspace label.
icon
ComponentType
A React component (icon) displayed next to the workspace name in the dashboard. Any icon component that renders an SVG works, including those from alinea/ui/icons.
preview
Preview
A workspace-level preview configuration. This is overridden by any root-level or type-level preview setting on a specific entry.

Multiple workspaces

You can declare as many workspaces as you need. The following example mirrors the apps/dev configuration with a primary workspace (rich, multi-root setup) and a lightweight secondary workspace.
cms.ts
import {Config, Field} from 'alinea'
import {createCMS} from 'alinea/next'

const Page = Config.document('Page', {fields: {}})
const Folder = Config.document('Folder', {
  contains: ['Folder', Page],
  fields: {}
})

export const cms = createCMS({
  schema: Config.schema({types: {Page, Folder}}),
  workspaces: {
    primary: Config.workspace('Primary workspace', {
      source: 'content/primary',
      mediaDir: 'public',
      color: '#3D5AFE',
      roots: {
        pages: Config.root('Pages', {
          contains: [Page, Folder]
        }),
        media: Config.media()
      }
    }),
    secondary: Config.workspace('Secondary workspace', {
      source: 'content/secondary',
      roots: {
        pages: Config.root('Pages', {
          contains: ['Page', 'Folder']
        }),
        media: Config.media()
      }
    })
  }
})
When using multiple workspaces, Alinea enforces that every workspace key matches its source directory name exactly. For example, the workspace keyed primary must have source: 'content/primary', not source: 'content/primary-site'. Validation runs at startup and will throw a descriptive error if the convention is not followed.
In single-workspace projects the workspace source directory becomes the content root directly. In multi-workspace projects a shared parent directory is inferred from all workspace source paths — make sure they share the same parent (e.g. content/).

Build docs developers (and LLMs) love