# How Hallmark Detects Existing Design Systems During Its Pre‑Flight Scan

> Learn how Hallmark's pre-flight scan detects design systems using a cached multi-signal approach. It prioritizes design.md files and falls back to project metadata for efficient identification.

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

---

**Hallmark uses a cached, multi‑signal pre‑flight scan that prioritizes a [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) file, falls back to project metadata like [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or Tailwind configs, and persists results to [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json) for subsequent runs.**

The Hallmark CLI begins every generation with a **pre‑flight scan** (Step 0) whose sole purpose is to discover existing design‑system artifacts. This discovery phase ensures that Hallmark respects established conventions rather than introducing conflicting styles. According to the [Hallmark source code](https://github.com/Nutlope/hallmark), the scan operates through a deterministic priority: cache validation, locked design‑system detection, signal aggregation, and finally user‑controlled refresh.

## How the Pre‑Flight Scan Works Step by Step

The detection logic in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) defines five sequential stages that execute on every Hallmark invocation.

### 1. Cache Lookup at [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json)

Hallmark first checks for a cached result at [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json). If the file exists **and** the project files—specifically [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or any `tailwind.config.*`—have not been modified more recently than the cache, the scan short‑circuits and re‑uses the stored results.

This optimization eliminates redundant filesystem traversal across repeated runs. The cache comparison relies on file modification timestamps rather than content hashing.

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

When the cache is stale or absent, Hallmark probes the project root for **[`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md)** or **[`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md)**. The presence of this file signals a **locked design system**—either generated by a previous Hallmark run or authored manually.

According to [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) → "design.md", when this file is detected:

- Hallmark reads it immediately
- Its contents **override** all other signals
- No further heuristic scanning occurs

This priority ensures human‑curated design specifications take absolute precedence.

### 3. Signal Aggregation for Undetected Systems

If no [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) exists, Hallmark proceeds to gather **implicit signals** from the project structure:

- [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) dependencies and scripts
- Tailwind configuration files ([`tailwind.config.js`](https://github.com/Nutlope/hallmark/blob/main/tailwind.config.js), [`tailwind.config.ts`](https://github.com/Nutlope/hallmark/blob/main/tailwind.config.ts), etc.)
- Existing CSS files or style conventions

These signals inform Hallmark whether the project uses Tailwind, CSS modules, or vanilla CSS, which steers subsequent code generation.

Results from this aggregation are written once to [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json) for future cache hits, as documented in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) → Persistence.

### 4. User‑Controlled Refresh Mechanism

Users can bypass the cache entirely through explicit commands:

- `"refresh pre‑flight"`
- `"scan again"`

When triggered, Hallmark ignores [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json) and re‑executes the full filesystem examination. This is essential when project dependencies or configurations change without modifying the monitored files.

### 5. Outcome Messages and User Visibility

The scan concludes by emitting a **pre‑flight block** that communicates its findings:

| Message | Condition |
|---------|-----------|
| *"design.md detected … reading the locked design system"* | [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md) found |
| *"No pre‑flight signals — proceeding with full Hallmark stack."* | No detectable design‑system cues |
| *"Pre‑flight cached … Say 'refresh pre‑flight' to re‑scan."* | Cache successfully re‑used |

These messages surface the detection state to the user, preventing silent misalignment between expectations and actual behavior.

## Pre‑Flight Detection Logic in Code

The implementation follows the priority sequence described in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md). Below is the core detection flow:

```typescript
// Pre‑flight scan implementation (derived from SKILL.md)
const preflightCache = '.hallmark/preflight.json';
const designFile = findFile(['design.md', 'DESIGN.md']);

let preflightData: PreflightResult;

// 1️⃣ Attempt cache re‑use
if (fs.existsSync(preflightCache) && !projectChangedSince(preflightCache)) {
  preflightData = JSON.parse(fs.readFileSync(preflightCache, 'utf8'));
} else {
  // 2️⃣ Locked design system detection
  if (designFile) {
    preflightData = {
      type: 'design-system',
      path: designFile,
      content: fs.readFileSync(designFile, 'utf8')
    };
  } else {
    // 3️⃣ Aggregate implicit signals
    preflightData = scanForSignals();
  }

  // 4️⃣ Persist for subsequent runs
  fs.writeFileSync(preflightCache, JSON.stringify(preflightData));
}

// 5️⃣ Surface result to user
emitPreflightMessage(preflightData);

```

The `findFile` utility performs case‑insensitive matching against the allowed [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) variants. The `scanForSignals` function encapsulates the Tailwind and [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) inspection logic.

## Key Source Files for Pre‑Flight Behavior

| File | Role in Design‑System Detection |
|------|--------------------------------|
| [[`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md)](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) | Canonical specification of pre‑flight steps, cache semantics, and [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) override priority |
| [`design‑md.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/design-md.md) | Formal definition of the portable [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) format that pre‑flight scanning targets |
| [`hero‑enrichment.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/hero-enrichment.md) | Documents cache reuse for [`preflight.json`](https://github.com/Nutlope/hallmark/blob/main/preflight.json) image assets |
| [`export‑formats.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/export-formats.md) | Lists conditional outputs (e.g., Tailwind `@theme`) emitted only when a design system is confirmed detected |

## Summary

- **Hallmark pre‑flight scan** runs as Step 0 of every invocation to discover existing design systems.
- **Cache first**: Checks [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json) and validates freshness against [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) and `tailwind.config.*` timestamps.
- **Locked system priority**: A [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md) file immediately overrides all other signals.
- **Fallback heuristics**: Scans [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), Tailwind configs, and CSS when no locked system exists.
- **Persistence**: writes aggregated signals to [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json) for cache hits.
- **User override**: "refresh pre‑flight" and "scan again" commands force full re‑examination.

## Frequently Asked Questions

### What file does Hallmark check first during pre‑flight detection?

Hallmark first checks [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json). If this cache file exists and the project's [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) or Tailwind configuration files have not been modified since the cache was written, Hallmark re‑uses the cached results without further filesystem inspection.

### How does Hallmark prioritize a manual design system over auto‑detection?

Hallmark prioritizes any [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md) file found in the project root. When detected, Hallmark reads this file immediately and treats its contents as the authoritative design system, skipping all other signal aggregation. This "locked design system" behavior ensures manual specifications cannot be accidentally overwritten.

### Can I force Hallmark to re‑scan my project if dependencies change?

Yes. Use the commands `"refresh pre‑flight"` or `"scan again"` to instruct Hallmark to ignore [`/.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main//.hallmark/preflight.json) and perform a complete fresh scan of the project. This is necessary when design‑related dependencies or configurations change without touching the monitored cache validation files.

### What happens if Hallmark finds no design‑system signals at all?

Hallmark emits the message *"No pre‑-flight signals — proceeding with full Hallmark stack"* and continues generation using its default, uncustomized output. No [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) is created or assumed; the project is treated as a vanilla codebase without existing design‑system constraints.