# Recipes

The tested UI and data patterns the builder drops into an app instead of writing them from scratch.

## What recipes are

A recipe is a finished file the builder copies into a project when a screen needs that pattern: a component under `src/components/`, or a module under `src/lib/`. Each one is written on the design tokens (`bg-bg`, `bg-surface`, `text-ink`, `text-mute`, `bg-accent`, `text-accent-fg`, `rounded-card`) and `lucide-react`, so it matches the rest of the app without changes. Recipes are plain data in `src/skills/recipes/skill.ts`; the builder reads them through its `use_recipe` tool and adapts the record types and fields to the app. Several of them (`shared`, `files`, `file-upload`, `payments`, `collections`) are the skeleton's own files, so they are already in every app; the recipe is how the builder re-reads them. The kit already covers most UI patterns; a recipe is for a shape the kit does not ship.

## The recipes

- **empty-state** — A list's empty state: icon, one sentence, one action. → `src/components/EmptyState.tsx`
- **form** — A form with inline validation, disabled-while-saving, and a success state. Adapt the fields. → `src/components/ItemForm.tsx`
- **modal** — A centered dialog (sheet on phones) with backdrop, Escape to close, focus trap-lite. → `src/components/Modal.tsx`
- **confirm** — Confirm a destructive action with a small dialog and a hook to use it. → `src/components/Confirm.tsx`
- **toast** — Lightweight toasts: useToast() returns a function toast(text, tone?: "ok" | "err"); ToastProvider wraps the app. → `src/components/Toast.tsx`
- **tabs** — Accessible tabs with keyboard arrows; content by key. → `src/components/Tabs.tsx`
- **line-chart** — A responsive SVG line chart with area fill, axis labels and a hover tooltip. No library. → `src/components/LineChart.tsx`
- **shared** — Records other people can see (posts, reviews, bookings, a shared board), enforced by Ripping: useShared<T>(name) with add, update, remove. Also use_recipe collections and declare each collection's rule there. → `src/lib/shared.ts`
- **files** — File uploads stored on Ripping: uploadFile(file, { visibility }) and useFiles() (list, upload, remove). Public files get a permanent url to save in records. → `src/lib/files.ts`
- **file-upload** — An upload button with drag and drop that stores the file on Ripping and calls onUploaded(file). Needs use_recipe files. → `src/components/FileUpload.tsx`
- **payments** — Taking money: useProducts() lists the owner's products (set on Ripping's Settings → Payments), checkout(items) sends the buyer to pay with whichever processor the owner chose, confirmPayment() on the return route says whether it was paid; usePurchases() / owns(id) say what the signed-in person has bought, for unlocking paid content (a Purchases page at /purchases is already in every app). Already in every app as src/lib/pay.ts. → `src/lib/pay.ts`
- **collections** — Declares shared collections and their rules (public | members | inbox) for useShared; Ripping reads this file. → `src/lib/collections.ts`
- **store** — A typed localStorage collection hook: list, add, update, remove, undo, export/import JSON. Adapt the record type. → `src/lib/store.ts`
- **supabase-store** — The same collection API over a Supabase table (needs @supabase/supabase-js and the connected project's url + anon key). → `src/lib/supabaseStore.ts`
- **supabase-auth** — Only when the person asks for Supabase auth specifically: magic-link sign-in over their connected Supabase project: a SignIn screen, a useSession hook, and a sign-out button. → `src/lib/auth.tsx`
- **list** — A typed list view: search box, sort menu, filter chips, empty state and simple pagination. Adapt the record type and the row. → `src/components/ListView.tsx`
- **settings** — A settings screen: profile, preferences (theme, density), data export/import as JSON, and delete everything with a confirm. Wire exportJson/importJson from the store. → `src/components/SettingsScreen.tsx`
- **stat-tiles** — A row of KPI tiles: label, value, delta with colour. → `src/components/StatTiles.tsx`

The `store` recipe is the browser-only version of the collection hook. The skeleton ships a different `src/lib/store.ts` with the same `useStore` API that also syncs per account; see [Saving data](data.md).
