Push / Pull Guide

How workspace data flows to the registry and back. Understanding this model is the key to debugging sync issues.

Data flow

Figma
  ↓  handoff-app fetch
Workspace: public/api/tokens/{color,typography,effect}.json
  ↓  scripts/tokens-to-dtcg.js   (Phase 0 — DTCG conversion)
Workspace: design-system/tokens/{primitive,semantic}/*.tokens.json
  ↓  scripts/tokens-transform.js  (Phase 1 — Style Dictionary)
Workspace: design-system/dist/{css,scss,tailwind,dtcg}/
  ↓  handoff-app push:all
Registry API  (HTTP POST to /api/registry/*)
  ↓  stored in Postgres
Registry pages  (read via DynamicDataProvider)

Workspace

A client project repo (e.g. handlebars-registry-next/handoff/). Contains component source files, page markdown, handoff.config.js, and the DTCG token pipeline. The workspace never deploys itself — it uses handoff-app as a CLI tool.

Registry

A clean, standalone deployment of the handoff-app Next.js server (e.g. on Vercel). Contains no client-specific data at deploy time. All tenant data arrives via push:all and is stored in Postgres.

push:all in detail

handoff-app push:all calls these endpoints in sequence. Each uses a Bearer token obtained via handoff-app login.

1
POST /api/registry/config

Client identity, Figma project key, attribution settings

handoff.config.js app block

2
POST /api/registry/theme

Custom CSS overrides for the registry UI

theme.css

3
POST /api/registry/navigation

Page tree and sidebar structure

pages/ directory tree

4
POST /api/registry/pages

All markdown content with frontmatter

pages/**/*.md

5
POST /api/registry/tokens

Raw Figma token snapshot

public/api/tokens.json

6
POST /api/registry/dtcg

DTCG manifest and compiled CSS/SCSS/Tailwind/JSON

design-system/manifest.json + dist/

7
POST /api/registry/icons

Icon catalog — flat array of IconCatalogEntry objects

icons/catalog.json

8
POST /api/registry/logos

Logo set with variants and inline SVG content

logos/logo-set.json

Component sync (push / pull)

push sends individual component files via POST /api/sync/upload. Each upload includes declaration metadata, build artifacts (Vite dist), source files (.tsx, .css), and screenshots. Unchanged files are skipped based on a content hash.

pull calls GET /api/sync/changes and writes the changeset back to the workspace — updated pages, component declarations, build artifacts, and source files.

Common issues

500 on push (relation does not exist)

The DB migration hasn't run yet. Trigger a new Vercel deploy or call /setup to force migration.

Icons push skips with "must be a JSON array"

icons/catalog.json must be a flat array of IconCatalogEntry objects — not wrapped in an object.

413 FUNCTION_PAYLOAD_TOO_LARGE

DTCG payload is too large for one request. Check that design-system/dist/ isn't including source maps or vendor files.

push:all succeeds but icons/logos still show "No data"

Check Vercel function logs for auto-migrate errors. If migration 0012 isn't in the journal, it won't run.