# How Hallmark's Pre‑flight Scan Detects Design Systems & Frameworks

> Discover how Hallmark's pre-flight scan automatically detects design systems, frameworks, fonts, and colors, caching findings to preserve your design tokens. Learn more today!

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

---

**Hallmark's pre‑flight scan is an automatic, lightweight analysis that runs at startup to detect existing fonts, color palettes, spacing scales, motion libraries, and frameworks—then caches the findings in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) to avoid overwriting established design tokens.**

Every time Hallmark starts, it performs a **pre‑flight scan** to understand what design assets and technical choices already exist in your codebase. This prevents the tool from clobbering custom fonts, hand‑tuned color systems, or framework‑specific conventions. According to the Hallmark source code in [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md), the scan triggers automatically when certain files are present and follows a strict priority order for resolving conflicting signals.

## When the Pre‑flight Scan Runs

The scan executes **without user intervention** if the repository contains any of these entry points: [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), `tailwind.config.*`, [`index.html`](https://github.com/Nutlope/hallmark/blob/main/index.html), or any CSS file `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L45-L50】`.

Results are stored in **[`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json)**. On subsequent runs, Hallmark reuses this cache unless source files have newer modification times or the user explicitly requests a refresh `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L77-L81】`.

## Six Signal Sources Hallmark Examines

The pre‑flight detection follows a strict priority order, with [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) taking absolute precedence:

| Priority | Signal | Detection Location |
|----------|--------|------------------|
| **0** | **[`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) / [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md)** | Project root—treated as locked design system overriding all other signals `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L53-L55】` |
| **1** | **Font stack** | [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) (`next/font`, `@fontsource/*`, `expo-google-fonts`, `geist`), HTML `<link>` tags, `tailwind.config.*` `theme.extend.fontFamily`, CSS `@import` statements `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L54-L56】` |
| **2** | **Palette** | `:root` CSS custom properties, `tailwind.config` `theme.extend.colors`, DTCG token files ([`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json), `design‑tokens.{json,yaml}`) `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L55-L56】` |
| **3** | **Motion stance** | [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) presence of `framer-motion`, `gsap`, `motion`, `lenis`, `lottie‑react`, `@react‑spring/*`, `auto‑animate` = "motion‑on"; absence = "motion‑cut" `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L56-L57】` |
| **4** | **Spacing scale** | Tailwind `theme.extend.spacing`, `--space-*` CSS variables, 4‑pt/8‑pt scale definitions `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L57-L58】` |
| **5** | **Framework** | `next`, `astro`, `vue`, `svelte`/`@sveltejs/kit`, `@remix-run/*`, or vanilla HTML fallback `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L58-L59】` |

## Pre‑flight Output Format

On first run, Hallmark prints a structured summary showing detected assets and its preservation strategy:

```text
Pre‑flight findings:
· Font stack: Geist + Geist Mono (next/font, package.json L23)
· Palette: OKLCH custom properties (app/globals.css :root)
· Motion: framer‑motion 11 installed (package.json L41)
· Spacing: Tailwind extend.spacing (4‑pt scale, tailwind.config.ts L18)
· Framework: Next.js 15 (app router)

Hallmark will preserve: font stack, palette, spacing scale.
Hallmark will introduce: macrostructure, microinteraction discipline,
slop‑test gates, hero enrichment recipe.

```

If cached results are reused, Hallmark notes the timestamp and offers a refresh option `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L81-L82】`.

## Edge Cases in Design System Detection

### Locked Design System Override

When [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) exists, Hallmark treats it as the **authoritative source** and defers all subsequent picks to its definitions `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L85-L87】`.

### Empty Repository Fallback

For repos with no detectable signals, Hallmark proceeds with a full stack and explicitly notes the absence of pre‑flight data `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L87-L89】`.

### Conflicting Signal Resolution

If signals contradict—e.g., a font library installed but a hard‑coded font in CSS—Hallmark flags the conflict and prompts for user clarification `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L88-L89】`.

## Working with Pre‑flight Data Programmatically

These examples mirror Hallmark's internal detection logic for custom tooling or debugging:

### Reading the Cache

```javascript
import { readFileSync, existsSync } from "fs";
import path from "path";

const preflightPath = path.resolve(".hallmark", "preflight.json");

if (existsSync(preflightPath)) {
  const cache = JSON.parse(readFileSync(preflightPath, "utf8"));
  console.log("Using cached pre‑flight:", cache);
}

```

### Extracting Tailwind Spacing

```javascript
import fs from "fs";

function getTailwindSpacing() {
  const cfgPath = fs.existsSync("tailwind.config.js")
    ? "tailwind.config.js"
    : fs.existsSync("tailwind.config.ts")
    ? "tailwind.config.ts"
    : null;
  
  if (!cfgPath) return null;

  const cfg = require(`./${cfgPath}`);
  return cfg.theme?.extend?.spacing || null;
}

console.log("Tailwind spacing scale:", getTailwindSpacing());

```

### Framework Detection

```javascript
import { readFileSync } from "fs";

const pkg = JSON.parse(readFileSync("package.json", "utf8"));
const deps = { ...pkg.dependencies, ...pkg.devDependencies };

const framework = Object.keys(deps).find((name) =>
  ["next", "astro", "vue", "svelte", "@sveltejs/kit", "@remix-run"].some(
    (kw) => name.includes(kw)
  )
);

console.log("Detected framework:", framework ?? "vanilla HTML");

```

## Key Files in the Pre‑flight System

| File | Purpose |
|------|---------|
| **[`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md)** | Master specification defining scan steps and signal priority `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md】` |
| **[`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json)** | Cached scan results for reuse across runs |
| **[`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json)** | Source for framework, font, and motion library detection |
| **`tailwind.config.*`** | Spacing and palette extension definitions |
| **[`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) / [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md)** | Optional locked design system with highest priority |

## Summary

- **Hallmark pre‑flight scan** runs automatically on startup when [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), Tailwind config, HTML, or CSS files exist
- **Six signal sources** are checked in strict priority, with [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) overriding all others
- **Cache reuse** via [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) avoids redundant analysis
- **Design system detection** preserves existing fonts, palettes, and spacing while identifying framework and motion preferences
- **Conflict handling** flags contradictory signals for user resolution

## Frequently Asked Questions

### What triggers the Hallmark pre‑flight scan?

The scan triggers automatically when Hallmark detects [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), `tailwind.config.*`, [`index.html`](https://github.com/Nutlope/hallmark/blob/main/index.html), or any CSS file in the project root. No manual command is required `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L45-L50】`.

### How does Hallmark prioritize conflicting design tokens?

Hallmark follows a strict 0‑5 priority order where [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) (priority 0) always wins. Within other signals, explicit configuration files (Tailwind config, CSS `:root`) take precedence over inferred dependencies `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L53-L58】`.

### Can I force Hallmark to re-run the pre‑flight scan?

Yes. Hallmark offers a refresh option when cached results are reused, or you can delete [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) to force a full re-scan on the next run `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L81-L82】`.

### What happens if no design system signals are detected?

Hallmark proceeds with a complete default stack and explicitly notes the lack of pre‑flight data in its output. It will not attempt to infer preferences from an empty codebase `【/cache/repos/github.com/Nutlope/hallmark/main/skills/hallmark/SKILL.md#L87-L89】`.