# Hallmark Pre-flight Scan: How It Detects Existing Design Systems Automatically

> Discover Hallmark's pre-flight scan. This automated tool instantly detects your design tokens fonts frameworks and motion libraries ensuring your existing design system is never overwritten.

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

---

**Hallmark's pre-flight scan is a lightweight, automated analysis that runs at startup to detect existing design tokens, fonts, frameworks, and motion libraries before generating any code, ensuring it never overwrites your established design system.**

The pre-flight scan is the first operation Hallmark performs on every run. It examines six signal sources in a specific priority order, then caches the results in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) for reuse on subsequent executions. This mechanism allows Hallmark to respect existing design decisions—whether you're using a custom Tailwind configuration, a locked [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) file, or a specific font stack from next/font.

## When the Pre-flight Scan Runs in Hallmark

Hallmark triggers the scan automatically when it detects any of the following files in your project root:

- [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json)
- `tailwind.config.*` (JS, TS, or MJS variants)
- [`index.html`](https://github.com/Nutlope/hallmark/blob/main/index.html)
- Any CSS files

According to the Hallmark source specification in [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) lines 45-50, this detection happens **without user prompting**—the scan is silent and non-blocking. The tool assumes that if these files exist, they contain valuable signals about your technical stack and design preferences.

### Caching Behavior

First-run results are written to [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json). On later invocations, Hallmark reuses this cache unless:

- You explicitly request a refresh via CLI flag
- Source files ([`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json), `tailwind.config.*`, CSS) have newer modification times than the cache

As documented in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 77-81, this cache invalidation strategy prevents stale detections while avoiding redundant filesystem operations.

## Six Signal Sources: Priority Order and Detection Methods

Hallmark examines signals in a strict hierarchy. Higher-priority findings can override lower-priority ones, creating a deterministic resolution order.

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

If [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) or [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md) exists in the project root, Hallmark treats it as **authoritative and immutable** ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 53-55). All subsequent signals are ignored. This file format allows teams to commit their design system decisions to version control, effectively freezing Hallmark's interpretation of tokens, typography, and spacing.

### Priority 1: Font Stack Detection

Hallmark detects fonts through multiple pathways ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 54-56):

| Source | Detection Pattern |
|--------|-------------------|
| [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) | `next/font` imports, `@fontsource/*` packages, `expo-google-fonts`, `geist` |
| HTML | `<link rel="stylesheet" …>` tags pointing to font CDNs |
| Tailwind config | `theme.extend.fontFamily` definitions |
| CSS | `@import` statements for Google Fonts, Fontshare, or local files |

### Priority 2: Color Palette Extraction

Palette detection supports modern color formats ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 55-56):

- **OKLCH/HSL/hex values** in CSS `:root` blocks
- **Tailwind config** `theme.extend.colors` or `theme.colors`
- **DTCG-style token files**: [`tokens.json`](https://github.com/Nutlope/hallmark/blob/main/tokens.json), [`design-tokens.json`](https://github.com/Nutlope/hallmark/blob/main/design-tokens.json), [`design-tokens.yaml`](https://github.com/Nutlope/hallmark/blob/main/design-tokens.yaml)

The scan parses these files statically—it does not execute JavaScript, so dynamic color generation in Tailwind configs may be partially invisible.

### Priority 3: Micro-interaction Stance

Hallmark categorizes projects as **"motion-on"** or **"motion-cut"** based on dependency detection ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 56-57):

**Motion-on triggers:**
- `framer-motion`
- `gsap`
- `motion` (Framer's new package)
- `lenis` (smooth scroll)
- `lottie-react`
- `@react-spring/*`
- `auto-animate`

Absence of these packages defaults the project to "motion-cut," which influences Hallmark's code generation templates.

### Priority 4: Spacing Scale Detection

Spacing is extracted from ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 57-58):

- `tailwind.config.*` → `theme.extend.spacing`
- CSS custom properties matching `--space-*` or `--spacing-*`
- Explicit 4-point or 8-point scale definitions in CSS comments or variable names

### Priority 5: Framework Detection

The final signal determines component generation patterns ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 58-59):

| Pattern | Framework |
|---------|-----------|
| `next` in dependencies | Next.js (App Router inferred from `app/` directory presence) |
| `astro` | Astro |
| `vue` | Vue 3 |
| `svelte` or `@sveltejs/kit` | Svelte / SvelteKit |
| `@remix-run/*` | Remix |
| None of above | Vanilla HTML |

## Pre-flight Output Format and User Feedback

When Hallmark completes a first-run scan, it emits a structured summary to stdout:

```

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.

```

This output explicitly separates **preserved signals** (your existing design system) from **introduced capabilities** (Hallmark's generative additions). If a cached [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) is reused, Hallmark notes the timestamp and offers a `--refresh-preflight` option ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 81-82).

## Edge Cases and Conflict Resolution

### Design.md Override

When [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) is present, Hallmark short-circuits all other detection. The file is parsed as a structured design specification, and its definitions for color, typography, spacing, and motion are treated as ground truth ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 85-87). This prevents scenario where installed dependencies conflict with committed design decisions.

### No Signals Detected

For empty repositories or projects without recognizable configuration files, Hallmark proceeds with a full default stack. The tool notes the absence of pre-flight data in its output, generating a complete starter design system rather than attempting partial detection ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 87-89).

### Conflicting Signals

When Hallmark detects contradictory information—such as a font library installed via npm but a hardcoded `font-family` in CSS—it flags the conflict explicitly and pauses for user clarification rather than making an arbitrary choice ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 88-89). This prevents silent misalignment between dependencies and actual usage.

## Programmatic Detection Examples

The following Node.js snippets illustrate how Hallmark's detection logic can be replicated for custom tooling or debugging. These are illustrative implementations based on the scan specification.

### Reading Cached Pre-flight Results

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

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

function shouldUseCache() {
  if (!existsSync(preflightPath)) return false;
  
  const cacheMtime = statSync(preflightPath).mtimeMs;
  const pkgMtime = existsSync(pkgPath) ? statSync(pkgPath).mtimeMs : 0;
  
  // Invalidate if package.json is newer than cache
  return cacheMtime >= pkgMtime;
}

if (shouldUseCache()) {
  const cache = JSON.parse(readFileSync(preflightPath, "utf8"));
  console.log("Using cached pre-flight:", cache);
} else {
  console.log("Cache stale or missing—running fresh scan");
}

```

### Extracting Tailwind Spacing Configuration

```javascript
import { createRequire } from "module";
import { existsSync } from "fs";

function getTailwindSpacing() {
  const configs = ["tailwind.config.js", "tailwind.config.ts", "tailwind.config.mjs"];
  const cfgPath = configs.find(existsSync);
  
  if (!cfgPath) return null;

  try {
    const require = createRequire(import.meta.url);
    const cfg = require(`./${cfgPath}`);
    return cfg.theme?.extend?.spacing ?? cfg.theme?.spacing ?? null;
  } catch {
    // Static fallback: parse file for spacing definitions
    return null;
  }
}

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

```

### Framework Detection from package.json

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

function detectFramework() {
  const pkg = JSON.parse(readFileSync("package.json", "utf8"));
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
  
  const frameworks = [
    { name: "Next.js", patterns: ["next"] },
    { name: "Astro", patterns: ["astro"] },
    { name: "Vue", patterns: ["vue"] },
    { name: "SvelteKit", patterns: ["@sveltejs/kit"] },
    { name: "Svelte", patterns: ["svelte"] },
    { name: "Remix", patterns: ["@remix-run/react"] },
  ];

  for (const fw of frameworks) {
    if (fw.patterns.some(p => deps[p])) return fw.name;
  }
  
  return "Vanilla HTML";
}

console.log("Detected framework:", detectFramework());

```

## Summary

Hallmark's pre-flight scan provides **zero-config design system detection** through six prioritized signal sources:

- **[`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) overrides all** — commit your design system to version control for deterministic behavior
- **Automatic caching** in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) eliminates redundant scanning
- **Conflict detection** prevents silent misalignment between dependencies and CSS
- **Framework-aware generation** tailors output to Next.js, Astro, Vue, SvelteKit, Remix, or vanilla HTML

The scan ensures Hallmark augments existing projects without destructive overwrites, making it safe to run on production codebases with established design tokens.

## Frequently Asked Questions

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

The scan runs 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 CSS files in your project root ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 45-50). No CLI flags or configuration is required—it's a zero-step initialization that happens before any code generation begins.

### How does Hallmark handle conflicts between Tailwind config and CSS variables?

When Hallmark detects contradictory signals—such as a color defined in both [`tailwind.config.js`](https://github.com/Nutlope/hallmark/blob/main/tailwind.config.js) and `:root` CSS—it flags the conflict in its output and pauses for user clarification rather than choosing arbitrarily ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 88-89). This prevents silent misalignment that could break existing UI.

### Can I force Hallmark to ignore my existing design system?

Yes. Remove or rename `tailwind.config.*`, clear relevant [`package.json`](https://github.com/Nutlope/hallmark/blob/main/package.json) dependencies, and ensure no [`design.md`](https://github.com/Nutlope/hallmark/blob/main/design.md) exists. For a complete override, create a [`DESIGN.md`](https://github.com/Nutlope/hallmark/blob/main/DESIGN.md) file with your preferred specifications—this becomes the authoritative source that supersedes all automatic detection ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 53-55, 85-87).

### Where does Hallmark store pre-flight scan results?

Scan results are cached in [`.hallmark/preflight.json`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/preflight.json) relative to your project root. This JSON file contains detected fonts, colors, spacing, motion stance, and framework information. Hallmark reuses this cache on subsequent runs unless source files have newer modification times or you pass an explicit refresh flag ([`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md) lines 77-82).