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

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 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 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:

According to the Hallmark source specification in 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. On later invocations, Hallmark reuses this cache unless:

  • You explicitly request a refresh via CLI flag
  • Source files (package.json, tailwind.config.*, CSS) have newer modification times than the cache

As documented in 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 — The Locked Design System

If design.md or DESIGN.md exists in the project root, Hallmark treats it as authoritative and immutable (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 lines 54-56):

Source Detection Pattern
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 lines 55-56):

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 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 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 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 is reused, Hallmark notes the timestamp and offers a --refresh-preflight option (SKILL.md lines 81-82).

Edge Cases and Conflict Resolution

Design.md Override

When 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 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 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 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

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

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

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 overrides all — commit your design system to version control for deterministic behavior
  • Automatic caching in .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, tailwind.config.*, index.html, or CSS files in your project root (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 and :root CSS—it flags the conflict in its output and pauses for user clarification rather than choosing arbitrarily (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 dependencies, and ensure no design.md exists. For a complete override, create a DESIGN.md file with your preferred specifications—this becomes the authoritative source that supersedes all automatic detection (SKILL.md lines 53-55, 85-87).

Where does Hallmark store pre-flight scan results?

Scan results are cached in .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 lines 77-82).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →