# How the Hallmark Pre-flight Cache Works: A Deep Dive into Configuration Caching

> Discover how the Hallmark pre-flight cache speeds up your builds by storing and reusing project analysis data. Learn its configuration and caching mechanisms.

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

---

**Hallmark's pre-flight cache stores project analysis findings in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) and reuses them on subsequent runs unless [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or `tailwind.config.*` files have newer modification times.**

Hallmark is an open-source project README generator by **Nutlope** that analyzes your codebase to create polished documentation. To avoid repeated expensive analysis, it implements a sophisticated caching mechanism that balances speed with accuracy. This article explains exactly how the pre-flight cache operates, when it invalidates, and how you can rely on it for fast, repeatable builds.

## What Is the Hallmark Pre-flight Cache?

The **pre-flight cache** is Hallmark's mechanism for persisting project configuration analysis. When Hallmark first processes a repository, it runs a pre-flight step that inspects:

- [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) for project metadata and dependencies
- `tailwind.config.*` files for styling decisions
- Other build configuration files that affect output

From this inspection, Hallmark computes **findings**—the macrostructure, theme selection, enrichment decisions, and image assets. Rather than recomputing these on every run, Hallmark writes them once to a JSON file and reuses the cached data when appropriate.

## Where the Cache Lives

Hallmark stores pre-flight findings at:

```

.project-root/.hallmark/preflight.json

```

This path is created relative to your project's root directory. The `.hallmark/` directory is typically gitignored, ensuring cached data remains local to each developer's environment and CI runner.

## Cache Invalidation Rules

According to the [Hallmark skill definition in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md)](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) (lines 177-179), the cache becomes stale when either condition is met:

1. **[`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or any `tailwind.config.*` file has a newer modification time** than the cached [`preflight.json`](https://github.com/Nutlope/hallmark/blob/main/preflight.json)
2. **The cache has exceeded its TTL**—Hallmark can enforce time-based expiry similar to the GitHub star-count caching pattern demonstrated in [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js)

When stale, Hallmark re-executes the full pre-flight analysis, overwrites [`preflight.json`](https://github.com/Nutlope/hallmark/blob/main/preflight.json) with fresh findings, and continues processing.

## How Hero Enrichment Uses Cached Data

The pre-flight cache serves double duty. In the **hero-enrichment** step, if you've attached an image asset, Hallmark prefers the already-cached image data stored in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) rather than re-downloading or regenerating a placeholder.

This design avoids redundant network requests and ensures consistent hero image handling across multiple README generation runs. The hero-enrichment logic is detailed in [[`hero-enrichment.md`](https://github.com/Nutlope/hallmark/blob/main/hero-enrichment.md)](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/hero-enrichment.md).

## Implementing the Cache Logic: Code Walkthrough

The following simplified implementation mirrors Hallmark's actual cache behavior:

```javascript
import { readFileSync, writeFileSync, existsSync, statSync } from 'fs';
import { join } from 'path';

const ROOT = process.cwd();
const CACHE_PATH = join(ROOT, '.hallmark', 'preflight.json');
const CONFIG_FILES = ['package.json', 'tailwind.config.js'];

/**
 * Return true if any config file is newer than the cache.
 */
function isCacheStale() {
  if (!existsSync(CACHE_PATH)) return true;
  
  const cacheMtime = statSync(CACHE_PATH).mtimeMs;
  
  return CONFIG_FILES.some(f => {
    const cfgPath = join(ROOT, f);
    return existsSync(cfgPath) && statSync(cfgPath).mtimeMs > cacheMtime;
  });
}

/**
 * Load cached pre-flight data or recompute it.
 */
function getPreflightData() {
  if (!isCacheStale()) {
    const raw = readFileSync(CACHE_PATH, 'utf8');
    return JSON.parse(raw);
  }

  // Expensive analysis only runs when cache is stale
  const findings = runPreflightAnalysis(ROOT);

  const payload = { ...findings, _cachedAt: Date.now() };
  writeFileSync(CACHE_PATH, JSON.stringify(payload, null, 2));
  
  return findings;
}

```

Key observations about this implementation:

- **`isCacheStale()`** implements the exact mtime comparison rule from [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md)
- **`_cachedAt`** timestamp enables optional TTL-based expiry
- **Atomic write pattern**: findings are computed fully before writing, preventing corrupt cache states

## Performance Characteristics

| Scenario | Behavior | Typical Latency |
|----------|----------|---------------|
| Cold start (no cache) | Full pre-flight analysis | Hundreds of milliseconds |
| Warm cache, fresh configs | Cache hit | < 5 ms (JSON parse only) |
| Stale cache (config changed) | Re-analysis + cache write | Similar to cold start |

The pre-flight cache transforms Hallmark from a per-run analysis tool into a near-instant documentation generator for iterative README editing.

## Key Files in the Hallmark Repository

| File | Role in Pre-flight Caching |
|------|---------------------------|
| [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) | Documents persistence policy and invalidation rules |
| [`skills/hallmark/references/hero-enrichment.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/hero-enrichment.md) | Shows cache reuse for image asset handling |
| [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) (generated) | On-disk cache storing computed findings |
| [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js) | Demonstrates TTL/stale-while-revalidate patterns that inspired the cache design |

## Summary

- Hallmark's **pre-flight cache** persists analysis findings to [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json)
- Cache invalidation triggers on **mtime changes** to [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or `tailwind.config.*` files
- The same cache supports **hero-enrichment** image data for consistent asset handling
- TTL-based expiry is available for environments requiring time-bounded freshness
- This architecture delivers sub-5ms repeated runs while guaranteeing accurate output when configurations change

## Frequently Asked Questions

### How do I force Hallmark to ignore the pre-flight cache?

Delete [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) from your project root. On the next run, Hallmark will perform a full pre-flight analysis as if processing the repository for the first time.

### Does the pre-flight cache include generated README content?

No. The cache stores only **findings**—the metadata, structural decisions, and image references needed to generate documentation. The final README is always freshly rendered from these findings.

### Will changes to my source code invalidate the pre-flight cache?

Not directly. The cache monitors **configuration files** ([`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), `tailwind.config.*`) rather than source files. If your code changes affect the README structure, modify [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or touch the cache file to trigger re-analysis.

### Is the `.hallmark/` directory safe to commit to version control?

Generally **no**. Add `.hallmark/` to your `.gitignore`. The cache contains environment-specific paths and timestamps that could cause inconsistencies across machines. It regenerates quickly on each fresh clone.