Concepts
Assets (Icons, Fonts, Logos)
Icon catalogs, logo sets, font files, and general uploaded assets.
"Assets" covers four related but structurally distinct entities. They share a theme (visual resources a design system publishes) but don't share one table or one push path.
Shape
| Entity | Table(s) | Push | Notes |
|---|---|---|---|
| General assets | handoff_asset (+ handoff_asset_blob for DB-stored bytes when S3 isn't configured, handoff_asset_usage for component↔asset usage tracking) | POST /api/handoff/assets (presign/confirm two-step upload) | assetType is logo|icon|image|video; grouped by handoff_asset_collection (a Figma section or a manual group). |
| Icon catalog | handoff_registry_icons — singleton row, full IconCatalogEntry[] | POST /api/registry/icons (push:all) | A separate, purpose-built catalog for icon browsing/search — distinct from individual handoff_asset rows of assetType: 'icon', which back the general asset library instead. handoff_icon_set groups icons into named sets (e.g. a Figma component set). |
| Logo set | handoff_registry_logos — singleton row, the full LogoSet shape | POST /api/registry/logos (push:all) | Light/dark/color/mono variants, primary/alternate/wordmark/icon-only — read by /foundations/logo. |
| Fonts | handoff_registry_font — one row per font file (keyed by filename), not a true singleton | POST /api/registry/fonts (push:all step) | Confirmed as its own dedicated table (not folded into general assets): stores base64-encoded bytes, family/familyKey, weight, style, format. Served at GET /fonts/<filename> so theme.css @font-face rules and the foundation rasterizer (satori) resolve them without workspace filesystem access. |
Three surfaces
| Surface | Where |
|---|---|
| UI | General assets: /assets, /assets/[id]; fonts and logos get dedicated sub-views at /assets/fonts, /assets/logos. Icons and logos also render on their own foundation pages: /foundations/icons, /foundations/icons/[name], /foundations/logo. See Registry → Stakeholder-facing UI routes. |
| REST | General assets: GET/POST /api/handoff/assets (+ /{id}, /{id}/raw, /presign, /confirm, /collections, /usages), see API → /api/handoff. Icon catalog / logo set: POST/GET /api/registry/icons (+ /download), POST/GET /api/registry/logos (+ GET /api/registry/logo.svg), see API → /api/registry. Fonts: push-only (POST /api/registry/fonts); read back via GET /fonts/<filename>, not a /api/registry/* route. |
| MCP | Icons & Logos: handoff_get_icon_catalog (bulk, filterable by category), handoff_search_icons (free-text), handoff_get_logo_set. Assets (registry mode only): handoff_search_assets, handoff_get_asset (with component usages + size info), handoff_list_asset_collections. See MCP → Tool catalog § Icons & Logos / Assets. No MCP tool currently exposes fonts: the tool catalog has no font-specific entry; an agent that needs font data has to go through the REST/UI surface above. |
Image slots are a related but separate concept
handoff_image_slot records sizing specs (aspect ratio, recommended dimensions, scale mode) for
named image-fill placeholders extracted from Figma inside a component; it's about how a
component expects an image to be supplied, not an asset entity itself. See
Components and handoff-app's schema-pg.ts for its full shape.