themes/mytheme/
├── skeleton.pt # Main HTML5 Chameleon base template
└── static/ # Theme static assets (stylesheets, fonts, images, scripts)
├── css/
│ └── theme.css
├── js/
│ └── theme.js
└── images/
└── logo.svgTheme Development & Chameleon TAL
Golem themes provide complete control over the layout, typography, aesthetic styling, and client-side behavior of generated documentation portals. Built on top of Chameleon Zope Page Templates (.pt) and standard TAL (Template Attribute Language), Golem couples powerful declarative templating with modern, parameterized CSS Custom Properties.
Theme Architecture & Layout Structure
A Golem theme is a self-contained directory containing layout templates and static assets. Golem locates and resolves themes using the following hierarchy:
- Explicit Custom Template: A template file designated in
templates_dir(e.g.templates/page.ptortemplates/skeleton.pt). - Project-Local Theme Folder: Located at
themes/<theme_name>/(e.g.themes/mytheme/skeleton.pt). - Packaged Plugin Theme: Discovered via Python package entry points in the
golem.themesgroup. - Built-in Default Theme: Shipped directly inside the
golempackage atsrc/golem/templates/default/skeleton.pt.
Standard Theme Directory Structure
When Golem builds your documentation site, static assets in themes/<theme>/static/ are automatically synchronized into the output directory under dist/static/.
Template Context Variables
When rendering skeleton.pt, Golem passes a comprehensive set of template variables to Chameleon:
Variable | Type | Description |
|
| Title of the website configured in |
|
| Title of the current document extracted from the top-level AsciiDoc header ( |
|
| Configured site author name or organization (default: |
|
| Base URL of the website if configured (useful for |
|
| Active version string of the Golem engine (e.g. |
|
| Pre-rendered semantic HTML5 content generated from the AsciiDoc document body. Also accessible as |
|
| Hierarchical site map data structure containing |
|
| Pre-rendered semantic HTML5 navigation list ( |
|
| Rendered Table of Contents HTML unordered list generated from document headings ( |
|
| Path of the source document relative to the content root directory. |
|
| List of custom stylesheet URLs or paths injected from configuration. |
|
| List of custom script URLs or paths injected from configuration. |
Chameleon TAL Syntax Reference
Chameleon templates use standard TAL XML attributes to inject dynamic data without breaking standard HTML syntax:
tal:content="variable": Replaces the element's text content with an HTML-escaped string value.tal:content="structure variable": Injects raw HTML markup without escaping (essential forbody_html,nav_html, andtoc_html).tal:replace="structure variable": Replaces the containing HTML tag itself with raw markup.tal:condition="variable": Renders the element conditionally only if the expression evaluates to truthy.tal:repeat="item collection": Loops through an iterable, repeating the element for each item.tal:attributes="attr expression": Dynamically sets HTML element attributes (e.g.tal:attributes="href item.url").${expression}: String interpolation syntax for inline variable substitution within text and attributes.
CSS Theme Custom Properties (--golem-*)
The default Golem theme ("Workbench" / Fired Clay aesthetic) is engineered entirely with parameterized CSS Custom Properties (--golem-*). Theme developers can completely re-skin Golem by overriding these variables in CSS without modifying the underlying HTML template.
Light Mode Palette Tokens
Token | Default Value | Role & Usage |
|
| Main document background color (warm parchment). |
|
| Elevated surfaces: header, sidebar navigation, footer, admonition backgrounds. |
|
| Background for inline code spans ( |
|
| High-contrast primary reading text and headings. |
|
| Secondary captions, metadata, table headers, and inactive links. |
|
| Brand accent color (terracotta / fired clay) used for active links, hover states, and key highlights. |
|
| Interactive hover and active focus state for primary brand elements. |
|
| Subtle borders for sidebar dividers, code blocks, tables, and section separators. |
|
| Standard hyperlink text color. |
|
| Hyperlink hover state color. |
|
| Visited hyperlink text color. |
|
| Accent border color for |
|
| Accent border color for |
|
| Accent border color for |
|
| Accent border color for |
|
| Accent border color for |
|
| Sub-perceptible SVG fractal noise texture overlay applied to the page body. |
Dark Mode Palette Overrides
Golem automatically supports dark mode via @media (prefers-color-scheme: dark). The dark theme uses charcoal and warm ember tones:
@media (prefers-color-scheme: dark) {
:root {
--golem-bg: #170f0b;
--golem-surface: #1e1410;
--golem-code-bg: #2a1e17;
--golem-text: #f0e4d8;
--golem-text-muted: #9a7a68;
--golem-primary: #d4692a;
--golem-primary-hover: #e07a3a;
--golem-border: #3d2a20;
--golem-link: #d4692a;
--golem-link-hover: #e07a3a;
--golem-link-visited: #8a4c32;
/* Admonitions */
--golem-note: #4a9a8a;
--golem-tip: #7aaa3a;
--golem-important: #d4692a;
--golem-warning: #d4a020;
--golem-caution: #c04040;
}
}Typography Tokens
Golem utilizes four distinct font tokens corresponding to functional typography roles:
Token | Default Fallback Stack | Purpose |
|
| Document titles ( |
|
| Main narrative paragraphs, lists, blockquotes, and prose content. |
|
| Sidebar navigation items, table of contents links, metadata badges, table headers, and footers. |
|
| Code blocks ( |
Typographical Scale, Optical Sizing & Line-Height
Golem embraces modern CSS variable fonts with optical sizing controls and proportional leading:
- Optical Sizing (
opsz):body { font-optical-sizing: auto; font-variation-settings: "opsz" 12; line-height: 1.75; } #golem-content h1 { font-variation-settings: "opsz" 36; line-height: 1.2; letter-spacing: -0.01em; } #golem-content h2 { font-variation-settings: "opsz" 24; line-height: 1.3; } #golem-content h3 { font-variation-settings: "opsz" 18; line-height: 1.4; } pre, .listingblock pre { line-height: 1.55; } - Container Sizing & Readability:
The main reading column is constrained for optimal typographical line length (60–75 characters per line):
#golem-content { flex: 1; padding: 2.5rem 3.5rem; max-width: 860px; } - Responsive Breakpoints:
/* Collapses right Table of Contents on medium viewports */ @media (max-width: 1100px) { #golem-sidebar-right { display: none; } #golem-content { padding: 2rem 2.5rem; } } /* Stacks navigation and reading pane into single column on mobile */ @media (max-width: 800px) { #golem-wrapper { flex-direction: column; } #golem-sidebar-left { width: 100%; border-right: none; border-bottom: 1px solid var(--golem-border); } #golem-content { padding: 1.5rem 1.25rem; } }
Loading Custom Web Fonts & External Stylesheets
You can load custom web fonts and external stylesheets across your documentation site using the custom_css setting in your configuration file (golem.toml or pyproject.toml).
In golem.toml
[site]
title = "My Project Docs"
custom_css = [
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap",
"/static/css/custom.css",
]
custom_js = [
"/static/js/theme-switcher.js",
]In pyproject.toml
[tool.golem.site]
title = "My Library Documentation"
custom_css = [
"https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;600&family=Outfit:wght@400;600;700&display=swap",
"/static/css/custom.css",
]Applying Custom Fonts in static/css/custom.css
Once loaded, assign the font families to Golem's typography tokens:
:root {
--golem-font-display: 'Outfit', sans-serif;
--golem-font-body: 'Outfit', sans-serif;
--golem-font-ui: 'Outfit', sans-serif;
--golem-font-mono: 'Fira Code', monospace;
}Overriding skeleton.pt in a Custom Theme
To create a fully customized theme or override Golem's default page structure:
- Create a theme directory:
themes/mytheme/. - Place a
skeleton.pttemplate insidethemes/mytheme/skeleton.pt. - Set
theme = "mytheme"ingolem.tomlunder[build](or[tool.golem.build]inpyproject.toml).
Complete Annotated Custom Theme Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${page_title} - ${site_title}</title>
<meta name="generator" content="${generator_version}" />
<meta tal:condition="site_author" name="author" content="${site_author}" />
<link rel="canonical" tal:condition="site_url" href="${site_url}" />
<!-- External and Custom Stylesheets -->
<tal:block tal:repeat="css_file custom_css">
<link rel="stylesheet" href="${css_file}" />
</tal:block>
<!-- Theme Stylesheet -->
<link rel="stylesheet" href="/static/css/theme.css" />
</head>
<body>
<header class="site-header">
<div class="header-container">
<a href="/" tal:attributes="href site_url or '/'" class="site-logo">${site_title}</a>
<span tal:condition="site_author" class="site-author">By ${site_author}</span>
</div>
</header>
<div class="layout-container">
<!-- Sidebar Navigation -->
<aside class="sidebar-nav">
<div tal:condition="nav_html" tal:replace="structure nav_html" />
<ul tal:condition="not:nav_html and nav_tree">
<li tal:repeat="item nav_tree">
<a href="${item.url}" tal:attributes="href item.url">${item.title}</a>
</li>
</ul>
</aside>
<!-- Main Document Body -->
<main class="content-body">
<h1 tal:condition="page_title">${page_title}</h1>
<div tal:content="structure body_html" />
</main>
<!-- Table of Contents -->
<aside class="sidebar-toc" tal:condition="toc_html">
<h3>On This Page</h3>
<div tal:content="structure toc_html" />
</aside>
</div>
<footer class="site-footer">
<p>Built with Golem ${generator_version}</p>
</footer>
<!-- Custom JavaScript Injections -->
<tal:block tal:repeat="js_file custom_js">
<script src="${js_file}"></script>
</tal:block>
</body>
</html>Distributing Reusable Themes via Python Packages
You can distribute Golem themes as reusable Python packages. Register your theme directory in pyproject.toml using entry points:
[project.entry-points."golem.themes"]
mytheme = "my_theme_package"When installed, users can select your theme simply by setting theme = "mytheme" in their golem.toml.