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.json file 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

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, or midnight
  • display-style: Determines the macro-layout philosophy—values like editorial, immersive, systematic, or brutalist
  • 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:

  1. A design.md file exists at project root
  2. Hallmark is invoked for a multi-page application (not a one-off landing page)
  3. 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.json diversity 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.md is 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.json and 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →