# @expo/styleguide-icons

Expo's icons for use on the web.

## Getting started

1. Install deps at the repo root: `yarn`.
2. Copy `.env.example` to `.env` and set `FIGMA_TOKEN` to a personal access token (Figma → avatar → Settings → Security → Personal access tokens).
3. Build: `yarn build` (from this package) or `yarn build` from the repo root.

Without a `FIGMA_TOKEN` the build falls back to an empty stub so downstream packages still compile.

## Scripts

| Command | What it does |
| --- | --- |
| `yarn build` | Smart build. Checks Figma's `lastModified`; if unchanged, skips the API entirely and re-bundles the existing sources. |
| `yarn build-stub` | Emits an empty package (no Figma, no icons). Used when `FIGMA_TOKEN` is missing. |
| `yarn refresh` | Forces a Figma pull then rebuilds. Prints a timing breakdown (`figmaExport / bundle / …`). Available at the repo root too. |

## Pipeline

One Node script — `scripts/build.mjs` — drives everything:

1. **Figma gate.** Fetches the Figma file's `lastModified` and compares it to `.figma-cache.json`. Unchanged → skip export.
2. **Figma export.** Runs `@figma-export/core` in-process with all four pages in parallel. `figma-js`'s `Client` is wrapped in a Proxy that retries on HTTP 429 respecting `Retry-After` ([Figma's recommendation](https://developers.figma.com/docs/rest-api/rate-limits/)). A live status line (TTY) collapses the per-icon progress; CI logs get per-page milestones only.
3. **Bundle.** A single `esbuild.build` pass (`bundle: false`, minify, CJS, JSX automatic) transforms ~3,600 `.tsx` files straight into the final layout at the package root (`custom/`, `duotone/`, `outline/`, `solid/`, `mergeClasses.js`). No `dist/` intermediate, no postbundle copy.
4. **Types.** Every icon's `.d.ts` has an identical shape, so we template them instead of running `tsc` — near-instant.
5. **Incremental.** An icon is skipped if its `.js` and `.d.ts` are both newer than the source `.tsx`.

Typical wall-times:

| Scenario | Time |
| --- | --- |
| No-op (Figma cached, outputs fresh) | ~0.5s |
| Clean bundle (Figma cached, no output) | ~1.5s |
| Force refresh (`yarn refresh`) | ~30–50s (Figma-bound; rate limit dependent) |

CI caches `src/{custom,duotone,outline,solid}` + `.figma-cache.json` separately, keyed only on Figma's `lastModified`, so every branch and PR reuses the same Figma snapshot — unrelated code pushes don't trigger a Figma refresh.
