Theme Portability
A well-written Accent CMS theme produces identical output whether you run accent serve in development, accent serve --production in production, or accent build for static deployment. This guide covers the guidelines and template features that make themes portable across all three modes.
Theme Structure
Every Accent theme consists of:
theme.yaml– theme configuration (name, assets, styling)templates/*.html.jinja– Jinja templatesassets/– CSS, JS, images, fonts
The CMS loads these files at startup and uses them for all page rendering. The rendering pipeline, template functions, and context variables are identical in serve and build modes.
What Stays the Same
Everything a theme developer interacts with works identically across serve and build:
| Feature | accent serve | accent build |
|---|---|---|
| Jinja template rendering | yes | yes |
Template inheritance (extends, include) | yes | yes |
All template functions (now, get_env, get_hash, etc.) | yes | yes |
| fingerprint filter | yes (no-op) | yes (active) |
theme.yaml configuration | yes | yes |
theme.assets.css / theme.assets.js | yes | yes |
Page context (page, site, theme, pages, etc.) | yes | yes |
| Shortcodes | yes | yes |
| Taxonomy pages | yes | yes |
| Pagination | yes | yes |
What Differs Between Modes
A few behaviors are mode-specific, but they require no changes to your theme:
Hot Reload (Development Only)
With dev.hot_reload: true, templates and assets refresh automatically when you save a file. In production mode and static builds, hot reload is disabled. Your templates don’t need to handle this – it’s automatic.
Asset Fingerprinting
The | fingerprint filter is active only during accent build. In accent serve, it returns the original path unchanged. Templates using | fingerprint work correctly in both modes without conditional logic:
{# Works in both modes: fingerprinted path in build, original path in serve #}
<link rel="stylesheet" href="/{{ ('theme/assets/' ~ css) | fingerprint }}">
Environment Variables
get_env() reads from the process environment in both modes. In build mode, values are baked into the static HTML. In serve mode, values are read per-request but frozen in the page cache for the duration of the cache TTL.
File Hashing
get_hash(path='...') resolves files against the theme’s assets directory. The hash output is identical for the same file content in both serve and build modes.
Writing Portable Themes
Follow these guidelines to ensure your theme works correctly in both serve and build:
Use Relative Asset Paths
Reference assets relative to the theme’s assets directory:
{# Correct: relative to theme assets #}
<link rel="stylesheet" href="/theme/assets/css/style.css">
{# With fingerprinting for cache busting #}
<link rel="stylesheet" href="/{{ ('theme/assets/css/style.css') | fingerprint }}">
Use Template Functions for Dynamic Values
Use template functions to derive values rather than hardcoding environment-specific information:
{# Cache busting via content hash #}
<link rel="stylesheet" href="/theme/assets/css/style.css?v={{ get_hash(path='theme/assets/css/style.css') }}">
{# Environment-specific configuration #}
{% set analytics_id = get_env(name="GA_ID") %}
{% if analytics_id %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ analytics_id }}"></script>
{% endif %}
Keep theme.yaml Complete
Declare all CSS and JS files in theme.yaml so the CMS knows which assets to load:
name: My Theme assets: css: - css/main.css - css/components.css js: - js/app.js
Test with accent build
Run accent build to verify your theme produces correct static output. The build uses the same rendering pipeline as serve mode, so if the build output is correct, your theme works:
accent build --output ./public --clean accent serve-static --dir ./public # Verify the site at http://127.0.0.1:4403
Avoid Dev-Only Assumptions
Don’t assume hot reload, debug panels, or SSE reload scripts are available. Use the dev.debug context variable for development-only markup:
{% if dev.debug %}
<div class="debug-panel">
<pre>{{ debug(page) }}</pre>
</div>
{% endif %}
Edition Availability
Theme portability across serve and build modes is available in all editions, including the free Core edition. No license key is required.