How Hallmark Handles the Diversification Rule in UI Generation: A Deep Dive into Theme Rotation
Hallmark enforces the diversification rule through a three-axis rotation system that ensures each generated page differs from the previous output on at least one of paper-band, display-style, or accent-hue, while flipping to "must-share" mode when a design.md file locks the project to a consistent visual system.
The diversification rule is the core mechanism that prevents Hallmark from generating repetitive UIs. As implemented in Nutlope/hallmark, this rule operates as a smart theme-rotation engine that reads project memory, compares design axes, and either enforces variety or consistency depending on project context. Understanding this rule is essential for anyone customizing Hallmark's output or debugging unexpected theme selections.
How the Diversification Rule Works in Hallmark
Hallmark's diversification system follows a seven-step pipeline that executes after any existing design memory is loaded. The entire process is documented in [skills/hallmark/SKILL.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md).
Step 1: Check for Project Memory (design.md)
Hallmark first looks for a design.md file at the project root. If present, the diversification rule inverts completely: consecutive pages must share the same theme system rather than differ. This "app mode" treats the repository as a single cohesive application requiring visual consistency.
Step 2: Parse the Last Stamp and Log
When no design.md exists, Hallmark reads the most recent generation record from two sources:
- The CSS/HTML stamp comment embedded in generated files (e.g.,
/* Hallmark · macrostructure: … */) - The
.hallmark/log.jsonfile containing structured history
From these, Hallmark extracts the three diversification axes of the previous run:
| Axis | Description |
|---|---|
| paper-band | The background/surface color system (warm, cool, neutral, etc.) |
| display-style | The structural layout approach (grid, editorial, immersive, etc.) |
| accent-hue | The primary accent color family and saturation strategy |
Step 3: Select a Different Theme
Hallmark picks from approximately 20 catalog themes or generates a custom theme when the brief signals creative intent. The chosen theme must differ from the previous one on at least one of the three axes. This "one-axis minimum" rule prevents identical consecutive outputs while allowing deliberate similarities.
Step 4: Apply Cross-Route Diversification
The diversification check is theme-route-blind. A custom theme following a catalog theme (or another custom theme) must still satisfy the axis-difference requirement. Custom themes explicitly declare their three axes in their metadata so the same validation applies universally. See [custom-theme.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/custom-theme.md#254) for the declaration schema.
Step 5-7: Handle Edge Cases and Persist State
- App mode override: When
design.mdis present, skip catalog rotation and enforce shared axes across all pages ([redesign.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/verbs/redesign.md#222)) - Studied-DNA suspension: If a prior "study" diagnosis supplies concrete DNA (paper, accent, type, macrostructure), diversification is suspended and that exact system is reused ([
SKILL.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md#337)) - Logging: After generation, Hallmark writes a stamp comment and appends to
/.hallmark/log.jsonfor future comparison ([SKILL.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md#461))
The Three Diversification Axes Explained
Each theme in the catalog defines its position on three axes, documented in skills/hallmark/references/themes/*.md.
Axis Definitions
- paper-band: Controls the chromatic temperature of backgrounds—options typically include
warm,cool,neutral,oxide, ormidnight - display-style: Determines the macro-layout philosophy—values like
editorial,immersive,systematic, orbrutalist - accent-hue: Specifies the primary action color and its rotation behavior—some themes fix this, others rotate among a drop set
Rotation Window and Drop-Hue Logic
Certain themes implement extended rotation beyond the basic rule. For example, the Carnival theme defines a "drop" hue that rotates among five possible values, with consecutive builds prohibited from reusing any drop seen in the last 3 entries. This creates a longer memory window than the default single-step comparison. See themes/carnival.md and themes/lumen.md for concrete axis declarations.
Core Diversification Logic in Code
The following pseudo-code illustrates the validation pattern Hallmark uses internally. The real implementation resides in the skill's JavaScript/TypeScript modules and mirrors this structure exactly:
// Diversification rule validation as implemented in Hallmark
import { readFileSync } from 'fs';
import path from 'path';
// 1️⃣ Load the previous generation's axes from log.json
function getPrevAxes(projectRoot) {
const logPath = path.join(projectRoot, '.hallmark', 'log.json');
if (!fs.existsSync(logPath)) return null;
const log = JSON.parse(readFileSync(logPath, 'utf8'));
const last = log[log.length - 1];
return {
paperBand: last.axes.paperBand,
displayStyle: last.axes.displayStyle,
accentHue: last.axes.accentHue,
};
}
// 2️⃣ Extract axes from a catalog theme's markdown file
function getThemeAxes(themeName) {
const themeFile = path.join(
__dirname, 'skills', 'hallmark', 'references', 'themes', `${themeName}.md`
);
const content = readFileSync(themeFile, 'utf8');
// Theme files contain YAML frontmatter with the three axes
const yaml = content.match(/```yaml([\s\S]*?)```/)[1];
return yamlParser(yaml);
}
// 3️⃣ Core diversification test: must differ on at least one axis
function passesDiversification(prev, candidate) {
if (!prev) return true; // First run: any theme is valid
return (
prev.paperBand !== candidate.paperBand ||
prev.displayStyle !== candidate.displayStyle ||
prev.accentHue !== candidate.accentHue
);
}
// 4️⃣ Theme selection with diversification enforcement
function pickTheme(projectRoot, catalogThemes) {
const prev = getPrevAxes(projectRoot);
for (const theme of catalogThemes) {
const axes = getThemeAxes(theme);
if (passesDiversification(prev, axes)) return theme;
}
throw new Error('No theme satisfies diversification – enlarge rotation window');
}
The production code adds two critical extensions: inversion logic for design.md presence (requiring passesConsistency instead of passesDiversification) and custom-theme axis parsing from embedded YAML declarations.
When the Diversification Rule Inverts to "Must-Share"
The most important edge case in Hallmark's diversification rule is the app-mode inversion. Documented in [redesign.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/verbs/redesign.md#222), this behavior triggers when:
- A
design.mdfile exists at project root - Hallmark is invoked for a multi-page application (not a one-off landing page)
- The project explicitly requests consistency across routes
In this mode, the rule flips from "must differ on ≥1 axis" to "must match on all 3 axes." Catalog rotation is skipped entirely, and Hallmark instead:
- Reads the locked theme from
design.md - Validates that all generated pages conform to that theme's axes
- Ignores
log.jsondiversity constraints
This inversion ensures that application UIs feel cohesive rather than disjointed, while still allowing the diversification rule to operate normally for one-off or exploration projects.
Key Source Files for the Diversification Rule
| File | Purpose |
|---|---|
skills/hallmark/SKILL.md |
Central specification of the diversification rule, rotation window, and interaction with project memory |
skills/hallmark/references/verbs/redesign.md |
Inversion logic for multi-page app consistency |
skills/hallmark/references/custom-theme.md |
Axis declaration schema for non-catalog themes |
skills/hallmark/references/themes/*.md |
Per-theme axis definitions and drop-hue rotation rules |
skills/hallmark/references/design-md.md |
Documentation of the "design-first" override mode |
site/_tests/README.md |
Test expectations and planned improvements for diversification |
site/_tests/verbs/redesign/ |
Concrete test cases verifying rule behavior |
Summary
- Hallmark's diversification rule operates on three axes: paper-band, display-style, and accent-hue
- Consecutive generations must differ on at least one axis unless
design.mdis present, which inverts the rule to require consistency - The rule is theme-route-blind: both catalog and custom themes participate in the same validation
- Log persistence in
.hallmark/log.jsonand CSS stamp comments enable cross-run memory - Studied-DNA runs suspend diversification entirely when a precise visual system is diagnosed
Frequently Asked Questions
What happens if no theme satisfies the diversification rule?
Hallmark throws an explicit error: 'No theme satisfies diversification – enlarge rotation window'. In practice, this rarely occurs because the catalog contains ~20 themes with varied axis combinations. If encountered, the solution is to either expand the acceptable theme set or reduce the rotation window (checking fewer historical entries).
How does the diversification rule affect custom themes?
Custom themes must explicitly declare their three axes (paper, display, accent) in their YAML metadata. Once declared, they enter the same diversification pool as catalog themes. A custom theme following any other theme—catalog or custom—must still differ on at least one axis.
Can I disable the diversification rule for a specific project?
Yes. Create a design.md file at your project root. This triggers app-mode inversion, which forces consistency across all generated pages. Alternatively, supply a studied-DNA diagnosis with concrete paper, accent, type, and macrostructure values; Hallmark will suspend diversification and reuse that exact system.
Why does Hallmark look at 3-5 log entries instead of just the last one?
The rotation window prevents rapid cycling between two similar themes. By examining 3-5 historical entries, Hallmark ensures broader palette exploration over time while still allowing deliberate returns to previously used aesthetics after sufficient variety has been generated.
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 →