Build and CI/CD Integration
This article covers the recommended package.json scripts, build strategies for different team workflows, and how to integrate token generation into a CI/CD pipeline.
Recommended package.json scripts
{
"scripts": {
"tokens:build": "theme-engine build",
"tokens:build:all": "theme-engine build:all",
"tokens:themes": "theme-engine themes:generate",
"tokens:dimension": "theme-engine dimension:generate",
"tokens:sync": "theme-engine sync:architecture",
"tokens:foundations": "theme-engine foundations:generate",
"tokens:figma": "theme-engine figma:generate",
"tokens:validate": "theme-engine validate:data"
}
}
Use tokens:build for all normal use. The others are useful during brand authoring or debugging.
Build strategies
Strategy A — Full regeneration (recommended for CI)
Run the full pipeline on every CI trigger. Guarantees that dist/ always reflects the current configuration.
npm run tokens:build
Simple, reliable, and idempotent. The full pipeline completes in a few seconds for most projects.
Strategy B — Incremental (local development)
When only the output format changed (no color or typography changes), skip data generation and only re-run the Style Dictionary transform:
npm run tokens:build:all
When brand colors changed:
npm run tokens:themes && npm run tokens:sync && npm run tokens:foundations && npm run tokens:build:all
Strategy C — Validate, then build (pre-publish)
Validate the generated data before building. Catches schema violations before the Style Dictionary step.
npm run tokens:validate && npm run tokens:build:all
CI/CD integration
GitHub Actions — full pipeline
name: Build design tokens
on:
push:
branches: [main]
paths:
- 'theme-engine/**'
- 'aplica-theme-engine.config.mjs'
jobs:
tokens:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Generate and build tokens
run: npm run tokens:build
- name: Validate output
run: npm run tokens:validate
# Optional: publish dist/ as a package artifact
- uses: actions/upload-artifact@v4
with:
name: token-dist
path: dist/
GitHub Actions — publish token package
If your project publishes dist/ as a separate npm package:
- name: Build tokens
run: npm run tokens:build
- name: Publish token package
run: npm publish --access public
working-directory: ./packages/tokens
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Committing data/ and dist/
| Approach | When to use |
|---|---|
| Don't commit either | CI regenerates both. Cleanest approach for teams with reliable CI. |
Commit dist/ only | When downstream consumers pull from the repo directly (not a published package). Regenerate in CI on each push. |
| Commit both | When you want reproducible snapshots for auditing or review. Add generation to a pre-commit hook. |
Pre-commit hook (commit both)
Install Husky and add:
# .husky/pre-commit
npm run tokens:build
git add data/ dist/
This ensures data/ and dist/ are always in sync with the configuration at commit time.
.gitignore recommendations
# Token build outputs — regenerate in CI
/data/
/dist/
Or, if committing dist/:
# Token source data — regenerate in CI
/data/
# dist/ is committed — do not ignore
Windows environments
The CLI works on Windows without additional configuration. If you encounter path resolution issues on Windows, see 07-troubleshooting.md.
Version pinning
Pin the engine version in package.json to control when breaking changes affect your build:
{
"dependencies": {
"@aplica/aplica-theme-engine": "3.3.1"
}
}
Use a patch-range (~3.3.0) for automatic patch updates only. Avoid ^ (caret) ranges if token naming contract stability is critical for your consumers.
Troubleshooting failed CI builds
No consumer workspace config was found—aplica-theme-engine.config.mjsis missing or not in the project root. Ensure the file is committed.validate:datafails — generation schema mismatch. Runtokens:buildlocally and commit the updateddata/.- Build exits non-zero with no error message — check Node.js version (requires ≥ 18.0.0).
- Fonts not copied —
assets/fonts/directory does not exist. Create it or setcopyFonts: falseintransformers.config.mjs.
For more, see 07-troubleshooting.md.