Guides
Adding a screen, adding a filter sheet, running on a real device, and the export that catches what tsc cannot.
Run it on a device
There is no simulator on the dev box and no way to see a screen from it. Metro runs here; the app runs on your phone.
bun run dev:expo # Metro on 8142
bun run phone # a QR code for the dev clientMetro is handed the live Tailscale Serve URL as EXPO_PACKAGER_PROXY_URL, so
the dev client connects through tailnet-only HTTPS with a valid certificate.
The raw tailnet hostname is retained as a fallback. Nothing to pass.
A native change cannot be verified from the dev box
Typecheck it, say what you built and what remains unchecked, and leave the looking to a real device. Do not imply you saw it.
Add a screen
- Route. A file under
src/app/(main)/, in the group it belongs to —(tabs),(detail),(tools),(filters),(settings). - Data. A
defineQueryinsrc/lib/api/<area>/. One declaration gives you the hook, the imperative fetch, the prefetch and the invalidation, all agreeing on the key. See Data. - Presentation. How the screen is presented — push, modal, sheet — is a route-table decision, not something the screen sets. See Architecture.
- States. Loading, empty and failed are decided once and applied; see Errors.
Add a filter sheet
Filters are routes here, under (filters). That is what makes a panel
linkable, restorable, and dismissible by the back gesture — a modal that is not
a route is none of those.
Put the screen beside its siblings in screener-filters/ or
player-filters/, and keep the state in the store the board reads. Zustand owns
it, not the URL: there is no URL to put it in.
Before you push
bun run typecheck
bunx expo export --platform iosThe export is the one that matters. It catches native resolution failures —
a module that resolves in Metro and not in a build — that tsc cannot see, and
it is cheaper than finding them in EAS.
Submitting
App Store covers submission and review, and the
app-store-review skill audits a build against the guidelines that actually get
apps rejected.