# How Configuration Is Managed in the Nutlope/hallmark Project

> Discover how the Nutlope/hallmark project manages configuration with a layered, convention-over-configuration system that respects design files and enforces diversification rules.

- Repository: [Hassan El Mghari/hallmark](https://github.com/Nutlope/hallmark)
- Tags: how-to-guide
- Published: 2026-08-10

---

**The Nutlope/hallmark project implements a layered, convention-over-configuration system that discovers existing design assets, respects an optional design lock file, and persists run-time state to cache results and enforce diversification rules across generations.**

The Hallmark skill handles configuration management through a deterministic pipeline defined primarily in [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md). Rather than relying on a single static configuration file, it employs a three-tier architecture that reads from project-level assets, optional design locks, and ephemeral run-time memory to generate UI components while avoiding redundant analysis.

## The Three-Layer Configuration Architecture

Hallmark’s configuration strategy operates across three distinct layers, each serving a specific purpose in the generation lifecycle.

### Project-Level Asset Discovery

At the foundation, Hallmark detects existing design tokens and framework configurations before any user interaction begins. The skill scans for [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), `tailwind.config.*` (JavaScript or TypeScript variants), and DTCG-formatted [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json) files at the repository root. According to the implementation in [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md), these files provide the baseline palette, typography, and spacing values that inform the generation process. When present, their modification times are compared against [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) to determine whether cached analysis remains valid or requires refresh.

### Design-System Lock Files

The second layer introduces an optional but authoritative override through [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) (or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md)). If this file exists at the repository root, Hallmark treats it as the single source of truth for macro-structure, theme definitions, and token exports, superseding dynamic generation. As documented in the "Design.md" section of [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md), this lock file allows teams to stabilize their design system and prevent drift across multiple generation runs.

### Run-Time Memory and Caching

The third layer manages ephemeral state through the `.hallmark/` directory. After each successful run, Hallmark writes a concise stamp to [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json) containing the date, macrostructure, theme, enrichment, and brief used. Simultaneously, [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) caches the pre-flight analysis of detected assets. The structure of these log entries is formally defined in [`skills/hallmark/references/custom-theme.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/custom-theme.md), which specifies how historical data drives diversification logic.

## Detecting Existing Configuration and Cache Invalidation

Hallmark employs specific detection patterns to identify configuration files, coupled with a modification-time-based caching strategy to optimize performance.

### Tailwind and DTCG Detection

The skill identifies Tailwind configurations by scanning for any file matching the glob `tailwind.config.*`. For design tokens, it looks specifically for a top-level [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json) file in the DTCG (Design Tokens Community Group) format. The presence of these files triggers palette extraction logic described in the "Palette" section of [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md).

### Cache Validation Logic

To avoid re-scanning unchanged projects, Hallmark compares the modification times (`mtime`) of detected configuration files against the timestamp stored in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json). If any source file is newer than the cache, the skill discards the pre-flight data and executes a fresh analysis. This mechanism ensures that manual edits to [`tailwind.config.js`](https://github.com/Nutlope/hallmark/blob/main/tailwind.config.js) or [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json) immediately invalidate stale caches without requiring explicit cache clearing commands.

## Persistence and Diversification Mechanics

Beyond caching, Hallmark uses persisted state to ensure creative variety across consecutive runs.

### The Log File Structure

Each generation appends an entry to [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json) with the following shape:

```json
{
  "date": "ISO-8601 timestamp",
  "macrostructure": "layout-archetype-id",
  "theme": "theme-configuration-hash",
  "enrichment": "content-enrichment-level",
  "brief": "generation-brief-summary"
}

```

As specified in [`skills/hallmark/references/custom-theme.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/custom-theme.md), the system maintains the 20 most recent entries, discarding older records to prevent unbounded file growth.

### Diversification Rules

Before generating new macro-structures, Hallmark reads the historical log and enforces diversification across three axes: **paper-band**, **display-style**, and **accent-hue**. The logic guarantees that at least one of these axes differs from the immediately previous entry, preventing repetitive outputs. This rule applies uniformly to both catalog-based and custom-theme generation runs, as detailed in the "Diversification" sections of [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) and [`skills/hallmark/references/custom-theme.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/custom-theme.md).

## Practical Implementation Examples

The following patterns illustrate how Hallmark accesses these configuration layers programmatically. While the actual skill uses internal helpers, the logic mirrors these standard Node.js patterns.

Detecting and loading a Tailwind configuration:

```javascript
import fs from 'fs';
import path from 'path';

function loadTailwindConfig(projectRoot) {
  const candidates = ['tailwind.config.js', 'tailwind.config.cjs', 'tailwind.config.ts'];
  for (const file of candidates) {
    const fullPath = path.join(projectRoot, file);
    if (fs.existsSync(fullPath)) {
      return fs.readFileSync(fullPath, 'utf8');
    }
  }
  return null;
}

```

Reading the optional design lock file:

```javascript
function readDesignLock(projectRoot) {
  const lockPath = path.join(projectRoot, 'design.md');
  return fs.existsSync(lockPath) ? fs.readFileSync(lockPath, 'utf8') : null;
}

```

Appending to the run-time log with history truncation:

```javascript
function appendLog(projectRoot, entry) {
  const logPath = path.join(projectRoot, '.hallmark', 'log.json');
  const logs = fs.existsSync(logPath) 
    ? JSON.parse(fs.readFileSync(logPath, 'utf8')) 
    : [];
  
  logs.unshift(entry); // newest first
  
  fs.mkdirSync(path.dirname(logPath), { recursive: true });
  fs.writeFileSync(logPath, JSON.stringify(logs.slice(0, 20), null, 2));
}

```

## Summary

- Hallmark uses a **three-layer configuration system**: project-level asset detection, optional [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) locks, and run-time memory in `.hallmark/`.
- **Cache invalidation** relies on file modification times to ensure `tailwind.config.*` or [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json) changes trigger fresh analysis.
- The **[`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json)** file maintains a rolling history of the last 20 generations to enforce diversification rules.
- **Diversification** requires that consecutive runs differ in at least one of three axes: paper-band, display-style, or accent-hue.
- Client-side configuration persistence in the Hallmark UI uses constants defined in [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js), such as `STORAGE_KEY = "hallmark-theme"`.

## Frequently Asked Questions

### How does Hallmark decide whether to use cached configuration or perform a fresh scan?

Hallmark compares the modification timestamps of detected configuration files (`tailwind.config.*`, [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json), [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json)) against the timestamp stored in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json). If any source file has been modified more recently than the cache, the skill discards the cached data and re-runs the pre-flight analysis to ensure accuracy.

### What is the purpose of the [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) file in Hallmark?

The [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) (or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md)) file serves as an optional design-system lock. When present at the repository root, Hallmark reads this file first and treats its contents as the authoritative source for macro-structure, theme definitions, and token exports. This overrides dynamic generation and ensures consistent output across multiple runs.

### How does Hallmark prevent generating the same layout repeatedly?

Before each generation, Hallmark reads [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json) to inspect the previous run's characteristics. It enforces a diversification rule that requires the new output to differ from the immediate predecessor in at least one of three specific axes: paper-band, display-style, or accent-hue. This ensures creative variety while maintaining design coherence.

### Where does Hallmark store its configuration cache and history?

Hallmark stores transient configuration analysis in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) and maintains a project-wide generation history in [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json). Both files reside in a `.hallmark/` directory at the project root. The log file retains the 20 most recent entries to support diversification logic without allowing the file size to grow indefinitely.