# Design.md Hub — v1.15.0

The Design.md Hub gives OpenLife a real, queryable catalog of brand
design systems. It lifts the existing DesignMd subsystem (which only
imported skeleton DESIGN.md files) into a hub with rich artifacts,
URL-based extraction, search, and drift detection.

## Concepts

- **Profile** — a brand's design system, identified by a slug like
  `stripe`. Lives at `design/profiles/<id>/`.
- **Artifacts** — files inside a profile dir:
  - `DESIGN.md` — Google-spec DESIGN.md (YAML frontmatter + Markdown
    rationale)
  - `tokens.json` — programmatic token map (colors, typography, spacing)
  - `preview.html` — single-file visual preview
  - `quality-score.json` — A/B/C/D/F grade per category
  - `render-contract.json` — runtime token schema
  - `style-fingerprint.json` — archetype classification
    (shadcn-neutral, apple-glass, carbon-enterprise, etc.)
  - `meta.json` — generated on import; tracks source, archetype,
    qualityScore, checksum, artifacts[]
- **Catalog** — a collection of profiles. Today:
  - `core` — 5 bundled brands shipped in the npm tarball
    (apple, claude, stripe, vercel, linear.app)
  - `full` — 72 brands available via `OPENLIFE_DESIGN_CATALOG_PATH` env
  - `<path>` — any local directory laid out as
    `<path>/design-md/<brand>/`

## CLI surface

```bash
# Catalog import
openlife design pull              # imports `core` by default
openlife design pull core
openlife design pull full         # requires OPENLIFE_DESIGN_CATALOG_PATH
openlife design pull /path/to/my/catalog
openlife design pull --no-rich    # DESIGN.md only, skip artifacts

# List + inspect
openlife design list
openlife design list --json
openlife design show stripe

# Search
openlife design search "luxury automotive"          # ranked
openlife design search blue --archetype shadcn-neutral
openlife design search "design" --quality B
openlife design search anything --json

# Token-level diff
openlife design diff apple claude
openlife design diff apple claude --json

# URL extraction (needs claude-cli OR OPENROUTER_API_KEY)
openlife design extract https://stripe.com
openlife design extract https://stripe.com --catalog
openlife design extract https://stripe.com --out /tmp/out --no-cache
openlife design extract https://stripe.com --provider openrouter --model anthropic/claude-haiku-4-5
openlife design extract https://stripe.com --compare design/profiles/stripe/DESIGN.md

# Drift — re-extract URL and diff against local profile
openlife design drift stripe https://stripe.com
openlife design drift stripe https://stripe.com --json
```

## Programmatic API

```ts
import { DesignMdImporter, DesignMdRegistry, DesignMdExtractor } from '@openlife/cli';

// Import a catalog
const importer = new DesignMdImporter();
const metas = await importer.pullCatalog('core');

// Query
const reg = new DesignMdRegistry();
const matches = reg.search('minimal', { qualityScore: 'A' });
const nearBlue = reg.findByTokenColor('#0066cc', 35);
const diff = reg.diff('apple', 'claude');

// Extract from URL
const extractor = new DesignMdExtractor();
const result = await extractor.extract('https://stripe.com', { catalog: true });
console.log(result.designPath, result.tokensPath, result.previewPath);
```

## Provider routing for the extractor

The extractor needs an LLM to write the DESIGN.md. The TS wrapper
resolves the provider in this order:

1. Explicit `opts.provider` → used as-is.
2. `ModelTierRouter.pick('chat.smart')` — if it picks `anthropic`,
   we use `claude-cli` (assumes `claude` is in PATH).
3. `OPENROUTER_API_KEY` env present → `openrouter`. Default model:
   `anthropic/claude-haiku-4-5` (configurable via `--model`).
4. None of the above → returns an actionable error
   (`no_provider_available: install claude CLI OR set OPENROUTER_API_KEY`).

## Cache

- **Extractor cache:** 24h TTL keyed by URL hash. Output stored under
  `~/.openlife/design-extract/<slug>/`. Bypass via `--no-cache`.
- **Catalog imports:** SHA256 dedup at the importer level. Re-running
  `pull` overwrites profiles with the same id deterministically.

## Security model

- **URL safety for extractor** — distinct from
  `SecurityDownloadGuard.validateUrl` (which whitelists package
  hosts). The extractor accepts any public `http(s)://` URL but blocks
  SSRF vectors: localhost, RFC1918, link-local, cloud metadata,
  IPv6 loopback, `*.local`, `*.internal`.
- **API keys** — `OPENROUTER_API_KEY` read from env/`.env` only.
- **File permissions** — imported artifacts use default
  filesystem permissions; the cache uses `0o600` where atomic.
- **No new network surface** — extraction reuses axios that ships with
  OpenLife; no new sockets.

## Workflow examples

### Build a SaaS using a brand's design system

```bash
# 1. Pull the bundled core (offline, instant)
openlife design pull core

# 2. Apply stripe's design system as the active mode
openlife aiobuilder designmd --set designmd --profile stripe

# 3. Generate a UI feature that respects stripe's tokens
openlife aiobuilder generate-ui --feature "pricing page"

# 4. Check the active mode
openlife aiobuilder designmd status
```

### Capture a new brand from the wild

```bash
# Extract + publish as a profile in one step
openlife design extract https://www.airbnb.com --catalog

# Verify
openlife design list
openlife design show www.airbnb.com   # slug derived from URL
```

### Audit drift against a live site

```bash
# Last week's profile vs today's live design
openlife design drift stripe https://stripe.com
# → verdict: minor drift (3 delta)
#    colors:     2 changed
#    typography: 1 changed
```

### Programmatic SaaS scaffolding (preview of v1.16)

```ts
import { DesignMdRegistry, DesignMdExtractor } from '@openlife/cli';

// Ingest the user's existing brand
const ext = new DesignMdExtractor();
await ext.extract('https://my-startup.com', { catalog: true });

// Hand to the scaffold engine (v1.16+)
// const scaffold = new ScaffoldEngine();
// await scaffold.applyTemplate('nextjs-supabase-clerk-stripe', {
//   project: 'my-app',
//   designProfile: 'my-startup.com',
// });
```

## Roadmap

- **v1.15.1** — Remote `pull --catalog=full` over HTTPS (no env required)
- **v1.16.0** — Scaffold consumes designProfile at template-apply time
- **v1.17.0** — Autonomous Story Loop uses active design profile
  for generated UI
- **v2.0** — Cross-machine design catalog via the v1.12 bridge

## Credits

The bundled extractor skill (`.catalog/skills/design-md-extractor/`)
is **Alan Nicolas' design-md skill** ([@oalanicolas](https://github.com/oalanicolas)),
licensed MIT. OpenLife wraps it with provider routing + URL safety +
cache + catalog publish but the extraction logic is his work.

The 5-brand bundled core was curated by Rafael Leão.
