Skip to content

Configuration

ACMS is configured via an acms.config.ts (or acms.config.js) file in your project root. The configuration file defines storage adapters, content strategy, and field management behavior.

import { defineConfig } from '@useacms/client';
import { localFile } from '@useacms/cli/adapters';
export default defineConfig({
dev: localFile({ path: './acms.json' }),
});

This minimal configuration uses the local file adapter for development. ACMS stores content in acms.json in your project root.

import { defineConfig } from '@useacms/client';
import { localFile, githubGist } from '@useacms/cli/adapters';
export default defineConfig({
// Storage adapter for development
dev: localFile({ path: './acms.json' }),
// Storage adapter for production
production: githubGist({
token: process.env.GITHUB_TOKEN,
gistId: 'your-gist-id',
}),
// Content delivery strategy
strategy: 'runtime',
// Field purge behavior
purgeUnusedFields: 'never',
});

The storage adapter used during local development. Defaults to localFile() if not specified.

dev: localFile({ path: './acms.json' })

The local file adapter stores content in a JSON file on disk. The dev server reads from and writes to this file when handling field registrations and content updates.

The storage adapter used in production. Required for acms push, acms pull, and acms sync commands.

production: githubGist({
token: process.env.GITHUB_TOKEN,
gistId: 'abc123',
})

See Storage Adapters for all available options.

Determines how content is delivered to your application:

  • 'build-time' — Content is fetched once during the build and embedded in the output. Best for static sites.
  • 'runtime' — Content is fetched at runtime from the storage adapter. Best for frequently changing content.
strategy: 'build-time' // or 'runtime'

Controls when unused fields (based on lastAccessed timestamps in metadata) are removed from the schema:

  • 'never' — Fields are never automatically removed. Use acms purge manually.
  • 'onStartup' — Unused fields are purged when acms dev starts.
  • 'always' — Unused fields are purged on every schema write.
purgeUnusedFields: 'never'

ACMS loads environment variables from a .env file in your project root using dotenv. This is useful for storing adapter credentials:

.env
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
GITHUB_GIST_ID=abc123def456

Then reference them in your config:

production: githubGist({
token: process.env.GITHUB_TOKEN,
gistId: process.env.GITHUB_GIST_ID,
})

The defineConfig function provides TypeScript type checking and autocomplete for your configuration:

import { defineConfig } from '@useacms/client';
// Full type safety and autocomplete
export default defineConfig({
dev: localFile(),
production: github({
token: process.env.GITHUB_TOKEN,
owner: 'myorg',
repo: 'content',
}),
strategy: 'build-time',
purgeUnusedFields: 'never',
});

You can use environment variables to select different adapters per environment:

import { defineConfig } from '@useacms/client';
import { localFile, githubGist, vercelEdgeConfig } from '@useacms/cli/adapters';
const isProd = process.env.NODE_ENV === 'production';
const isStaging = process.env.NODE_ENV === 'staging';
export default defineConfig({
dev: localFile({ path: './acms.json' }),
production: isProd
? vercelEdgeConfig({ token: process.env.VERCEL_TOKEN })
: isStaging
? githubGist({ token: process.env.GITHUB_TOKEN, gistId: process.env.STAGING_GIST_ID })
: localFile({ path: './acms.json' }),
});

The CLI looks for configuration files in this order:

  1. acms.config.ts
  2. acms.config.js
  3. acms.config.mjs

The config is loaded using jiti, which supports TypeScript and ESM natively without requiring a separate build step.

The acms.json file is the local content store. It contains two sections:

{
"hero": {
"title": "Welcome",
"subtitle": "Built with ACMS"
},
"contact": {
"email": "hello@example.com"
},
"_meta": {
"hero.title": {
"type": "string",
"lastAccessed": "2025-01-15T10:30:00.000Z"
},
"hero.subtitle": {
"type": "string",
"lastAccessed": "2025-01-15T10:30:00.000Z"
},
"contact.email": {
"type": "string",
"lastAccessed": "2025-01-15T10:30:00.000Z"
}
}
}
  • Content fields — The top-level keys (excluding _meta) are your content, organized by the paths you access in code.
  • _meta — Metadata about each field including its type, last access timestamp, and optional label or default value.