# How Hallmark Manages Configuration: A Layered Discovery and Caching System

> Discover how Hallmark manages configuration with a layered system. It caches settings, logs history, and respects design specs for efficient project management. Learn more!

- Repository: [Hassan El Mghari/hallmark](https://github.com/Nutlope/hallmark)
- Tags: internals
- Published: 2026-08-03

---

**Hallmark uses a layered configuration system that discovers existing project settings, caches them in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json), maintains a run history in [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json), and respects user-provided design specifications via [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md).**

Configuration management in Hallmark is designed to be **non-intrusive, repeatable, and progressively diverse**. Rather than forcing preset values onto your project, Hallmark inspects your existing codebase on every run, persists its findings for performance, and ensures successive builds vary visually. This approach is defined and implemented in the `Nutlope/hallmark` repository.

---

## Project Discovery: Reading Your Existing Setup

Hallmark begins each run by scanning your repository for classic web-project files. This **discovery layer** prevents Hallmark from overwriting design systems you've already established.

The inspection covers:

- [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) – for dependencies and project metadata
- [`tailwind.config.js`](https://github.com/Nutlope/hallmark/blob/main/tailwind.config.js) or [`tailwind.config.ts`](https://github.com/Nutlope/hallmark/blob/main/tailwind.config.ts) – for custom fonts, colors, and theme extensions
- [`index.html`](https://github.com/Nutlope/hallmark/blob/main/index.html) and any CSS files – for inline styles and existing design tokens
- Token files: [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json), `design-tokens.{json,yaml}`, or [`tokens.css`](https://github.com/Nutlope/hallmark/blob/main/tokens.css)

According to the skill definition in [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) (line 149), Hallmark "reads [existing code] before asking the user anything." It extracts your **font stack**, **color palette**, and **spacing scale** directly from these sources.

---

## The Pre-Flight Cache: [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json)

To avoid expensive file-system scans on every run, Hallmark implements a **caching layer** that stores discovery results.

The cache lives at [`./.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/./.hallmark/preflight.json) and is created automatically on first run. Hallmark uses **modification-time comparison** to determine cache validity:

- If [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or `tailwind.config.*` has been modified since the cache was written, the cache is regenerated
- Otherwise, Hallmark reuses the cached snapshot

This behavior is documented in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) (line 177): *"Write the findings to [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) once … unless [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) / `tailwind.config.*` mtimes are newer."*

```javascript
import fs from "fs";
import path from "path";

const projectRoot = process.cwd();
const preflightPath = path.join(projectRoot, ".hallmark", "preflight.json");

function needsRecalc() {
  if (!fs.existsSync(preflightPath)) return true;

  const preflightMtime = fs.statSync(preflightPath).mtimeMs;
  const pkgMtime = fs.statSync(path.join(projectRoot, "package.json")).mtimeMs;
  const twConfig = fs.existsSync("tailwind.config.ts") 
    ? "tailwind.config.ts" 
    : "tailwind.config.js";
  const twMtime = fs.statSync(twConfig).mtimeMs;

  return pkgMtime > preflightMtime || twMtime > preflightMtime;
}

const preflight = needsRecalc()
  ? generatePreflight(projectRoot)
  : JSON.parse(fs.readFileSync(preflightPath, "utf-8"));

```

---

## Project-Level Memory: [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json)

Hallmark maintains a **run history** to enforce visual diversification across successive builds. This log prevents repetitive outputs and drives intelligent theme selection.

The log file [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json) stores:

- Date of each run
- Selected **macrostructure** (e.g., "hero-grid")
- Applied **theme** (e.g., "carnival")
- **Enrichment** settings
- Brief description of the build

```javascript
const logPath = path.join(projectRoot, ".hallmark", "log.json");
let log = fs.existsSync(logPath) 
  ? JSON.parse(fs.readFileSync(logPath, "utf-8")) 
  : [];

const entry = {
  date: new Date().toISOString().split("T")[0],
  macrostructure: "hero-grid",
  theme: "carnival",
  enrichment: "none",
  brief: "Landing page for a coffee brand"
};

log.unshift(entry);
log = log.slice(0, 20);  // retain only last 20 runs
fs.mkdirSync(path.join(projectRoot, ".hallmark"), { recursive: true });
fs.writeFileSync(logPath, JSON.stringify(log, null, 2));

```

Before selecting a new macrostructure or theme, Hallmark reads this log to ensure at least one visual axis differs from recent runs—this is the **diversification rule** (see [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md), line 462).

---

## Locked Design System: [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) Override

For projects requiring strict design control, Hallmark supports a **locked specification** via [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md) at the project root.

This file takes **absolute precedence** over all automatic inference. When present:

- Hallmark reads [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) **before** any other configuration step
- Automatic theme selection is bypassed
- All palette, typography, and macrostructure decisions defer to the locked spec

As stated in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) (line 153): *"[`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) – at the project root … overrides everything else."*

```javascript
const designPath = path.join(projectRoot, "design.md");
if (fs.existsSync(designPath)) {
  const designSpec = fs.readFileSync(designPath, "utf-8");
  applyDesignSpec(designSpec);  // parse and apply locked values
} else {
  // proceed with normal discovery and token generation
}

```

---

## Design Tokens and Tailwind Integration

Hallmark integrates deeply with **Tailwind CSS** configurations and design token standards.

### Token File Support

Hallmark recognizes DTCG-shaped token files:

- [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json)
- `design-tokens.{json,yaml}`
- [`tokens.css`](https://github.com/Nutlope/hallmark/blob/main/tokens.css)

When present, Hallmark consumes these directly and injects them into the generated Tailwind configuration (see [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md), line 155).

### Tailwind Config Reading

Hallmark reads your existing `tailwind.config.{js,ts}` to:

- Extract custom colors and fonts
- Determine whether to extend or replace values
- Handle Tailwind v4's `@theme` syntax (see [`skills/hallmark/references/export-formats.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/export-formats.md), line 210)

Hallmark may add `@source` directives but never forces `theme.extend` blocks unless your config lacks required values.

---

## Client-Side UI State

The Hallmark demo site stores interface preferences separately from build-time configuration. In [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js), the selected UI theme is persisted in `localStorage`:

```javascript
const STORAGE_KEY = "hallmark-theme";

```

This is purely for the showcase UI and does not affect the build process.

---

## Configuration Flow Summary

The complete Hallmark configuration management flow operates as follows:

1. **Detect existing assets** – scan [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), `tailwind.config.*`, HTML, CSS, and token files
2. **Load or regenerate pre-flight cache** – check [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) against source mtimes
3. **Check for locked design** – if [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) exists, use it exclusively
4. **Read project log** – parse [`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json) to enforce diversification rules
5. **Generate output** – create or extend Tailwind config, write tokens, update run log

---

## Summary

- **Discovery layer** reads existing project files to avoid overwriting established designs
- **[`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json)** caches discovery results for performance, with mtime-based invalidation
- **[`.hallmark/log.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json)** maintains run history to enforce visual diversification across builds
- **[`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md)** provides optional locked design specification that overrides all automatic inference
- **Token files and Tailwind config** are consumed directly as design token sources
- **`.hallmark/` directory** is gitignored to prevent committing runtime cache files

---

## Frequently Asked Questions

### What happens if I delete the `.hallmark/` directory?

Hallmark will recreate it on the next run. The pre-flight discovery will execute fresh, reading all source files to rebuild [`preflight.json`](https://github.com/Nutlope/hallmark/blob/main/preflight.json). Your run history in [`log.json`](https://github.com/Nutlope/hallmark/blob/main/log.json) will reset, so the diversification rule may temporarily allow repeats of recent macrostructures or themes.

### Can I commit my Hallmark configuration to version control?

Only commit files you create explicitly. The `.hallmark/` folder is gitignored by default and should remain uncommitted—it contains auto-generated cache and log data. However, [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md), [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json), or custom `tailwind.config.*` changes should be committed as they represent your intentional design decisions.

### How does Hallmark handle Tailwind CSS v4?

Hallmark reads the newer `@theme` syntax directly from CSS files, as documented in [`skills/hallmark/references/export-formats.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/export-formats.md) (line 210). It differentiates between v3's JavaScript-based configuration and v4's CSS-native theming to extract colors and fonts appropriately.

### Why does my second Hallmark run complete faster?

The pre-flight cache eliminates redundant file-system scans. On first run, Hallmark discovers and writes [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json). On subsequent runs, it compares modification times against this cache and reuses the stored snapshot unless your [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or Tailwind config has changed.