Github
Configuration

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:

  1. handoff.config.ts
  2. handoff.config.js
  3. handoff.config.cjs
  4. handoff.config.json

-c, --config <file> on any command loads one specific file instead. defineConfig types the config:

handoff.config.ts
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.
  • undefined is skipped.

Main settings

SettingPurpose
app.title, app.clientName of the documentation site and of the client. Page titles use app.title.
app.themeTheme of the documentation app. npx handoff-app eject:theme copies it to theme/default.scss.
app.basePathURL path when you serve the site under a sub-path, for example /design-system
app.breakpointsPreview widths. A declared block merges onto the defaults.
app.portsWorkspace server ports, { app, websocket }. The defaults are 3000 and 3001.
app.attributionShow the Handoff attribution. The default is true.
catalog.includeCatalog directories. See Registration.
entries.scss, entries.jsGlobal stylesheet and script built into every preview
integrations.figmaFigma file and token. See Figma foundations.
pipeline.transformersExtra token transformers. See Token transformers.
reactDocgenmaxDepth and excludeDirectories for the property table scan
exportsOutputDirectoryDirectory for fetched foundations. The default is exported.
sitesOutputDirectoryDirectory for build output. The default is out.
runtime.modeworkspace (default) or registry
runtime.workspace.declarationFormatFormat of the declarations that checkout writes: ts, js, or cjs
runtime.registryConnectionRegistry URL and token of a connected workspace. See Connect a workspace.
runtime.registryRegistry database, asset storage, and email. See Registry.
runtime.mcpMCP endpoint on or off. See MCP.
runtime.aiAI assistant. See AI assistant.
hooksBuild 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 with HandoffConfigError.

Some settings change the shape of the build. These are baked, so changing them on a deployed registry needs a rebuild:

  • runtime.mode
  • runtime.mcp
  • runtime.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.

On this page