app-startup-and-bootstrap
Orders an Expo app's cold start - polyfills, error net, splash hold, storage open, providers, splash release, background flush.
Skill by zakariaf
Chalk Labs
Need help deploying app-startup-and-bootstrap?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/zakariaf-app-startup-and-bootstrap
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: writing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Node.js package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/app-startup-and-bootstrap
What's inside
- Skill name
app-startup-and-bootstrap- Description
- Orders an Expo app's cold start - polyfills, error net, splash hold, storage open, providers, splash release, background flush. Use when editing the root _layout.tsx or the app root, or the splash hangs or flashes. Not for routes (navigation-and-routing).
- License
- MIT
- Instructions
- 231 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Agent Skills spec issues
- files: referenced but missing: scripts/metro/metro-kits.ts
Files (45)
- SKILL.md
- shared.json · assets/
- app-root-with-session.tsx · examples/
- task-draft-buffer.ts · examples/
- checker-rules.md · references/
- lifecycle-flush.md · references/
- splash-screen.md · references/
- startup-gate-and-deferred-work.md · references/
- startup-order.md · references/
- check-lib.mjs · scripts/
- check-startup.mjs · scripts/
- source-scan.mjs · scripts/lib/
- startup-scan.mjs · scripts/lib/
- selftest.mjs · scripts/
- startup.json · templates/contracts/
- startup.schema.json · templates/contracts/
- _layout.tsx · templates/src/app/
- app-root.tsx · templates/src/features/root-navigator/
- app-stack.tsx · templates/src/features/root-navigator/
- background-flush.test.ts · templates/src/features/root-navigator/
- background-flush.ts · templates/src/features/root-navigator/
- hold-splash.test.ts · templates/src/features/root-navigator/
- hold-splash.ts · templates/src/features/root-navigator/
- root-kits.test.tsx · templates/src/features/root-navigator/
- root-kits.tsx · templates/src/features/root-navigator/
- root-motion.test.tsx · templates/src/features/root-navigator/
- root-motion.tsx · templates/src/features/root-navigator/
- root-stack.tsx · templates/src/features/root-navigator/
- startup-gate.test.ts · templates/src/features/root-navigator/
- startup-gate.ts · templates/src/features/root-navigator/
- use-flush-on-background.test.ts · templates/src/features/root-navigator/
- use-flush-on-background.ts · templates/src/features/root-navigator/
- use-startup-ready.test.ts · templates/src/features/root-navigator/
- use-startup-ready.ts · templates/src/features/root-navigator/
- create-root-kits.ts · templates/src/services/
- root-kit.test.ts · templates/src/services/root-kits/
- root-kit.ts · templates/src/services/root-kits/
- index.ts · tests/bases/app/
- package.json · tests/bases/app/
- app-error-net.ts · tests/bases/app/src/services/error-net/
- install-error-net.ts · tests/bases/app/src/services/error-net/
- tsconfig.json · tests/bases/app/
- CASES.json · tests/fixtures/check-startup/
- SUITE.json · tests/fixtures/check-startup/
- EXPECT.txt · tests/fixtures/check-startup/good/
SKILL.md (first lines)
# App startup and bootstrap
The app starts in one fixed order: the entry loads the polyfills and then the router; the root layout
installs the error net, holds the native splash and decides the direction before anything opens; the
app root opens storage once, connects the error log and hydrates the stores synchronously, mounts the
providers in dependency order and releases the splash once the first screen is real. Buffered writes
flush from one root hook when the app leaves the foreground. Optional kits (crash reporting,
analytics, notifications, ...) plug into typed slots from one registry, so the root files stay
canonical when a kit is added. One zero-dependency checker proves it.
## Rules that must hold
1. **The entry imports the polyfills first and `expo-router/entry` last.** Nothing follows the router
import. Why: ES imports evaluate in order; a module after the router entry loads after the root
component was registered. (`entry-router-last`)
2. **The root layout's first imports are side effects: the error net installer, then the splash
hold.** Every import with bindings comes after them. Why: a module that throws while loading must
find the net, and the hold must run before any other app module. (`root-import-order`)
3. **The native splash is held once, at module scope, in `hold-splash.ts`.** Why: Expo Router hides
an unheld splash at "navigation ready", over a direction restart's empty screen or a blocking wait;
called in a component or effect, the hold comes after native content appeared, when iOS and Android
may already have hidden it. (`splash-hold`)
4. **The splash is released once, in an effect, below the direction gate, when the startup gate is
ready** (`useStartupReady(gate, hideSplash)` in the app root). A startup component renders `null`
only while the splash is held. Why: a hold with no release keeps a release build on the splash
forever; a release in render or above the gate uncovers a frame that is not the first screen.
(`splash-release`, `blank-frame`)
5. **The root layout's first render creates adapters, reads config and resolves the language, and
opens nothing; `DirectionGate` is its outermost element (directly inside web-support's
`WebStorageGate` when the app ships the web); everything with effects lives in its child
`AppRoot`.** Why: a direction restart re-runs every module and initializer, so work done
before the decision happens twice (rtl-and-direction's `direction-before-render` enforces the gate).
6. **The data layer opens once, synchronously, in the app root's startup initializer, then the error
net's sink connects, then the query client, settings and stores hydrate, then the optional kits are
created, in that order** (`startApp`, run as `useState(() => startApp(services, language))`). Why: the first frame has the real rows
with no loading state, the buffered errors of the first moments reach the log before any provider
renders, and a second open runs migrations again. (`storage-open-once`, `sink-before-providers`)
7. **The startup path awaits nothing.** The root layout and the app root contain no `await`,
`.then`, `.catch` or `.finally`; async work the first screen truly needs is a non-interactive
blocking task of `createStartupGate` with a literal `deadlineMs` at or under 3000. A session
restore follows auth-and-secure-storage: its read is async and non-interactive, so it is a blocking
task under the deadline, and a miss starts the session as unknown or unavailable; a biometric
unlock is never a gate task but a lock screen after the splash. Why: a promise that never settles
keeps a held splash up forever, and a prompt that waits for the person outlasts any deadline; the
gate always opens by its deadline and reports what it missed. (`startup-await`, `startup-deadline`)
8. **Fonts are embedded with the expo-font config plugin, never loaded at runtime.** Why: `useFonts`
either holds the first frame or swaps the font after it. (`runtime-font-load`)
9. **Providers nest in one dependency order and each is mounted once on the root path:** services (or
`AppProviders`), data, query, settings store, stores, preferences (i18n, theme, text locale), root
stack (gesture root, keyboard, `RootMotion` (the one MotionConfig), navigation theme, session,
feedback, ads, games, then `AppStack`, whose `RootKits` slot wraps the `Stack` in the kits'
providers). Why: each provider reads only those
outside it, a misplaced one throws only when its path renders on a device, and a second copy
silently overrides the first. (`provider-order`, `provider-once`)
10. **Deferred work starts after the splash release, in the component or service that owns it; never
through `InteractionManager`.** Why: consent, entitlements, OTA checks and prefetches must not delay
the first frame, and `InteractionManager` is a deprecated stub in React Native 0.86 that runs on the
next tick. (`interaction-manager`)
11. **Buffered writes flush from one root hook when the app leaves the foreground:**
`useFlushOnBackground(flushers, errorLog)` once, in the app root, before
`useCheckpointOnBackground`; features hand it a `Flusher` and never write from their own `AppState`
listener. Why: an iOS swipe-kill from the app switcher sends `inactive` and no `background`, and
listeners run in subscription order, so the drafts must land before the WAL is folded.
(`flush-root`, `lifecycle-write`)
12. **Optional kits join through the slots, never through the root files.** A kit returns a `RootKit`
(`forward`, `blocking`, `flushers`, `motion`, `opensDebugRoutes`, `provide`, `effects`; every part
optional) from the app's one registry, `src/services/create-root-kits.ts`; `startApp` first calls
the registry's `prepareRootKits` (the ports every reader uses: a test build's simulated clock and
network), then `createRootKits` once, after the stores, attaches the kits to the error sink
(which replays the reports it kept) and hands their tasks to the gate and their flushers to the
flush; `RootMotion` renders the first kit's motion slot in `MotionConfig`'s place; `AppStack`
opens its `(debug)` group only while a kit says so and renders `<RootKits kits>` around the
`Stack`; a kit that needs Metro lists a `MetroKit` in `scripts/metro/metro-kits.ts`, which the
canonical `metro.config.js` composes. A slot no kit fills does nothing, and a test build's kits
are reached only through the test-only gate. Why: the root skeleton stays the canonical file
every skill cites, a kit is added or removed in one line, and every kit's work still runs at its
place in the startup order (E1, E2, E6, E7, F5, F6, I1). (`root-kits`)
13. **Prove the launch on a release build, on both platforms.** Expo Go shows the app icon instead of
the splash, and a development build does not apply every splash config property (Expo's SDK 57
splash-screen docs); only a release build shows the hold, the release and a direction restart as
people see them.
## Workflow
1. **Read the order**: [references/startup-order.md](references/startup-order.md) (section 1 is the
table of every step, its file and its owner skill). Find where the change belongs before writing it.
2. **New app or no root yet**: copy the templates (line 1 names each repo path):
`templates/src/app/_layout.tsx`, `templates/src/features/root-navigator/` (`app-root.tsx`,
`root-stack.tsx`, `app-stack.tsx`, `hold-splash.ts`, `startup-gate.ts`, `use-startup-ready.ts`,
`background-flush.ts`, `use-flush-on-background.ts`, `root-kits.tsx`, the helpers each with its
test), `templates/src/services/root-kits/root-kit.ts` (+ test, the slot types and helpers),
`templates/src/services/create-root-kits.ts` (the app's registry, empty) and
`templates/contracts/startup.json`. These files are the canonical root skeleton that other skills
cite; each of them owns one piece inside it. They expect the composition root
(architecture-and-boundaries), the error net (error-handling-typed-results), `DirectionGate`
(rtl-and-direction), the data layer (persistence-and-migrations), `watchSystemA11y` and
`MotionConfig` (accessibility-as-code), `useScreenAnimation` (motion-and-animation) and the
navigation theme (design-system-structure); set up a missing one with its skill first. Route groups
and `Stack.Protected` inside `AppStack` are navigation-and-routing's.
3. **Adding a piece of startup.** An optional kit from another skill (crash reporting, analytics,
push or local notifications): one entry in `src/services/create-root-kits.ts`, as that skill's
example shows; the root files stay unchanged (read [references/startup-order.md](references/startup-order.md)
section 15, the slot contract). An app piece (a store, a client, the session): its creation in
`startApp` at its row of the order table, its provider at its place in the tree, and its name in
`appRootOrder` in `contracts/startup.json` if it is new; pass what a kit reads (the settings, the
session) on to `createRootKits`. Imitate [examples/app-root-with-session.tsx](examples/app-root-with-session.tsx).
4. **Work that is async**: decide with [references/startup-gate-and-deferred-work.md](references/startup-gate-and-deferred-work.md)
(section 1) whether it blocks the first screen. Deferred is the default; a blocking task returns a
Result, goes into `createStartupGate({ blocking })` and gets a test that drives it resolving, failing
and hanging.
5. **Splash problems** (hangs, flashes, empty frame): [references/splash-screen.md](references/splash-screen.md)
(sections 3-4 and the pitfalls table). The splash art itself is icons-app-icon-and-splash's.
6. **A buffered writer** (debounced draft, batch queue): read [references/lifecycle-flush.md](references/lifecycle-flush.md),
imitate [examples/task-draft-buffer.ts](examples/task-draft-buffer.ts), return its flusher from
`startApp`.
7. **Test**: `npx jest src/features/root-navigator --ci --maxWorkers=2`, then `npm run typecheck` and
`npx eslint . --max-warnings 0`.
8. **Run the checker** from the repo root: `node ${CLAUDE_SKILL_DIR}/scripts/check-startup.mjs .`;
look up a FAIL line's rule in [references/checker-rules.md](references/checker-rules.md); fix andFrom zakariaf/ReactNative-Skills, MIT.
More from zakariaf/ReactNative-Skills
- 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
android-release-play
zakariaf
Ships Android App Bundles to Google Play: upload key, Play App Signing, AAB gate, versionCode, tracks, rollout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
architecture-and-boundaries
zakariaf
Places app code in the src/ layout and checks import boundaries: one-way zones, pure core, ports with fakes, one composition root.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
async-safety
zakariaf
Prevents silent async bugs: effect races, stale results, lost promises, leaked listeners and timers, AbortSignal gaps.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
audio-and-haptics-feedback
zakariaf
Builds SFX and haptics behind ports.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
auth-and-secure-storage
zakariaf
Builds sign-in - tokens in expo-secure-store, shared refresh, protected routes, OAuth PKCE, Apple sign-in.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
background-tasks
zakariaf
Builds expo-background-task jobs: idempotent, budgeted runs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9
Signals
- Stars
- 11
- Forks
- 2
- Open issues
- 0
- Last commit (this folder)
- Oct 17, 2026 (13 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/zakariaf/ReactNative-Skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from zakariaf
- 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get app-startup-and-bootstrap running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
app-startup-and-bootstrap skill. Agent Mart. https://agentmart.dev/skills/zakariaf-app-startup-and-bootstrap (last updated 2026-10-24)