create-disposabl-app 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +21 -22
- package/dist/templates/default/apps/desktop/.oxfmtrc.json +5 -0
- package/dist/templates/default/apps/desktop/.oxlintrc.json +6 -0
- package/dist/templates/default/apps/desktop/README.md +58 -0
- package/dist/templates/default/apps/desktop/forge.config.mts +90 -0
- package/dist/templates/default/apps/desktop/index.html +12 -0
- package/dist/templates/default/apps/desktop/package.json +55 -1
- package/dist/templates/default/apps/desktop/src/declarations.d.ts +2 -0
- package/dist/templates/default/apps/desktop/src/index.css +8 -0
- package/dist/templates/default/apps/desktop/src/main.ts +58 -0
- package/dist/templates/default/apps/desktop/src/preload.ts +3 -0
- package/dist/templates/default/apps/desktop/src/renderer.ts +19 -0
- package/dist/templates/default/apps/desktop/tsconfig.json +14 -0
- package/dist/templates/default/apps/desktop/vite.main.config.mts +4 -0
- package/dist/templates/default/apps/desktop/vite.preload.config.mts +4 -0
- package/dist/templates/default/apps/desktop/vite.renderer.config.mts +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/agent-device/SKILL.md +22 -0
- package/dist/templates/default/apps/mobile/.agents/skills/android-emulator/SKILL.md +32 -0
- package/dist/templates/default/apps/mobile/.agents/skills/dogfood/SKILL.md +27 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/SKILL.md +176 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/app-store-metadata.md +497 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/ios-app-store.md +376 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/native-ios.md +167 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/play-store.md +244 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/testflight.md +62 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-app-stores/references/workflows.md +120 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-hosting/SKILL.md +431 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-hosting/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/SKILL.md +46 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/metrics.md +98 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/queries.md +444 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/setup.md +529 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-observe/references/third-party.md +136 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/SKILL.md +237 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/controllers.md +139 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/logs-and-crashes.md +101 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/run-your-app.md +256 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-simulator/references/troubleshooting.md +56 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update/SKILL.md +146 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/SKILL.md +238 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/SKILL.md +99 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/scripts/fetch.js +109 -0
- package/dist/templates/default/apps/mobile/.agents/skills/eas-workflows/scripts/package.json +6 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/LICENSE +21 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/RECIPES.md +385 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/SKILL.md +274 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-animation/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-app-clip/SKILL.md +290 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-app-clip/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-app-clip/references/native-module.md +96 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/SKILL.md +69 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/brownfield-integrated.md +551 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/brownfield-isolated.md +449 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/comparison.md +63 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/feature-integration.md +163 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-brownfield/references/version-compatibility.md +40 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/SKILL.md +478 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/references/expo-router-loaders.md +341 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-data-fetching/references/offline-and-cancellation.md +68 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/SKILL.md +376 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/references/audit.md +190 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-design-system/references/native-slop.md +74 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dev-client/SKILL.md +184 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dev-client/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dom/SKILL.md +425 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-dom/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-examples/SKILL.md +106 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-examples/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-examples/references/catalog.md +105 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/SKILL.md +124 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/references/compatibility.md +130 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/references/example.md +212 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-migrate-module/references/migration-map.md +457 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/SKILL.md +151 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/config-plugin.md +90 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/create-expo-module.md +206 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/lifecycle.md +127 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/module-config.md +48 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/native-module.md +286 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-module/references/native-view.md +171 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/SKILL.md +201 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/controls.md +231 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/gradients.md +106 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/icons.md +232 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/media.md +193 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/storage.md +121 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/visual-effects.md +198 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-native-ui/references/webgpu-three.md +605 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-overview/SKILL.md +120 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-overview/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-overview/references/launch-without-dev-menu.md +24 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-project-structure/SKILL.md +114 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-project-structure/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/SKILL.md +240 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/form-sheet.md +253 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/route-structure.md +229 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/search.md +248 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/tabs.md +433 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/toolbar-and-headers.md +284 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-router/references/zoom-transitions.md +158 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/SKILL.md +314 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/agents/visual-grader.md +52 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/references/design-rubric.md +45 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/references/runtime-matrix.md +34 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/check-static.sh +64 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/clean-fixture.sh +56 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/generate_viewer.py +450 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/latest-sdk.sh +46 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/make-fixture.sh +95 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/make-workspace.sh +31 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/snapshot-android.sh +284 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/snapshot-ios.sh +132 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-skill-eval/scripts/snapshot-web.sh +61 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/SKILL.md +101 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/drop-in-replacements.md +27 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/jetpack-compose.md +73 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/swift-ui.md +73 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/references/universal.md +104 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-ui/scripts/list-components.js +193 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/SKILL.md +150 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/expo-av-to-audio.md +132 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/expo-av-to-video.md +160 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/native-tabs.md +124 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/new-architecture.md +79 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/react-19.md +79 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/react-compiler.md +59 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-upgrade/references/react-navigation-to-expo-router.md +61 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/SKILL.md +91 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/false-friends.md +119 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/native-patterns.md +39 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/run-as-goal.md +48 -0
- package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/references/verify-on-device.md +45 -0
- package/dist/templates/default/apps/mobile/.agents/skills/ios-simulator/SKILL.md +32 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/POWER.md +172 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/SKILL.md +238 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/agents/openai.yaml +4 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-analyze-app.md +208 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-analyze-js.md +264 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-barrel-exports.md +250 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-code-splitting.md +255 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-hermes-mmap.md +167 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-library-size.md +164 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-native-assets.md +208 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-r8-android.md +231 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/bundle-tree-shaking.md +215 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/bundle-treemap-source-map-explorer.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/controlled-textinput-pingpong.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/devtools-flamegraph.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/emerge-xray-ios.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/expo-atlas-treemap.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/flashlight-flatlist-vs-flashlist.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/fps-drop-graph.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/memory-heap-snapshot.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/tti-warm-start-diagram.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/view-hierarchy-flattening.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/xcode-instruments-templates.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/images/xcode-thread-view.png +0 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-animations-reanimated.md +273 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-atomic-state.md +190 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-bottomsheet.md +339 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-concurrent-react.md +238 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-lists-flatlist-flashlist.md +223 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-measure-fps.md +178 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-memory-leaks.md +168 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-profile-react.md +138 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-react-compiler.md +261 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/js-uncontrolled-components.md +219 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-android-16kb-alignment.md +114 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-measure-tti.md +221 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-memory-leaks.md +206 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-memory-patterns.md +240 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-platform-setup.md +112 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-profiling.md +140 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-sdks-over-polyfills.md +192 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-threading-model.md +230 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-turbo-modules.md +210 -0
- package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/references/native-view-flattening.md +180 -0
- package/dist/templates/default/apps/mobile/AGENTS.md +41 -0
- package/dist/templates/default/apps/mobile/app.json +38 -0
- package/dist/templates/default/apps/mobile/assets/expo.icon/Assets/expo-symbol 2.svg +3 -0
- package/dist/templates/default/apps/mobile/assets/expo.icon/Assets/grid.png +0 -0
- package/dist/templates/default/apps/mobile/assets/expo.icon/icon.json +40 -0
- package/dist/templates/default/apps/mobile/assets/images/android-icon-background.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/android-icon-foreground.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/android-icon-monochrome.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/icon.png +0 -0
- package/dist/templates/default/apps/mobile/assets/images/splash-icon.png +0 -0
- package/dist/templates/default/apps/mobile/eslint.config.js +10 -0
- package/dist/templates/default/apps/mobile/package.json +43 -1
- package/dist/templates/default/apps/mobile/skills-lock.json +185 -0
- package/dist/templates/default/apps/mobile/src/app/_layout.tsx +5 -0
- package/dist/templates/default/apps/mobile/src/app/index.tsx +17 -0
- package/dist/templates/default/apps/mobile/tsconfig.json +20 -0
- package/dist/templates/default/apps/web/.agents/skills/frontend-design/SKILL.md +71 -0
- package/dist/templates/default/apps/web/.agents/skills/web-design-guidelines/SKILL.md +39 -0
- package/dist/templates/default/apps/web/.env.example +3 -0
- package/dist/templates/default/apps/web/components.json +23 -0
- package/dist/templates/default/apps/web/eslint.config.ts +21 -0
- package/dist/templates/default/apps/web/package.json +39 -1
- package/dist/templates/default/apps/web/public/disposabl-logo.svg +8 -0
- package/dist/templates/default/apps/web/public/favicon.ico +0 -0
- package/dist/templates/default/apps/web/public/manifest.json +25 -0
- package/dist/templates/default/apps/web/skills-lock.json +17 -0
- package/dist/templates/default/apps/web/src/index.css +92 -0
- package/dist/templates/default/apps/web/src/routeTree.gen.ts +282 -0
- package/dist/templates/default/apps/web/src/router/__root.tsx +63 -0
- package/dist/templates/default/apps/web/src/router/_authenticated/dashboard.tsx +9 -0
- package/dist/templates/default/apps/web/src/router/_authenticated/todos/$id.tsx +27 -0
- package/dist/templates/default/apps/web/src/router/_authenticated/todos/index.tsx +33 -0
- package/dist/templates/default/apps/web/src/router/index.tsx +15 -0
- package/dist/templates/default/apps/web/src/router.tsx +20 -0
- package/dist/templates/default/apps/web/tsconfig.json +33 -0
- package/dist/templates/default/apps/web/tsr.config.json +6 -0
- package/dist/templates/default/apps/web/vite.config.ts +65 -0
- package/dist/templates/default/bun.lock +3932 -0
- package/dist/templates/default/bunfig.toml +5 -0
- package/dist/templates/default/disposabl.json +9 -0
- package/dist/templates/default/gitignore +9 -1
- package/dist/templates/default/package.json +29 -4
- package/dist/templates/default/packages/backend/.agents/skills/convex/SKILL.md +69 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-add/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-advisor/SKILL.md +32 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-agent/SKILL.md +25 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-auth/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-authz/SKILL.md +36 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-backup/SKILL.md +33 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-billing/SKILL.md +69 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-cost/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/SKILL.md +325 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/agents/openai.yaml +14 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/assets/icon.svg +3 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/advanced-patterns.md +146 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/hybrid-components.md +38 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/local-components.md +39 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-create-component/references/packaged-components.md +54 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-crons/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-deploy-guard/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-design/SKILL.md +30 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-docs/SKILL.md +31 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-domains/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-env/SKILL.md +24 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-expert/SKILL.md +38 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-explain-app/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-improve-convex-plugin/SKILL.md +24 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-insights/SKILL.md +32 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-launch-readiness/SKILL.md +35 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-migrate/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-migrate-rehearse/SKILL.md +31 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-monitor/SKILL.md +22 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-optimize/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-quickstart/SKILL.md +29 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-quickstart/agents/openai.yaml +14 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-quickstart/assets/icon.svg +4 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-reviewer/SKILL.md +26 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-seed/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-self-heal/SKILL.md +38 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-sentinel/SKILL.md +25 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-suggest/SKILL.md +27 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-test/SKILL.md +23 -0
- package/dist/templates/default/packages/backend/.agents/skills/convex-verify/SKILL.md +34 -0
- package/dist/templates/default/packages/backend/.prettierignore +4 -0
- package/dist/templates/default/packages/backend/AGENTS.md +18 -0
- package/dist/templates/default/packages/backend/CLAUDE.md +13 -0
- package/dist/templates/default/packages/backend/README.md +33 -0
- package/dist/templates/default/packages/backend/convex/_generated/ai/ai-files.state.json +6 -0
- package/dist/templates/default/packages/backend/convex/_generated/ai/guidelines.md +286 -0
- package/dist/templates/default/packages/backend/convex/_generated/api.d.ts +66 -0
- package/dist/templates/default/packages/backend/convex/_generated/api.js +23 -0
- package/dist/templates/default/packages/backend/convex/_generated/dataModel.d.ts +60 -0
- package/dist/templates/default/packages/backend/convex/_generated/server.d.ts +164 -0
- package/dist/templates/default/packages/backend/convex/_generated/server.js +101 -0
- package/dist/templates/default/packages/backend/convex/auth.config.ts +14 -0
- package/dist/templates/default/packages/backend/convex/auth.ts +15 -0
- package/dist/templates/default/packages/backend/convex/convex.config.ts +30 -0
- package/dist/templates/default/packages/backend/convex/http.ts +5 -0
- package/dist/templates/default/packages/backend/convex/mcp.ts +8 -0
- package/dist/templates/default/packages/backend/convex/schema.ts +10 -0
- package/dist/templates/default/packages/backend/convex/todos/index.ts +26 -0
- package/dist/templates/default/packages/backend/convex/todos/internal.ts +43 -0
- package/dist/templates/default/packages/backend/convex/tsconfig.json +27 -0
- package/dist/templates/default/packages/backend/convex/users.ts +20 -0
- package/dist/templates/default/packages/backend/eslint.config.mjs +62 -0
- package/dist/templates/default/packages/backend/package.json +36 -0
- package/dist/templates/default/packages/backend/skills-lock.json +203 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/accordion.tsx +77 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/alert-dialog.tsx +185 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/alert.tsx +75 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/aspect-ratio.tsx +22 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/attachment.tsx +207 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/avatar.tsx +106 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/badge.tsx +51 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/breadcrumb.tsx +121 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/bubble.tsx +127 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/button-group.tsx +87 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/button.tsx +57 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/calendar.tsx +241 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/card.tsx +102 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/carousel.tsx +239 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/chart.tsx +368 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/checkbox.tsx +27 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/code-block.tsx +243 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/collapsible.tsx +19 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/combobox.tsx +300 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/command.tsx +194 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/context-menu.tsx +271 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/dialog.tsx +156 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/direction.tsx +4 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/drawer.tsx +224 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/dropdown-menu.tsx +269 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/empty.tsx +103 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/field.tsx +236 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/hover-card.tsx +50 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/input-group.tsx +158 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/input-otp.tsx +83 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/input.tsx +19 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/item.tsx +201 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/kbd.tsx +26 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/label.tsx +19 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/marker.tsx +70 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/menubar.tsx +284 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/message-scroller.tsx +128 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/message.tsx +91 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/native-select.tsx +64 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/navigation-menu.tsx +170 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/pagination.tsx +133 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/popover.tsx +87 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/progress.tsx +82 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/questionnaire.tsx +330 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/radio-group.tsx +35 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/resizable.tsx +49 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/scroll-area.tsx +51 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/select.tsx +201 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/separator.tsx +22 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/sheet.tsx +132 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/sidebar.tsx +723 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/skeleton.tsx +13 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/slider.tsx +51 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/spinner.tsx +16 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/switch.tsx +31 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/table.tsx +113 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/tabs.tsx +81 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/textarea.tsx +17 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/toast.tsx +229 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/toggle-group.tsx +87 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/toggle.tsx +42 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/tooltip.tsx +65 -0
- package/dist/templates/default/packages/disposabl-kit/client/components/ui/trace.tsx +161 -0
- package/dist/templates/default/packages/disposabl-kit/client/hooks/use-mobile.ts +21 -0
- package/dist/templates/default/packages/disposabl-kit/client/lib/prerender.ts +89 -0
- package/dist/templates/default/packages/disposabl-kit/client/lib/return-to.ts +12 -0
- package/dist/templates/default/packages/disposabl-kit/client/lib/utils.ts +1 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/_auth-pages/login.tsx +114 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/_auth-pages/signUp.tsx +120 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/_authenticated/route.tsx +38 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/consent.tsx +137 -0
- package/dist/templates/default/packages/disposabl-kit/client/routes/route.tsx +30 -0
- package/dist/templates/default/packages/disposabl-kit/client/styles/globals.css +60 -0
- package/dist/templates/default/packages/disposabl-kit/client/vite.config.ts +32 -0
- package/dist/templates/default/packages/disposabl-kit/components.json +23 -0
- package/dist/templates/default/packages/disposabl-kit/eslint.config.js +21 -0
- package/dist/templates/default/packages/disposabl-kit/package.json +59 -0
- package/dist/templates/default/packages/disposabl-kit/server/http.ts +42 -0
- package/dist/templates/default/packages/disposabl-kit/server/lib/functions.ts +46 -0
- package/dist/templates/default/packages/disposabl-kit/server/lib/mcp-tools.ts +47 -0
- package/dist/templates/default/packages/disposabl-kit/server/lib/platforms.ts +20 -0
- package/dist/templates/default/packages/disposabl-kit/tsconfig.json +17 -0
- package/dist/templates/default/patches/@convex-dev%2Fauth@2.0.0-beta.0.patch +310 -0
- package/dist/templates/default/patches/@convex-dev%2Fstatic-hosting@0.2.1.patch +187 -0
- package/dist/templates/default/tsconfig.json +9 -0
- package/dist/templates/default/turbo.json +51 -0
- package/package.json +1 -2
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: expo-web-to-native
|
|
3
|
+
description: Migrate an existing web React app to a native iOS/Android app with Expo. Use when the user wants to turn a website into a mobile app, port a Next.js/Vite/CRA React codebase to React Native, reuse web code on native incrementally, or asks how web idioms (the DOM, CSS, React Router, localStorage, window) map to native. This is the end-to-end migration guide; use the `expo-dom` skill for the DOM-component mechanism itself.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
license: MIT
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Web to Native
|
|
9
|
+
|
|
10
|
+
A web React app does not *convert* to native — there is no transpiler. It **migrates**, screen by screen, the way a strangler fig grows around a tree and slowly replaces it: stand up a native shell, run the whole web UI inside it on day one, then strangle each screen into native in priority order. This skill is the spine that orders the work; each step hands off to an existing Expo skill rather than re-explaining it. It operationalizes Expo's [From Web to Native with React](https://expo.dev/blog/from-web-to-native-with-react) — read that for the why.
|
|
11
|
+
|
|
12
|
+
```mermaid
|
|
13
|
+
flowchart TD
|
|
14
|
+
A1[1 · Assess: write the worklist] --> A2[2 · Scaffold Expo shell]
|
|
15
|
+
A2 --> A3[3 · DOM-component shell<br/>· expo-dom · SHIP DAY ONE]
|
|
16
|
+
A3 --> A4[4 · Strangle screens to native<br/>highest-value first · expo-router]
|
|
17
|
+
A4 -->|more screens| A4
|
|
18
|
+
A4 --> A5[5 · Wire data / auth / storage<br/>· expo-data-fetching]
|
|
19
|
+
A5 --> A6[6 · Ship · eas-app-stores]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Principles
|
|
23
|
+
|
|
24
|
+
- **Migrate, don't rewrite.** Never big-bang it; every step keeps the app shippable.
|
|
25
|
+
- **Ship on day one.** The web UI runs in a DOM-component shell (step 3) before anything is nativized — that's the milestone; everything after is polish.
|
|
26
|
+
- **Strangle by value.** Nativize the hot screens; leave the rest in the webview. Each DOM screen carries a ~2 MB web runtime — reason enough not to ship everything as DOM.
|
|
27
|
+
- **Nativize means redesign, not reskin.** A strangled screen should look like Apple/Google shipped it, not the web page reskinned. **Reach for `@expo/ui` first** - it renders real SwiftUI/Compose, so it feels *exactly* like the OS; styled RN primitives are the fallback for custom layouts only. Plus platform navigation (`expo-router`: NativeTabs, large titles), liquid glass and native components via `@expo/ui`, and mobile UX (sheets, swipe, haptics). The web→native pattern map is [`./references/native-patterns.md`](./references/native-patterns.md). If it still feels like a website, you ported instead of redesigned.
|
|
28
|
+
- **Verify by running, not compiling.** A clean build proves nothing (a blank webview compiles fine). Run each screen — but judge *content and behavior* against the web original, not pixels (a nativized screen should look more native, not identical).
|
|
29
|
+
- **Orchestrate, don't reinvent.** Each step routes into an existing skill. The value here is the *order* and the *gotchas* — the idiom-by-idiom mappings live in [`./references/false-friends.md`](./references/false-friends.md).
|
|
30
|
+
|
|
31
|
+
## Run it as a loop (recommended)
|
|
32
|
+
|
|
33
|
+
The migration is a long repeat-until-done loop, so the first move is to **write the goal objective and launch it** — not to grind screens by hand. Fill the objective in [`./references/run-as-goal.md`](./references/run-as-goal.md) for this app and present it; it **re-reads this skill every iteration**, so each `/goal` turn reloads the playbook + worklist and drives the next screen (it even self-bootstraps the assess step). Then run `/goal` with it — or, if the harness can't loop, write it to `migration-goal.md` and have the user launch it. The steps below are what each iteration does; run them by hand only if you're not looping.
|
|
34
|
+
|
|
35
|
+
## The migration
|
|
36
|
+
|
|
37
|
+
> **No repo to migrate** - just building native fresh as a web dev? You don't need these steps: use `expo-router`, and keep [`./references/false-friends.md`](./references/false-friends.md) open for the web→native idiom map. Everything below assumes an existing web app.
|
|
38
|
+
|
|
39
|
+
### 1. Assess → write the worklist
|
|
40
|
+
|
|
41
|
+
Read the repo and produce `migration-progress.md`, the durable worklist the rest of the migration checks off. Make two cuts:
|
|
42
|
+
|
|
43
|
+
- **Screens vs backend.** Page routes (`page.tsx`) are screens you migrate; server routes (`route.ts`), the ORM, and auth handlers stay server-side. Decide the backend once: keep it deployed (the native app becomes an HTTP client) or move it to EAS Hosting (`eas-hosting`).
|
|
44
|
+
- **Bucket each screen** by how it should land: **port-as-is** (presentational → ships in a DOM webview), **nativize-now** (hot, or needs native feel — gestures, lists, keyboard), **nativize-later**, or **hybrid** (a native shell around a web sub-tree, e.g. a chat list wrapping a markdown renderer).
|
|
45
|
+
|
|
46
|
+
Note the framework signals as you read — RSC vs client, Tailwind/shadcn, where data is fetched — since they decide how each screen ports (false-friends has the mappings; async Server Components in particular must be split into a client fetch + a presentational component before they can move). **Flag third-party services/SDKs too** — browser SDKs don't carry over (`false-friends` → *Services & SDKs*); payments especially is a *fork, not a swap* (in-app digital goods must use store IAP via RevenueCat, ~30% — not Stripe), a business-model call to make now, not at App Store review. The worklist is only trustworthy once every route is sorted and every screen bucketed.
|
|
47
|
+
|
|
48
|
+
### 2. Scaffold the shell
|
|
49
|
+
|
|
50
|
+
`create-expo-app`, then mirror the web routes in Expo Router — Next's tree maps almost 1:1 (note `[id]/page.tsx` → `[id].tsx`, and routes may live in `src/app/`). Empty screens, one per route.
|
|
51
|
+
|
|
52
|
+
### 3. Shell it in DOM components — the day-one milestone
|
|
53
|
+
|
|
54
|
+
Bring every screen over as a DOM component (`'use dom'`, per the `expo-dom` skill) rendered by its native route, so the whole app runs on a phone before anything is nativized. Expect per-screen edits - unwrapping Server Components, swapping framework imports (`next/link`), carrying the styling over - all covered in false-friends. Then verify by running (below); this is shippable to TestFlight as-is.
|
|
55
|
+
|
|
56
|
+
### 4. Strangle screens to native — by value
|
|
57
|
+
|
|
58
|
+
Walk `migration-progress.md` top-down. For each screen, *redesign* it native - don't port the web layout. Reach for **`@expo/ui` first** (real SwiftUI/Compose - buttons, lists, sheets, pickers, sliders; [`./references/native-patterns.md`](./references/native-patterns.md) maps which web pattern becomes which native component), then platform navigation (`expo-router` - NativeTabs, large titles) and mobile UX (swipe, haptics, momentum/inverted scroll); RN primitives only for custom layouts. Consult [`./references/false-friends.md`](./references/false-friends.md) for each idiom. `@expo/ui` and DOM components both run in **Expo Go** (SDK 56+) - a dev build (the `expo-dev-client` skill) is only needed for *custom* native modules. Verify *content and behavior* against the running web original (the look should become more native), then check it off. One screen per pass, app shippable throughout. It's a loop over a durable worklist, so it can run unattended - hand it to a goal loop ([`./references/run-as-goal.md`](./references/run-as-goal.md)).
|
|
59
|
+
|
|
60
|
+
### 5. Wire data, auth, and storage
|
|
61
|
+
|
|
62
|
+
The web data layer doesn't survive the move - relative fetches, cookie sessions, `localStorage`, and env vars all change (swaps in false-friends). Use `expo-data-fetching` for requests and caching; add `eas-hosting` if the backend moved to EAS Hosting.
|
|
63
|
+
|
|
64
|
+
### 6. Ship
|
|
65
|
+
|
|
66
|
+
`eas-app-stores` for the store builds (App Store / Play / TestFlight), EAS Update for OTA pushes after.
|
|
67
|
+
|
|
68
|
+
## Verify by running, not compiling
|
|
69
|
+
|
|
70
|
+
A green `expo export` proves a screen *bundles*, not that it *renders* — a screen can build and still render blank or mis-render. So after the shell and after every nativized screen, compare the two **running** apps for the same route:
|
|
71
|
+
|
|
72
|
+
- **Web original** — capture it with **`agent-browser`** (vercel-labs CLI): `open` the route, `snapshot --json` the accessibility tree, `screenshot`.
|
|
73
|
+
- **Native** — drive the simulator with **`argent`**: `describe` / `debugger-component-tree` for structure, `flow` to replay the check each pass.
|
|
74
|
+
|
|
75
|
+
Pass on parity of **content and behavior** — not pixels: a nativized screen should look *more* native than the web, never identical (the DOM-shell stage is the exception — there it *is* the web UI, so it should match). Feel is part of native and can't be screenshotted — for screens with transitions or gestures, capture a short recording, not just a still (see `native-patterns.md` → Feel). This loop is **opinionated about its tooling**: if `agent-browser` or `argent` isn't installed, ask the user and install it before proceeding — don't fall back to manual screenshots. Full recipe and setup in [`./references/verify-on-device.md`](./references/verify-on-device.md).
|
|
76
|
+
|
|
77
|
+
## References
|
|
78
|
+
|
|
79
|
+
- [`./references/false-friends.md`](./references/false-friends.md) — web idiom → native equivalent + the gotcha for each. The lookup for steps 3–5, and for any web dev unlearning idioms.
|
|
80
|
+
- [`./references/native-patterns.md`](./references/native-patterns.md) — web UX *pattern* → native redesign (`@expo/ui`-first). The step-4 redesign playbook so screens feel OS-native, not reskinned.
|
|
81
|
+
- [`./references/verify-on-device.md`](./references/verify-on-device.md) — the two-agent parity recipe: drive the web app (browser agent) and the native app (argent), open the same route, compare.
|
|
82
|
+
- [`./references/run-as-goal.md`](./references/run-as-goal.md) — a ready-shaped, migration-specific goal objective for driving step 4 unattended (re-reads this skill each iteration).
|
|
83
|
+
- [Expo — From Web to Native with React](https://expo.dev/blog/from-web-to-native-with-react) — the canonical guide this skill operationalizes.
|
|
84
|
+
|
|
85
|
+
## Submitting Feedback
|
|
86
|
+
If you encounter errors, misleading or outdated information in this skill, report it so Expo can improve:
|
|
87
|
+
```bash
|
|
88
|
+
npx --yes @expo/agent-cli@latest feedback --category skills --subject "expo-web-to-native" "<actionable feedback>"
|
|
89
|
+
```
|
|
90
|
+
Only submit when you have something specific and actionable to report. Include as much relevant context as possible.
|
|
91
|
+
If an agent repeatedly fails at an Expo task or the user has to step in, submit a brief report of the task, expected result, and what went wrong using `--category evals` and the relevant Expo package or command as `--subject`.
|
package/dist/templates/default/apps/mobile/.agents/skills/expo-web-to-native/agents/openai.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Expo Web to Native"
|
|
3
|
+
short_description: "Migrate an existing web React app (Next.js, Vite, CRA) to a native iOS/Android app with Expo, screen by screen"
|
|
4
|
+
default_prompt: "Use $expo-web-to-native to migrate a web React codebase to native: assess and bucket screens, ship a DOM-component shell on day one, then nativize screens in priority order with @expo/ui and Expo Router."
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# False Friends: web idioms → native
|
|
2
|
+
|
|
3
|
+
Disclosed reference for [`expo-web-to-native`](../SKILL.md). A *false friend* is a web idiom that looks portable but isn't - it compiles in your head, then breaks (or silently no-ops) on native. Each row is `web idiom → native equivalent → the gotcha`. Reach for this in steps 3–5 of a migration, and whenever you're learning native after the web.
|
|
4
|
+
|
|
5
|
+
This is the single source of truth for the mapping; the SKILL.md steps name a few high-traffic swaps but defer the full list here.
|
|
6
|
+
|
|
7
|
+
## Elements & text
|
|
8
|
+
|
|
9
|
+
| Web | Native | Gotcha |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `<div>`, `<section>`, `<span>` | `<View>` | `View` is the only generic container; no semantic element variants. |
|
|
12
|
+
| `<p>`, `<h1>`, raw text in JSX | `<Text>` | **All** text must sit inside `<Text>`. Bare strings in a `View` throw. |
|
|
13
|
+
| `<img src>` | `<Image>` / `expo-image` | `expo-image` adds caching, blurhash, transitions. Remote images need an explicit `width`/`height` or a flex parent. |
|
|
14
|
+
| `<button>`, `<a>` | `<Pressable>` | No default styling, no hover. Wrap label text in `<Text>`. |
|
|
15
|
+
| `<input>` | `<TextInput>` | Controlled via `value` + `onChangeText` (not `onChange`/`e.target.value`). |
|
|
16
|
+
| `<ul>/<li>` rendered with `.map()` | `<FlatList>` / `<FlashList>` | `.map()` over a long list mounts every row at once → jank. Use a virtualized list with `data` + `renderItem`. |
|
|
17
|
+
|
|
18
|
+
## Events & interaction
|
|
19
|
+
|
|
20
|
+
| Web | Native | Gotcha |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `onClick` | `onPress` | Also `onLongPress`, `onPressIn/Out`. There is no click. |
|
|
23
|
+
| `onChange={e => e.target.value}` | `onChangeText={text => ...}` | The handler receives the string directly, not an event. |
|
|
24
|
+
| `onSubmit` (form) | `onPress` / `onSubmitEditing` | No `<form>` element and no submit event; wire the button/keyboard return key. |
|
|
25
|
+
| `:hover`, `:focus` | press/focus state | No hover on touch. Track state and style from it, or use `Pressable`'s state callback. |
|
|
26
|
+
| `e.preventDefault()` | — | No default actions to prevent; remove it. |
|
|
27
|
+
|
|
28
|
+
## Styling & layout
|
|
29
|
+
|
|
30
|
+
| Web | Native | Gotcha |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `className` / CSS files | `StyleSheet.create` or NativeWind | Plain RN has no className. For Tailwind muscle memory use NativeWind. |
|
|
33
|
+
| CSS cascade & inheritance | none | Styles don't inherit (except a few `Text` props like `color`/`fontSize` to nested `Text`). Style each node. |
|
|
34
|
+
| `display: flex` opt-in, default `row` | flex always on, default **`column`** | Biggest layout surprise: flex is the only layout model and the main axis is vertical by default. |
|
|
35
|
+
| `px`, `rem`, `%` | unitless numbers (dp) | `padding: 16` = density-independent pixels. `%` works in some props; no `rem`/`em`/`vh`. |
|
|
36
|
+
| `@media` queries | `useWindowDimensions()` / `Platform` | No media queries. Branch on dimensions or platform at runtime. |
|
|
37
|
+
| `position: fixed` | `position: absolute` + safe area | No `fixed`. Pin with `absolute` and respect insets (`react-native-safe-area-context`). |
|
|
38
|
+
| `z-index` | `zIndex` (+ `elevation` on Android) | Works mostly, but Android shadow/stacking also needs `elevation`. |
|
|
39
|
+
| CSS transitions / `@keyframes` | `Animated` / Reanimated | No CSS animation. Reanimated is the standard; gestures via `react-native-gesture-handler`. |
|
|
40
|
+
| `gap`, flexbox | `gap`, flexbox | These largely transfer — flexbox is the one big win for web devs. |
|
|
41
|
+
|
|
42
|
+
## Navigation & URLs
|
|
43
|
+
|
|
44
|
+
| Web | Native | Gotcha |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| React Router / Next.js routes | Expo Router (file-based) | File-based like Next App Router; `react-router` concepts map but the API differs. |
|
|
47
|
+
| `<a href>` / `<Link>` | `expo-router` `<Link href>` | Works in DOM components too. |
|
|
48
|
+
| `useNavigate()` / `router.push` | `useRouter()` from `expo-router` | `router.push/replace/back`. |
|
|
49
|
+
| `useParams` / `useSearchParams` | `useLocalSearchParams()` | Note: doesn't work *inside* a DOM component - read in the native parent, pass as props (see `expo-dom`). |
|
|
50
|
+
| `window.location` | `usePathname()` / router | No `location` object. |
|
|
51
|
+
| Deep links / `myapp://` | URL scheme + universal links | Configure `scheme` in app config; native gives you real deep linking and (with AASA) app links - see `expo-app-clip` for the AASA file. |
|
|
52
|
+
|
|
53
|
+
## React architecture & data (Next.js / SSR apps)
|
|
54
|
+
|
|
55
|
+
| Web | Native | Gotcha |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| Async Server Component (`async function Page()`) | client component + data fetch | No RSC on native (Expo's is experimental and different). Split into a client component that fetches via the API + a presentational child *before* porting. |
|
|
58
|
+
| Server actions (`'use server'`) | API route + `fetch` | No server actions. Expose an endpoint and call it. |
|
|
59
|
+
| `cookies()` / `headers()` (server) | token in `expo-secure-store` | Server-only. Auth moves to a bearer token sent as a header. |
|
|
60
|
+
| ORM / DB client in a page (Drizzle, Prisma) | server only - call over HTTP | The device never talks to the DB. Keep the backend deployed, or move routes to EAS Hosting (`eas-hosting`); the app fetches. |
|
|
61
|
+
| `next/navigation` (`notFound`, `redirect`) | `expo-router` | `redirect()` → `router.replace`; `notFound()` → a native `+not-found` route. |
|
|
62
|
+
| `_layout` as a DOM component | always native | Layout routes can't be DOM components — they *are* the native shell. Rewrite web-only layout logic (theme scripts, providers) with native APIs. |
|
|
63
|
+
|
|
64
|
+
## Storage, state & sessions
|
|
65
|
+
|
|
66
|
+
| Web | Native | Gotcha |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `localStorage` / `sessionStorage` | `expo-sqlite` (`globalThis.localStorage`) | `import 'expo-sqlite/localStorage/install';` polyfills the global `localStorage`, so existing code works as-is (or `expo-sqlite/kv-store`). **No `sessionStorage` equivalent** — native has no session concept. |
|
|
69
|
+
| Cookies / `document.cookie` | `expo-secure-store` + headers | No cookie jar by default. Store tokens in SecureStore; send as auth headers. |
|
|
70
|
+
| Auth via session cookie | token in SecureStore | Redesign auth around bearer tokens, not browser sessions. |
|
|
71
|
+
| In-memory React state | same | `useState`/`useReducer`/`useContext` transfer unchanged. |
|
|
72
|
+
|
|
73
|
+
## Browser & platform APIs
|
|
74
|
+
|
|
75
|
+
| Web | Native | Gotcha |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `window`, `document` | none | Don't exist. Guard web-only libs, or keep them in a DOM component (`expo-dom`). |
|
|
78
|
+
| `window.matchMedia('(prefers-color-scheme: dark)')` | `useColorScheme()` | Hook from `react-native`, reactive to the system theme. Web theme bootstrap scripts in the layout don't run. |
|
|
79
|
+
| `window.innerWidth/Height` | `useWindowDimensions()` | Reactive hook; updates on rotation. |
|
|
80
|
+
| `navigator.*`, Web APIs | Expo SDK modules | e.g. camera → `expo-camera`, geolocation → `expo-location`, clipboard → `expo-clipboard`. |
|
|
81
|
+
| `alert()` / `confirm()` / `prompt()` | `alert()` works; `Alert.alert(...)` for the rest | RN provides a global `alert()`; `confirm()` / `prompt()` don't exist — use `Alert.alert` with a button array. |
|
|
82
|
+
| `process.env.X` | `process.env.EXPO_PUBLIC_X` | Only `EXPO_PUBLIC_`-prefixed vars are inlined into the client bundle. |
|
|
83
|
+
| `console.log` | `console.log` | Works — shows in the dev tools/terminal. |
|
|
84
|
+
| `dangerouslySetInnerHTML` | — | No DOM to inject into. Render data, or use a DOM component / WebView. |
|
|
85
|
+
| inline SVG | `react-native-svg` | No native `<svg>`; the library mirrors the element API. |
|
|
86
|
+
|
|
87
|
+
## Networking
|
|
88
|
+
|
|
89
|
+
| Web | Native | Gotcha |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `fetch('/api/x')` (relative) | absolute URL | Native has no origin — relative paths fail. Use a configured base URL (`EXPO_PUBLIC_API_URL`). |
|
|
92
|
+
| CORS | n/a | No browser CORS, but you still need a reachable absolute host. |
|
|
93
|
+
| `fetch`, React Query, SWR | same | The libraries themselves work on native - see `expo-data-fetching`. |
|
|
94
|
+
| Next.js API routes | Expo Router API routes | Move server endpoints to Expo API routes on EAS Hosting - see `eas-hosting`. |
|
|
95
|
+
| Streaming responses (SSE, AI SDK `useChat`) | `expo/fetch` with `textStreaming` | RN's built-in `fetch` can't read a streaming response body. Use `expo/fetch` (streams, and works with the Vercel AI SDK) or an XHR-based polyfill. |
|
|
96
|
+
|
|
97
|
+
## Third-party services & SDKs
|
|
98
|
+
|
|
99
|
+
Browser SDKs don't run on native — each needs a native equivalent. The canonical, version-matched integrations live in the `expo-examples` skill (the `expo/examples` repo); reach for those instead of wiring from scratch.
|
|
100
|
+
|
|
101
|
+
| Web service | Native | Gotcha |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| **Stripe.js — digital goods / subscriptions** | store **In-App Purchase** via **RevenueCat** (`react-native-purchases`) | **Policy, not just an SDK swap.** Apple & Google *require* IAP for in-app digital goods and take ~15–30%; shipping Stripe for them gets the app rejected. Decide at assess time — it can change the business model. |
|
|
104
|
+
| **Stripe.js — physical goods / services** | `@stripe/stripe-react-native` (PaymentSheet, Apple/Google Pay) | Stripe's RN SDK is allowed for physical goods; see `expo-examples` `with-stripe`. |
|
|
105
|
+
| Google Maps JS | `react-native-maps` | A native map view, not an embedded iframe. |
|
|
106
|
+
| Web Push | `expo-notifications` (APNs / FCM) | Different delivery + permission model. |
|
|
107
|
+
| OAuth redirect flow | `expo-auth-session` (deep-link OAuth), or a native auth SDK (Clerk, Supabase…) | No browser redirect — an app deep link completes the flow. |
|
|
108
|
+
| GA / Segment.js analytics | native SDK (`posthog-react-native`, Segment RN) | The web JS snippet won't load; swap for the native SDK. |
|
|
109
|
+
| `<input type=file>` / `getUserMedia` | `expo-image-picker` / `expo-camera` / `expo-document-picker` | Native pickers + runtime permissions. |
|
|
110
|
+
|
|
111
|
+
## Scrolling, keyboard & safe area
|
|
112
|
+
|
|
113
|
+
| Web | Native | Gotcha |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| Body scrolls by default | `<ScrollView>` / `<FlatList>` | Nothing scrolls unless you make it. Wrap overflowing content explicitly. |
|
|
116
|
+
| `overflow: scroll` | `<ScrollView>` | Don't nest a `ScrollView` inside a `FlatList` of the same axis. |
|
|
117
|
+
| Keyboard overlaps inputs | `KeyboardAvoidingView` | The keyboard covers inputs by default; wrap forms to push content up. |
|
|
118
|
+
| Notch / status bar | `react-native-safe-area-context` | Content flows under the notch/home indicator unless you apply safe-area insets. |
|
|
119
|
+
| `:focus` ring, tab order | manual | No automatic focus management; wire `ref`/`focus()` and `returnKeyType`. |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Native patterns: redesigning web UX for native
|
|
2
|
+
|
|
3
|
+
Disclosed reference for [`expo-web-to-native`](../SKILL.md), step 4. `false-friends.md` translates *idioms* (`div` → `View`); this translates *UX patterns* - a web interaction into its native equivalent. Step 4 isn't a port, it's this redesign.
|
|
4
|
+
|
|
5
|
+
**Reach for `@expo/ui` first.** It renders real SwiftUI (iOS) and Jetpack Compose (Android), so its components look and feel *exactly* like the OS — the difference between "native-ish RN" and "indistinguishable from an app Apple/Google shipped." See the `expo-ui` skill. Drop to styled RN primitives only for what `@expo/ui` doesn't cover: custom layouts (chat bubbles, bespoke cards) and **large data lists** (`@expo/ui` `List` is a JS-thread node per item — use `FlashList`/`FlatList` for feeds). `@expo/ui` runs in **Expo Go** (SDK 56+) — no dev build needed; reach for a dev build (the `expo-dev-client` skill) only for *custom* native modules.
|
|
6
|
+
|
|
7
|
+
| Web pattern | Native redesign — reach for first | Why |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| Top tab bar / nav links | **NativeTabs** - bottom, liquid glass on iOS 26 (`expo-router`) | Thumb-reachable, OS-native bar |
|
|
10
|
+
| Page header / breadcrumb | **large-title** Stack header + header **search field** (`expo-router`) | The native screen frame |
|
|
11
|
+
| In-page tabs / toggle group | **SegmentedControl** — `@expo/ui` (`community/segmented-control`) | Native segmented switch |
|
|
12
|
+
| Modal / dialog | **BottomSheet** — `@expo/ui` | Sheets *are* the native modal |
|
|
13
|
+
| `<select>` / dropdown | **Picker**, or long-press **MenuView** — `@expo/ui` (`community/menu`) | Native wheel / menu, no popover |
|
|
14
|
+
| Accordion / "show more" | **Collapsible** — `@expo/ui` | Native disclosure |
|
|
15
|
+
| Settings / short list | **List** + **FieldGroup** rows (Switch / Picker / TextInput) — `@expo/ui` | The Settings-app look |
|
|
16
|
+
| Data feed / table / long list | **FlashList** / `FlatList`, virtualized + momentum | Tables don't exist on mobile; `@expo/ui` `List` isn't for big data |
|
|
17
|
+
| Checkbox / toggle | **Switch** (on/off) or **Checkbox** (multi-select) — `@expo/ui` | Native control, not a styled box |
|
|
18
|
+
| Date / time input | **DateTimePicker** — `@expo/ui` (`community/datetime-picker`) | Native wheel / calendar |
|
|
19
|
+
| Range slider | **Slider** — `@expo/ui` | |
|
|
20
|
+
| Onboarding / carousel / swipe pages | **PagerView** — `@expo/ui` (`community/pager-view`) | Native paging, not a scroll strip |
|
|
21
|
+
| Refresh button / auto-poll | pull-to-refresh (`RefreshControl`) | The native refresh gesture |
|
|
22
|
+
| Hover menu / tooltip | long-press **MenuView** context menu — `@expo/ui` (`community/menu`) | No hover on touch |
|
|
23
|
+
| Toast / snackbar | native banner + **haptic** (`expo-haptics`) | |
|
|
24
|
+
| Buttons | `@expo/ui` **Button**; `Pressable` for custom | Native press + haptics |
|
|
25
|
+
| Multi-column layout | single column + tabs / stack | One thing at a time on a phone |
|
|
26
|
+
|
|
27
|
+
**The test:** if a screenshot of the native screen could pass for the web version, you reskinned it. Redesign until it could pass for a screen the OS shipped.
|
|
28
|
+
|
|
29
|
+
## Feel — beyond the components
|
|
30
|
+
|
|
31
|
+
The table gets the right *components*; "native" also lives in *motion and touch* - and a web port arrives with almost none, so you must add it. The tooling is in `expo-router` (navigation/transitions) and `expo-native-ui` (motion/effects); reach for it, don't hand-roll:
|
|
32
|
+
|
|
33
|
+
- **Transitions for free** - use Expo Router's native-stack so push/pop, modals, and sheets animate with real platform physics; shared-element zoom via `expo-router` `zoom-transitions.md`.
|
|
34
|
+
- **Motion** - Reanimated (`withSpring`/`withTiming`) + `react-native-gesture-handler` for swipes/drags → load the `expo-animation` skill (purpose gate, timing values, interruption).
|
|
35
|
+
- **Touch** — `expo-haptics` on commits, selection changes, and pull-to-refresh — choreography, not just a toast buzz.
|
|
36
|
+
- **Native rhythm** — large-title collapse on scroll, momentum / inverted scroll, a keyboard that pushes content (`KeyboardAvoidingView`).
|
|
37
|
+
- **Respect reduced motion** — gate non-essential animation on Reanimated's `useReducedMotion()`.
|
|
38
|
+
|
|
39
|
+
**Feel can't be screenshotted.** A janky transition or wrong easing passes a still-image parity check and still betrays the app — for screens with motion, verify with a short recording (iOS `xcrun simctl io booted recordVideo feel.mov`; Android `adb shell screenrecord`; or a device-agent flow), not just a screenshot.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Run the migration as a goal loop
|
|
2
|
+
|
|
3
|
+
Disclosed reference for [`expo-web-to-native`](../SKILL.md) - the recommended way to drive the whole migration. The migration is a repeat-until-done loop (assess → nativize each screen → verify → check off), which is exactly the shape of a **goal loop**: a single objective re-injected every turn until the worklist is empty. This file carries a ready-shaped, migration-specific objective - and, crucially, the objective **re-reads this skill every iteration**, so the loop keeps following the playbook (and self-bootstraps the assess step if no worklist exists yet).
|
|
4
|
+
|
|
5
|
+
Use it in one of two modes depending on the agent you're running.
|
|
6
|
+
|
|
7
|
+
## Mode A — the agent can run a goal loop
|
|
8
|
+
|
|
9
|
+
Harnesses with a goal/loop command (Claude Code `/goal`, Codex CLI, or any harness of the same shape) can drive this themselves. Fill the template below and hand it to that command — the loop re-runs it until `migration-progress.md` has no unchecked nativize-now items.
|
|
10
|
+
|
|
11
|
+
## Mode B — the agent can't loop itself
|
|
12
|
+
|
|
13
|
+
Write the filled-in objective to `migration-goal.md` in the project, then give the user the one-line instruction to launch it (e.g. *"run your agent's goal loop with the objective in `migration-goal.md`"*). The objective is plain text and portable, so the user runs it in whatever harness they have.
|
|
14
|
+
|
|
15
|
+
## The objective (template)
|
|
16
|
+
|
|
17
|
+
Fill the two `<…>` slots, then run or hand off verbatim. It is written to survive re-injection — it restates its own worklist, direction, and stop condition every turn.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Goal: migrate <APP NAME> from web to a native Expo app by following the expo-web-to-native skill, one screen per iteration, until done.
|
|
21
|
+
|
|
22
|
+
Each iteration, FIRST re-read the playbook - plugins/expo/skills/expo-web-to-native/SKILL.md (and its references) - then:
|
|
23
|
+
1. If migration-progress.md doesn't exist yet, do the skill's step 1 (Assess) to
|
|
24
|
+
create the worklist, then stop. Otherwise open it and take the top unchecked
|
|
25
|
+
item under "nativize-now"; if none are left unresolved (every nativize-now is
|
|
26
|
+
done or blocked), STOP and summarize what shipped + what's blocked and why.
|
|
27
|
+
2. Redesign that screen native per the skill's step 4 — reach for @expo/ui FIRST
|
|
28
|
+
(real SwiftUI/Compose), then expo-router (NativeTabs, large titles);
|
|
29
|
+
RN primitives only for custom layouts. NEVER a webview port.
|
|
30
|
+
Use references/native-patterns.md (UX patterns) and references/false-friends.md
|
|
31
|
+
(idioms). Match the web screen's content and behavior.
|
|
32
|
+
3. Verify per references/verify-on-device.md: compare the running web original
|
|
33
|
+
(browser agent) against the native screen (simulator / argent) — content and
|
|
34
|
+
behavior parity, NOT pixels (it should look more native). If it's off for reasons
|
|
35
|
+
IN the code, fix it this iteration. If it's blocked by something OUTSIDE the code
|
|
36
|
+
(missing backend/auth/data, or a secret you can't supply), don't loop — mark it
|
|
37
|
+
blocked in step 4 and move on.
|
|
38
|
+
4. Check the item off in migration-progress.md, appending one line:
|
|
39
|
+
"<screen> — done", or "<screen> — blocked: <reason> — needs <what would unlock>".
|
|
40
|
+
Either way the item is resolved; never revisit a blocked one.
|
|
41
|
+
|
|
42
|
+
Rules: one screen per pass; the app builds green each iteration; @expo/ui before RN primitives; never touch "nativize-later" items.
|
|
43
|
+
Base API URL for native (no relative paths): <EXPO_PUBLIC_API_URL>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Why a pre-shaped objective
|
|
47
|
+
|
|
48
|
+
The objective is filled in for this migration — worklist, redesign rules, and self-verification path already wired to the skill's references — so you can launch the loop without authoring one from scratch. Tailor the `<…>` slots and direction when a specific migration needs more than the template covers.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Verify a migrated screen against the running web app
|
|
2
|
+
|
|
3
|
+
Disclosed reference for [`expo-web-to-native`](../SKILL.md), steps 3–4. Verification means **running both apps and comparing the same screen** - the native port beside the web original. A clean compile or a green `expo export` proves nothing - a screen can build and still render blank or mis-render. This parity check is the gate the strangle loop runs each iteration.
|
|
4
|
+
|
|
5
|
+
Two agents drive it, and this skill is **opinionated**: it requires both and installs them rather than falling back to manual screenshots.
|
|
6
|
+
|
|
7
|
+
- **Web side — `agent-browser`** (vercel-labs, a Rust browser CLI): `open <url>`, `snapshot --json` (accessibility tree with refs), `screenshot <path>`, `read` (rendered DOM/text).
|
|
8
|
+
- **Native side — `argent`** (`@swmansion/argent`): drives the simulator — `describe` (a11y tree), `debugger-component-tree` (RN tree), `gesture-tap`/`keyboard`, `flow` to record a check and replay it each pass. Invoke as `argent run <tool> --udid <udid>` (get the udid from `argent run list-devices`).
|
|
9
|
+
|
|
10
|
+
## Setup — install if missing (don't skip, don't fall back to manual)
|
|
11
|
+
|
|
12
|
+
Check both are on PATH; if either is absent, ask the user, then install before proceeding:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
which agent-browser || (npm i -g agent-browser && agent-browser install) # web agent (+ its Chrome)
|
|
16
|
+
which argent || npm i -g @swmansion/argent # device agent
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## The workflow
|
|
20
|
+
|
|
21
|
+
**A. Capture the web original** with agent-browser — the source of truth for parity. Run the web app (its `pnpm dev` server, or the **deployed URL** if local setup needs DB/auth env), then:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
agent-browser open "<web-url>/<route>?<params>"
|
|
25
|
+
agent-browser snapshot --json # structure to diff
|
|
26
|
+
agent-browser screenshot web.png # visual reference
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Tip:** capture web baselines for every screen once, up front, then diff against them instead of re-opening the web app each iteration.
|
|
30
|
+
|
|
31
|
+
**B. Capture the native screen** (iOS shown via `simctl`; Android note below):
|
|
32
|
+
1. Run the app: `npx expo start --ios` (Expo Go). To keep the onboarding sheet, dev menu, and Tools button out of your screenshots on SDK 57 and earlier, and on the URLs you open yourself in step 3, see `../../expo-overview/references/launch-without-dev-menu.md`. On **SDK 56+ both `@expo/ui` and DOM components run in Expo Go** — no dev build, no `react-native-webview` to install; reach for a dev build (the `expo-dev-client` skill) only for *custom* native modules. Stale-bundle trap: a CI-mode Metro + cached Expo Go can show an old build — terminate Expo Go and add `--clear` if a change doesn't appear.
|
|
33
|
+
2. Boot a sim: `xcrun simctl boot <udid>` (`xcrun simctl list devices available`); `open -a Simulator`.
|
|
34
|
+
3. Open the route: deep-link `xcrun simctl openurl booted "exp://<lan-ip>:8081/--/<route>?<params>"`, or argent `launch-app` + `gesture-tap`.
|
|
35
|
+
4. Capture: `xcrun simctl io booted screenshot native.png`, or `argent run describe --udid <udid>` for structure.
|
|
36
|
+
|
|
37
|
+
> **Android:** `simctl` / `expo run:ios` are iOS-only. Use an Android emulator + `adb` — `adb exec-out screencap -p > native.png`, `adb shell am start -a android.intent.action.VIEW -d "<deep-link>"`, `adb shell screenrecord` for motion — or `npx expo run:android` for a dev build.
|
|
38
|
+
|
|
39
|
+
**C. Compare** the two for the same route — layout, content, behavior. Diff the structures (agent-browser `snapshot` against argent `describe` / `debugger-component-tree`), not just pixels. Pass only on parity: same data, and params passed into a DOM webview must produce the same result.
|
|
40
|
+
|
|
41
|
+
**Feel needs motion, not a still.** For a nativized screen with transitions, gestures, or haptics, a screenshot can't catch a janky push or wrong easing — capture a short recording (iOS `xcrun simctl io booted recordVideo feel.mov`; Android `adb shell screenrecord`; or an argent flow) and confirm it moves like a native app (see `native-patterns.md` → Feel).
|
|
42
|
+
|
|
43
|
+
## What "pass" looks like
|
|
44
|
+
- **DOM-shelled screen (step 3):** the web UI renders inside the native header/shell; params from the native route drive it the same as on web.
|
|
45
|
+
- **Nativized screen (step 4):** native primitives only, no webview; matches the web original screen.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ios-simulator
|
|
3
|
+
description: Verify and debug native, React Native, Expo, or Flutter apps on an iOS Simulator with agent-device. Use when an agent needs to launch an app, inspect its live UI, tap, type, scroll, validate a code change, collect failure evidence, or reproduce a workflow on an iPhone or iPad Simulator.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# iOS Simulator
|
|
7
|
+
|
|
8
|
+
Require the `agent-device` CLI to be installed separately before driving a simulator:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install -g agent-device@latest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Treat installation and upgrades as user-owned setup steps. Do not run that command autonomously or substitute a mutable `npx -y agent-device@latest` invocation.
|
|
15
|
+
|
|
16
|
+
For a normal app-driving task, start immediately. Do not probe first with `--help`, `--version`, `devices`, `appstate`, `snapshot`, or `screenshot`. Target iOS explicitly when opening an app or bundle id:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
agent-device open <app-or-bundle-id> --platform ios --foreground
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Follow the initial interactive snapshot and corrective error hints. If the shell reports that `agent-device` is unavailable, stop and ask the user to install it or expose their existing installation on `PATH`.
|
|
23
|
+
|
|
24
|
+
Only when the task is specialized or a command shape is unclear, read the relevant version-matched help topic:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
agent-device help validate # engineering validation and build freshness
|
|
28
|
+
agent-device help debugging # screenshots, logs, traces, video, and failures
|
|
29
|
+
agent-device help react-native # React Native and Expo runtime guidance
|
|
30
|
+
agent-device help react-devtools # React components, props/state/hooks, render profiling
|
|
31
|
+
agent-device help scripting # durable replay and CI workflows
|
|
32
|
+
```
|
package/dist/templates/default/apps/mobile/.agents/skills/react-native-best-practices/POWER.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-native-best-practices
|
|
3
|
+
description: Provides React Native performance optimization guidelines for FPS, TTI, bundle size, memory leaks, re-renders, and animations. Applies to tasks involving Hermes optimization, JS thread blocking, bridge overhead, FlashList, native modules, or debugging jank and frame drops.
|
|
4
|
+
license: MIT
|
|
5
|
+
author: Callstack
|
|
6
|
+
keywords: ["react-native", "expo", "performance", "optimization", "profiling"]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Onboarding
|
|
10
|
+
|
|
11
|
+
## Step 1: Validate React Native Setup
|
|
12
|
+
|
|
13
|
+
Before applying performance optimizations, ensure:
|
|
14
|
+
- **Expo CLI** or **React Native CLI** is installed
|
|
15
|
+
- Verify with: `npx expo --version` and `npx react-native --version`
|
|
16
|
+
- Metro bundler is running (**apply only for** bundle analysis)
|
|
17
|
+
- React Native DevTools profiling is available through `agent-device react-devtools` (**apply only for** React render profiling/debugging)
|
|
18
|
+
- Run `agent-device react-devtools status`, then `agent-device react-devtools wait --connected`
|
|
19
|
+
|
|
20
|
+
## Security Guardrails
|
|
21
|
+
|
|
22
|
+
- Review shell commands before running them and prefer version-pinned tooling from trusted sources.
|
|
23
|
+
- Do not pipe remote install scripts directly into a shell.
|
|
24
|
+
- Treat third-party packages as normal supply-chain dependencies that require provenance and version review.
|
|
25
|
+
- If using remote chunk loading, prefer app-bundled chunks or signed CI release manifests; hosted chunks must be first-party artifacts tied to the current release.
|
|
26
|
+
|
|
27
|
+
# When to Load Reference Files
|
|
28
|
+
|
|
29
|
+
Load specific reference files from `references/` based on the task:
|
|
30
|
+
|
|
31
|
+
## JavaScript/React Performance (`js-*`)
|
|
32
|
+
|
|
33
|
+
- **Debugging slow/janky UI or animations** → `references/js-measure-fps.md`
|
|
34
|
+
- **Investigating re-render issues** → `references/js-profile-react.md` → `references/js-react-compiler.md`
|
|
35
|
+
- **Optimizing list scrolling** → `references/js-lists-flatlist-flashlist.md`
|
|
36
|
+
- **Reducing re-renders with state management** → `references/js-atomic-state.md`
|
|
37
|
+
- **Using Concurrent React features** → `references/js-concurrent-react.md`
|
|
38
|
+
- **Enabling automatic memoization** → `references/js-react-compiler.md`
|
|
39
|
+
- **Optimizing animations** → `references/js-animations-reanimated.md`
|
|
40
|
+
- **Fixing TextInput lag** → `references/js-uncontrolled-components.md`
|
|
41
|
+
- **Hunting JavaScript memory leaks** → `references/js-memory-leaks.md`
|
|
42
|
+
|
|
43
|
+
## Native Performance (`native-*`)
|
|
44
|
+
|
|
45
|
+
- **Measuring startup time (TTI)** → `references/native-measure-tti.md`
|
|
46
|
+
- **Building native modules** → `references/native-turbo-modules.md`
|
|
47
|
+
- **Understanding native threading** → `references/native-threading-model.md`
|
|
48
|
+
- **Profiling native code** → `references/native-profiling.md`
|
|
49
|
+
- **Setting up native tooling** → `references/native-platform-setup.md`
|
|
50
|
+
- **Debugging view hierarchy** → `references/native-view-flattening.md`
|
|
51
|
+
- **Native memory patterns** → `references/native-memory-patterns.md`
|
|
52
|
+
- **Hunting native memory leaks** → `references/native-memory-leaks.md`
|
|
53
|
+
- **Choosing native SDKs vs polyfills** → `references/native-sdks-over-polyfills.md`
|
|
54
|
+
- **Fixing Android 16KB alignment** → `references/native-android-16kb-alignment.md`
|
|
55
|
+
|
|
56
|
+
## Bundle & App Size (`bundle-*`)
|
|
57
|
+
|
|
58
|
+
- **Analyzing bundle size** → `references/bundle-analyze-js.md`
|
|
59
|
+
- **Analyzing app size** → `references/bundle-analyze-app.md`
|
|
60
|
+
- **Fixing barrel imports** → `references/bundle-barrel-exports.md`
|
|
61
|
+
- **Enabling tree shaking** → `references/bundle-tree-shaking.md`
|
|
62
|
+
- **Android code shrinking** → `references/bundle-r8-android.md`
|
|
63
|
+
- **Optimizing Hermes bundle loading** → `references/bundle-hermes-mmap.md`
|
|
64
|
+
- **Managing native assets** → `references/bundle-native-assets.md`
|
|
65
|
+
- **Evaluating library size** → `references/bundle-library-size.md`
|
|
66
|
+
- **Code splitting** → `references/bundle-code-splitting.md`
|
|
67
|
+
|
|
68
|
+
## Problem → Reference Mapping
|
|
69
|
+
|
|
70
|
+
Use this quick lookup when debugging specific issues:
|
|
71
|
+
|
|
72
|
+
| Problem | Start With |
|
|
73
|
+
|---------|-----------|
|
|
74
|
+
| App feels slow/janky | `references/js-measure-fps.md` → `references/js-profile-react.md` |
|
|
75
|
+
| Too many re-renders | `references/js-profile-react.md` → `references/js-react-compiler.md` |
|
|
76
|
+
| Slow startup (TTI) | `references/native-measure-tti.md` → `references/bundle-analyze-js.md` |
|
|
77
|
+
| Large app size | `references/bundle-analyze-app.md` → `references/bundle-r8-android.md` |
|
|
78
|
+
| Memory growing | `references/js-memory-leaks.md` or `references/native-memory-leaks.md` |
|
|
79
|
+
| Animation drops frames | `references/js-animations-reanimated.md` |
|
|
80
|
+
| List scroll jank | `references/js-lists-flatlist-flashlist.md` |
|
|
81
|
+
| TextInput lag | `references/js-uncontrolled-components.md` |
|
|
82
|
+
| Native module slow | `references/native-turbo-modules.md` → `references/native-threading-model.md` |
|
|
83
|
+
| Native library alignment issue | `references/native-android-16kb-alignment.md` |
|
|
84
|
+
|
|
85
|
+
## Quick Reference Commands
|
|
86
|
+
|
|
87
|
+
### FPS & Re-renders
|
|
88
|
+
```bash
|
|
89
|
+
agent-device react-devtools status
|
|
90
|
+
agent-device react-devtools wait --connected
|
|
91
|
+
agent-device react-devtools profile start
|
|
92
|
+
agent-device react-devtools profile stop
|
|
93
|
+
agent-device react-devtools profile slow --limit 5
|
|
94
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
95
|
+
agent-device react-devtools profile timeline --limit 20
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Drive the target interaction with normal `agent-device` commands between `profile start` and `profile stop`.
|
|
99
|
+
|
|
100
|
+
Manual fallback when `agent-device` is unavailable: open React Native DevTools from Metro (`j`) or the Dev Menu, use the Profiler tab, and record the same interaction.
|
|
101
|
+
|
|
102
|
+
For release-build React component profiling, connect [`@callstack/inspector`](https://github.com/callstackincubator/inspector#inspector) first so React DevTools can attach to the release app, then run the `agent-device react-devtools` flow above.
|
|
103
|
+
|
|
104
|
+
Baseline runtime metrics should come from the target interaction itself:
|
|
105
|
+
- Capture commit timeline, re-render counts, slow components, and heaviest-commit breakdown.
|
|
106
|
+
- Treat component tree depth and count as supporting context only.
|
|
107
|
+
|
|
108
|
+
**Common fixes:**
|
|
109
|
+
- Replace ScrollView with FlatList/FlashList for lists
|
|
110
|
+
- After profiling shows cascading re-renders, use React Compiler for automatic memoization
|
|
111
|
+
- After profiling shows broad store/context updates, use atomic state (Jotai/Zustand) to reduce re-renders
|
|
112
|
+
- Use `useDeferredValue` for expensive computations
|
|
113
|
+
|
|
114
|
+
**Review guardrails:**
|
|
115
|
+
- Check library versions before suggesting API-specific fixes. FlashList v2 deprecates `estimatedItemSize`.
|
|
116
|
+
- Do not suggest `useMemo` or `useCallback` dependency changes without a reproducible correctness issue or profiling evidence.
|
|
117
|
+
- Do not report stale closures unless the stale read path or repro is clear.
|
|
118
|
+
|
|
119
|
+
### Analyze Bundle Size
|
|
120
|
+
```bash
|
|
121
|
+
npx react-native bundle \
|
|
122
|
+
--entry-file index.js \
|
|
123
|
+
--bundle-output output.js \
|
|
124
|
+
--platform ios \
|
|
125
|
+
--sourcemap-output output.js.map \
|
|
126
|
+
--dev false --minify true
|
|
127
|
+
|
|
128
|
+
npx source-map-explorer output.js --no-border-checks
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Common fixes:**
|
|
132
|
+
- Avoid barrel imports (import directly from source)
|
|
133
|
+
- Remove unnecessary Intl polyfills only after checking Hermes API and method coverage
|
|
134
|
+
- Evaluate tree shaking (Expo SDK 52+ experimental unused import/export removal, or Re.Pack only if already configured)
|
|
135
|
+
- Enable R8 for Android native code shrinking
|
|
136
|
+
|
|
137
|
+
### Measure TTI
|
|
138
|
+
- Use `react-native-performance` for markers
|
|
139
|
+
- Only measure cold starts (exclude warm/hot/prewarm)
|
|
140
|
+
|
|
141
|
+
**Common fixes:**
|
|
142
|
+
- For React Native 0.78 and earlier, disable Android JS bundle compression to enable Hermes mmap
|
|
143
|
+
- Use native navigation (react-native-screens)
|
|
144
|
+
- Preload commonly-used expensive screens before navigating to them
|
|
145
|
+
|
|
146
|
+
### Native Performance
|
|
147
|
+
|
|
148
|
+
**Profile native:**
|
|
149
|
+
- iOS: Xcode Instruments → Time Profiler
|
|
150
|
+
- Android: Android Studio → CPU Profiler
|
|
151
|
+
|
|
152
|
+
**Common fixes:**
|
|
153
|
+
- Use background threads for heavy native work
|
|
154
|
+
- Prefer async over sync Turbo Module methods
|
|
155
|
+
- Use C++ for cross-platform performance-critical code
|
|
156
|
+
|
|
157
|
+
## Priority Guidelines
|
|
158
|
+
|
|
159
|
+
Apply optimizations in this order:
|
|
160
|
+
|
|
161
|
+
| Priority | Category | Impact | Prefix |
|
|
162
|
+
|----------|----------|--------|--------|
|
|
163
|
+
| 1 | FPS & Re-renders | CRITICAL | `js-*` |
|
|
164
|
+
| 2 | Bundle Size | CRITICAL | `bundle-*` |
|
|
165
|
+
| 3 | TTI Optimization | HIGH | `native-*`, `bundle-*` |
|
|
166
|
+
| 4 | Native Performance | HIGH | `native-*` |
|
|
167
|
+
| 5 | Memory Management | MEDIUM-HIGH | `js-*`, `native-*` |
|
|
168
|
+
| 6 | Animations | MEDIUM | `js-*` |
|
|
169
|
+
|
|
170
|
+
## Attribution
|
|
171
|
+
|
|
172
|
+
Based on "The Ultimate Guide to React Native Optimization" by Callstack.
|