Theme Development
Single source guide for developing Theme Packs and Theme Apps on the current runtime
Theme Development (Single Source)
This is the only developer guide for theme development in this repository.
It covers both theme types supported by current runtime code:
Theme Pack(default path)Theme App(advanced executable path)
If you are building a third-party theme, start with Theme Pack unless you explicitly need an executable storefront runtime.
1. Scope and Relationship to Plugins
Theme development and business plugin development are separate tracks.
- Themes control storefront/admin presentation and rendering behavior.
- Business plugins provide backend capability through plugin runtime (
external-http/internal-fastify). - A business plugin can expose
app block/app embedviathemeExtensions, but it is still a plugin, not a theme.
Use this doc for theme-* and theme-app-* development only.
2. Theme Shapes and When to Use Them
| Shape | Best for | Runtime model |
|---|---|---|
Theme Pack | Branding, layout, templates, assets, block composition | Rendered by built-in theme runtime |
Theme App | Fully executable storefront with custom runtime behavior | Spawned as child process by API runtime |
3. Installer Kinds and Manifest Files
Theme installation uses POST /api/v1/admin/extensions/:kind/install.
Kinds:
theme-shop-> Theme Pack (theme.json, targetshop)theme-admin-> Theme Pack (theme.json, targetadmin)theme-app-shop-> Theme App (theme-app.json, targetshop)theme-app-admin-> Theme App (theme-app.json, targetadmin)
4. Theme Pack Contract
Theme Pack is a static resource package. Do not ship executable runtime code.
Recommended package layout
my-theme-pack/
├── theme.json
├── tokens.css
├── templates/
│ ├── home.json
│ └── product.json
├── assets/
│ └── hero-banner.webp
└── schemas/
└── settings.schema.jsonMinimal theme.json
{
"schemaVersion": 1,
"slug": "modern-travel",
"name": "Modern Travel",
"version": "1.0.0",
"target": "shop",
"description": "Travel-focused storefront theme pack",
"entry": {
"tokensCSS": "tokens.css",
"templatesDir": "templates",
"assetsDir": "assets",
"settingsSchema": "schemas/settings.schema.json"
},
"defaultConfig": {
"colors": {
"primary": "#0f766e",
"background": "#f8fafc"
}
}
}Pack development rules
- Use JSON templates under
templates/to define page structure. - Use CSS tokens and static assets for visual system.
- Keep customization inside block/slot contract.
- Do not put executable JS/TS runtime code in the package.
5. Theme App Contract
Theme App is an executable package with built output.
Supported runtime boundary (current code)
- manifest filename must be
theme-app.json runtime.kindmust benext-standalone- API runtime starts app via
node <runtime.entry> - health checks must pass before activation completes
- runtime state is process-local (single replica is the safe shape)
Recommended package layout
my-theme-app/
├── theme-app.json
├── server.js
├── .next/
│ └── static/
└── public/Minimal theme-app.json
{
"schemaVersion": 1,
"type": "theme-app",
"slug": "modern-travel-app",
"name": "Modern Travel App",
"version": "1.0.0",
"target": "shop",
"runtime": {
"kind": "next-standalone",
"entry": "server.js",
"healthPath": "/api/health"
},
"port": {
"preferred": 3100,
"range": { "min": 3100, "max": 3199 }
},
"healthCheck": {
"path": "/api/health",
"timeout": 5000,
"retries": 3,
"retryInterval": 2000
}
}Theme App activation behavior
Activation is fail-safe:
- API reads active theme state.
- API starts Theme App runtime.
- API performs health checks.
- Active theme switches only after healthy startup.
If startup or health check fails, active theme stays unchanged.
6. Theme Runtime and Routing Behavior
- Theme Pack uses built-in renderer in Shop/Admin apps.
- Theme App traffic is proxied through
/theme-app/{target}/{slug}/*. - Theme API routes (
/api/*) remain owned by platform API. - Plugin gateway routes (
/api/v1/shop/plugins/{slug}/api/*) remain independent from theme runtime.
7. Theme + Plugin Integration Model
Theme and plugin integration should follow this pattern:
- Theme defines layout and rendering slots.
- Plugin provides dynamic business capabilities and data endpoints.
- Plugin
themeExtensionscontributesapp block/app embedinto theme rendering.
Do not move plugin business logic into theme packages.
8. Local Development and Packaging
Theme Pack
- edit
theme.json, templates, tokens, and assets - create zip with package root containing
theme.json - upload via Theme install in Admin
Theme App
- build standalone output first
- ensure
theme-app.jsonpoints to builtruntime.entry - include required static artifacts (
.next/static,publicas needed) - zip built package root and upload in Admin
9. Minimal Submission Directory Templates
Use these as copy-paste starting points before zipping.
Theme Pack (shop/admin)
my-theme-pack/
├── theme.json
├── tokens.css
├── templates/
│ ├── home.json
│ └── product.json
├── assets/
│ └── hero-banner.webp
└── schemas/
└── settings.schema.jsonMinimal theme.json for submission:
{
"schemaVersion": 1,
"slug": "my-theme-pack",
"name": "My Theme Pack",
"version": "1.0.0",
"target": "shop",
"entry": {
"tokensCSS": "tokens.css",
"templatesDir": "templates",
"assetsDir": "assets",
"settingsSchema": "schemas/settings.schema.json"
}
}Theme App (shop/admin)
my-theme-app/
├── theme-app.json
├── server.js
├── .next/
│ └── static/
└── public/Minimal theme-app.json for submission:
{
"schemaVersion": 1,
"type": "theme-app",
"slug": "my-theme-app",
"name": "My Theme App",
"version": "1.0.0",
"target": "shop",
"runtime": {
"kind": "next-standalone",
"entry": "server.js",
"healthPath": "/api/health"
}
}ZIP notes:
- ZIP root must contain
theme.jsonortheme-app.jsondirectly, or contain a single wrapper folder with that manifest. - Upload with the correct kind for target and shape (
theme-shop,theme-admin,theme-app-shop,theme-app-admin).
10. Acceptance Checklist
Before upload:
- manifest file exists and validates (
theme.jsonortheme-app.json) - slug/version/target are correct
- package structure matches selected kind
- no disallowed artifacts for selected theme shape
After install:
- theme appears in installed list for target (
shoporadmin) - activation succeeds
- storefront/admin renders correctly
- rollback to previous theme works
Theme App extra checks:
- runtime process starts successfully
- health check passes within configured retries
- proxied traffic works through
/theme-app/{target}/{slug}/*
11. Authoritative Code References
Use these files as runtime truth when updating this document:
apps/api/src/core/admin/extension-installer/types.tsapps/api/src/core/admin/extension-installer/theme-installer.tsapps/api/src/core/admin/extension-installer/theme-app-installer.tsapps/api/src/core/admin/theme-app-runtime/contract.tsapps/api/src/core/admin/theme-app-runtime/manager.tsapps/api/src/core/admin/theme-app-runtime/gateway.tsapps/api/src/core/admin/theme-management/service.tsapps/shop/lib/theme-pack/types.tsapps/admin/lib/theme-pack/types.ts
When this document conflicts with runtime behavior, update this document to match code.