Config file
Where Handoff reads its config, how values merge onto the defaults, and the main settings.
Config file
Handoff reads the first of these files in the working directory and warns about the others:
handoff.config.tshandoff.config.jshandoff.config.cjshandoff.config.json
-c, --config <file> on any command loads one specific file instead. defineConfig types the
config:
import { defineConfig, fromEnv } from 'handoff-app'
export default defineConfig({
app: { title: 'Example Design System' },
catalog: { include: ['components', 'patterns'] },
runtime: {
mode: 'workspace',
workspace: { declarationFormat: 'ts' },
registry: {
database: { url: fromEnv('DATABASE_URL'), driver: 'pg' },
},
},
})npx handoff-app eject:config writes the full default config to the working directory.
Merge rules
Values merge onto the defaults in layers: defaults, base config, profile, then a programmatic override from the JavaScript API.
- Plain objects merge recursively.
- Arrays, scalars,
null, and functions replace the value below them. undefinedis skipped.
Main settings
| Setting | Purpose |
|---|---|
app.title, app.client | Name of the documentation site and of the client. Page titles use app.title. |
app.theme | Theme of the documentation app. npx handoff-app eject:theme copies it to theme/default.scss. |
app.basePath | URL path when you serve the site under a sub-path, for example /design-system |
app.breakpoints | Preview widths. A declared block merges onto the defaults. |
app.ports | Workspace server ports, { app, websocket }. The defaults are 3000 and 3001. |
app.attribution | Show the Handoff attribution. The default is true. |
catalog.include | Catalog directories. See Registration. |
entries.scss, entries.js | Global stylesheet and script built into every preview |
integrations.figma | Figma file and token. See Figma foundations. |
pipeline.transformers | Extra token transformers. See Token transformers. |
reactDocgen | maxDepth and excludeDirectories for the property table scan |
exportsOutputDirectory | Directory for fetched foundations. The default is exported. |
sitesOutputDirectory | Directory for build output. The default is out. |
runtime.mode | workspace (default) or registry |
runtime.workspace.declarationFormat | Format of the declarations that checkout writes: ts, js, or cjs |
runtime.registryConnection | Registry URL and token of a connected workspace. See Connect a workspace. |
runtime.registry | Registry database, asset storage, and email. See Registry. |
runtime.mcp | MCP endpoint on or off. See MCP. |
runtime.ai | AI assistant. See AI assistant. |
hooks | Build hooks. See Hooks. |
The Config type, exported from handoff-app, documents every setting.
Build-time and runtime values
fromEnv('NAME') refers to an environment variable instead of copying its value into the config.
- A literal value is baked into the build.
- For a
fromEnv()value, the build keeps only the variable name. A deployed registry reads the value at request time, so you can change it without a rebuild. - Secrets must use
fromEnv(). A literal secret stops the command withHandoffConfigError.
Some settings change the shape of the build. These are baked, so changing them on a deployed registry needs a rebuild:
runtime.moderuntime.mcpruntime.ai.enabled- The database driver
- The asset storage provider and the email provider
- Every custom server module
See Environment for fromEnv() and every variable Handoff reads.