How Hallmark Performs Pre-Flight Scanning: A Complete Technical Breakdown

Hallmark performs pre-flight scanning by walking the project source tree once, caching static-analysis data to .hallmark/preflight.json, and re-using that cache on subsequent runs unless configuration files have been modified.

This article explains Hallmark's incremental preprocessing system as implemented in the Nutlope/hallmark repository. The pre-flight scanner serves as the foundation for Hallmark's design-system-aware rendering pipeline, enabling fast, deterministic builds through intelligent caching mechanisms.

What Pre-Flight Scanning Accomplishes

When Hallmark first processes a project, it needs to understand the codebase structure before rendering any components. The scanner extracts asset references, component usage patterns, theme settings, and dependency information from files like package.json and tailwind.config.*. Rather than repeating this expensive analysis on every invocation, Hallmark persists results to a hidden cache.

According to skills/hallmark/SKILL.md (lines 177-179), this approach transforms a potentially slow filesystem crawl into a near-instant cache lookup for typical development workflows.

The Four-Stage Pre-Flight Process

Initial Scan and Cache Creation

The first time Hallmark runs against a project, it executes a full scan. The scanner traverses the source tree, reads relevant configuration files, and builds a comprehensive analysis object. This data includes:

  • Installed dependencies from package.json
  • Tailwind theme customizations
  • Image asset references
  • Component registration patterns

Once collected, the results are serialized to .hallmark/preflight.json in the project root.

// Simplified pre-flight generation logic
import { readFileSync, writeFileSync } from 'fs';

function runPreflight() {
  if (!isCacheStale()) {
    console.log('Re-using cached pre-flight data');
    return JSON.parse(readFileSync(preflightPath, 'utf8'));
  }

  console.log('Scanning project for pre-flight data...');
  const data = {
    dependencies: JSON.parse(readFileSync(pkgPath, 'utf8')).dependencies,
    // Additional analysis omitted
  };

  writeFileSync(preflightPath, JSON.stringify(data, null, 2));
  return data;
}

Cache Re-Use on Subsequent Runs

Hallmark optimizes for the common case: multiple invocations against an unchanged codebase. On every run, it compares modification timestamps (mtimes) between the cache and primary configuration files. When package.json and all tailwind.config.* files remain unmodified, Hallmark skips the scan entirely and loads .hallmark/preflight.json directly.

This design prioritizes developer experience—subsequent renders complete in milliseconds rather than seconds.

Cache Invalidation Strategy

Stale caches are automatically detected through timestamp comparison. If either package.json or any Tailwind configuration file has a newer mtime than .hallmark/preflight.json, Hallmark discards the old cache and re-executes the full scan.

// Cache staleness detection
function isCacheStale() {
  if (!fs.existsSync(preflightPath)) return true;
  
  const cacheMtime = statSync(preflightPath).mtimeMs;
  const pkgMtime = statSync(pkgPath).mtimeMs;
  const twMtime = statSync(tailwindPath).mtimeMs;
  
  return pkgMtime > cacheMtime || twMtime > cacheMtime;
}

This ensures that newly added dependencies, theme changes, or style configuration updates immediately propagate through the rendering pipeline without manual cache clearing.

Asset Fallback Resolution

The cached pre-flight data directly powers rendering decisions. As documented in skills/hallmark/references/hero-enrichment.md (line 30), Hallmark implements a three-tier asset resolution strategy:

  1. Attached image files take priority
  2. Cached entries from .hallmark/preflight.json serve as secondary sources
  3. Placeholder assets provide graceful degradation
function getHeroImage(assetPath) {
  const preflight = JSON.parse(readFileSync('.hallmark/preflight.json', 'utf8'));

  if (fs.existsSync(assetPath)) return assetPath;
  if (preflight.heroImage) return preflight.heroImage;
  return '/assets/placeholder.svg';
}

Critically, Hallmark never overwrites cached assets—the system treats pre-flight data as read-only after initial generation.

Key Source Files and Their Roles

File Purpose
skills/hallmark/SKILL.md Defines persistence logic and cache invalidation rules
skills/hallmark/references/hero-enrichment.md Documents asset handling and fallback behavior
site/js/main.js Runtime loader that consumes pre-flight JSON
package.json & tailwind.config.* Configuration sources that trigger cache refresh
.hallmark/preflight.json Generated cache file (runtime only)

Performance Characteristics

The pre-flight scanning architecture delivers several measurable benefits:

  • First run: Full scan overhead (acceptable as one-time cost)
  • Typical run: Sub-millisecond cache load
  • Cache refresh: Triggered only when configuration changes
  • Disk usage: Single JSON file, typically under 50KB

This trade-off—accepting initial scan latency for near-zero recurring cost—aligns with Hallmark's target use case: interactive component rendering during development.

Summary

  • Hallmark's pre-flight scanner runs once per project to collect static-analysis data
  • Results are cached to .hallmark/preflight.json for fast subsequent access
  • Mtime comparison against package.json and tailwind.config.* enables automatic cache invalidation
  • The cache supports asset fallback chains that never overwrite stored data
  • Core logic is defined in SKILL.md (lines 177-179) with enrichment details in hero-enrichment.md

Frequently Asked Questions

How does Hallmark know when to invalidate the pre-flight cache?

Hallmark compares modification timestamps. If package.json or any tailwind.config.* file has been modified more recently than .hallmark/preflight.json, the cache is discarded and regenerated. This happens automatically without user intervention.

Can I manually clear the pre-flight cache?

Deleting the .hallmark/preflight.json file forces a fresh scan on the next invocation. Hallmark does not provide a dedicated CLI flag for cache management—the system relies on automatic invalidation based on file mtimes.

What happens if a referenced image asset is deleted after the pre-flight scan?

Hallmark's asset resolution implements fallbacks. It first checks for the file directly, then consults the cached pre-flight data, and finally serves a placeholder. The system never corrupts the cache by writing missing asset status back to .hallmark/preflight.json.

Does the pre-flight scanner analyze every file in the project?

The scan targets configuration files and asset references specifically. It does not perform deep static analysis of every source file—instead focusing on package.json, Tailwind configurations, and explicitly referenced resources that influence rendering decisions.

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 →