How the Hallmark Theme-Diversification Rule Works: Paper-Band, Display-Style, and Accent-Hue
The Hallmark theme-diversification rule guarantees that consecutive page generations use perceptually distinct themes by requiring each new selection to differ from the previous theme on at least one of three orthogonal axes: paper-band lightness, display-style typeface category, or accent-hue angle.
The Nutlope/hallmark repository implements this diversification system to prevent "same-theme-again" slop across consecutive builds. By evaluating candidate themes against three independent aesthetic dimensions defined in site/css/tokens.css, the algorithm ensures that each new page feels visually fresh while respecting the catalog’s structured design language. The rule operates by comparing potential selections against the most recent entry stored in .hallmark/log.json.
The Three Orthogonal Axes
The theme-diversification rule measures perceptual difference across three independent properties. Each theme in the 20-theme catalog declares specific values for these axes in site/css/tokens.css.
Paper-Band Lightness
The paper-band axis categorizes the lightness of the --color-paper token using OKLch percentages. Values fall into three bands:
- Dark: Less than 30% lightness
- Mid: Between 30% and 85% lightness
- Light: Greater than 85% lightness
For example, the Specimen theme declares oklch(96% …) for its paper color according to the comment in site/css/tokens.css (line 16), placing it in the light band.
Display-Style Typography
The display-style axis identifies the typeface family of the --font-display token. The system recognizes ten distinct categories:
- High-contrast-serif
- Roman-serif
- Classical-serif
- Geometric-sans
- Grotesk-sans
- Rounded-sans
- Mono
- Condensed-display
- Heavy-display
- Risograph-bold
As defined in site/css/tokens.css (line 34), the Midnight theme uses a geometric-sans stack, while other themes may declare heavy-display or roman-serif variants.
Accent-Hue Classification
The accent-hue axis measures the hue angle of the --color-accent token, grouped into four perceptual categories:
- Warm: 10° to 60° (reds, oranges, yellows)
- Cool: 200° to 300° (blues, purples)
- Neutral: Achromatic or near-zero chroma
- Chromatic-other: Distinct hues like greens (used for the
Studiotheme)
In site/css/tokens.css (line 69), the Brutal theme defines --color-accent: #E63946, which maps to a warm hue angle, satisfying the warm classification.
The Theme Selection Algorithm
When Hallmark generates a new page, it executes a five-step decision flow to enforce diversification. According to skills/hallmark/SKILL.md (lines 74-82), the process works as follows:
-
Read the previous state. The algorithm inspects the last entry in
.hallmark/log.jsonto retrieve the previous theme’s axis values. If the file does not exist, this indicates the first run and any theme may be selected. The logging schema is documented inskills/hallmark/SKILL.md(lines 99-110). -
Enumerate candidates. The system loads all 20 named themes from the catalog and extracts their three axis values from
site/css/tokens.css. -
Compare axes. For each candidate, the algorithm checks against the previous theme:
- If all three axes match, the candidate is rejected.
- If any one axis differs, the candidate is acceptable.
-
Select and announce. The first acceptable candidate is chosen (or the one matching additional user signals). Hallmark announces the selection before generation, for example: "Theme: Bloom. Differs from the last on: accent-hue."
-
Log the result. The chosen theme’s axis values are recorded in
.hallmark/log.jsonfor the next run’s diversification check.
This permissive rule allows themes to share two axes as long as the third differs, creating a rich rotation of visual styles.
Implementation Examples
The diversification logic can be implemented in code by comparing axis values directly:
// Function that decides if a candidate theme satisfies diversification
function passesDiversification(prev, candidate) {
const diffPaper = prev.paperBand !== candidate.paperBand;
const diffDisplay = prev.displayStyle !== candidate.displayStyle;
const diffAccent = prev.accentHue !== candidate.accentHue;
return diffPaper || diffDisplay || diffAccent;
}
To inspect the last logged theme manually:
# View the previous theme name from the log
cat .hallmark/log.json | jq '.[0].theme'
# → "specimen"
# Show its axis values from the CSS tokens
grep -A3 "\[data-theme=\"specimen\"\]" site/css/tokens.css
The CSS tokens for the Brutal theme demonstrate how the three axes manifest in code:
[data-theme="brutal"] {
--color-paper: oklch(98% 0.001 0); /* light band */
--font-display: "Albert Sans", "GT America", ui-sans-serif, sans-serif; /* heavy-condensed style */
--color-accent: #E63946; /* warm hue */
}
Summary
- The theme-diversification rule operates on three independent axes: paper-band lightness, display-style typography, and accent-hue angle.
- Candidate themes must differ from the previous selection in
.hallmark/log.jsonon at least one axis to be acceptable. - Axis values are defined in
site/css/tokens.csswithin each theme’s CSS custom properties. - The algorithm prevents visual repetition while allowing themes to share two axes if the third differs.
- Selections are persisted to
.hallmark/log.jsonto inform future diversification checks.
Frequently Asked Questions
What happens if there is no previous theme in the log?
If .hallmark/log.json does not exist or contains no entries, Hallmark treats this as the initial run. Any theme from the 20-theme catalog may be selected without diversification restrictions, as there is no prior state to compare against.
Can two themes share two axes but still be selected consecutively?
Yes. The rule is deliberately permissive: a theme only needs to differ on one of the three axes to be acceptable. For example, a new theme may share the same paper-band (light) and display-style (geometric-sans) as the previous theme, provided the accent-hue changes from warm to cool.
Where are the axis values defined for each theme?
Each theme’s axis values are derived from three CSS custom properties in site/css/tokens.css: --color-paper defines the paper-band, --font-display defines the display-style, and --color-accent defines the accent-hue. The human-readable testing documentation in site/_tests/README.md (line 69) also describes these classifications.
How does the rule prevent "same-theme-again" slop?
By requiring at least one axis change from the previous entry in .hallmark/log.json, the system guarantees that consecutive outputs cannot be visually identical. Because the three axes are orthogonal, Hallmark can rotate through many theme combinations before any single axis repeats, ensuring each generated page maintains perceptual distinctiveness.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →