@jhm1909/ag-kit 0.1.0
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/.agent/ARCHITECTURE.md +189 -0
- package/.agent/known-registries.json +181 -0
- package/.agent/mcp_config.json +19 -0
- package/.agent/rules/clean-code.md +107 -0
- package/.agent/rules/documents.md +177 -0
- package/.agent/rules/git-workflow.md +68 -0
- package/.agent/rules/nano-banana.md +46 -0
- package/.agent/rules/research.md +35 -0
- package/.agent/rules/skill-loading.md +100 -0
- package/.agent/rules/skill-suggestion.md +47 -0
- package/.agent/rules/testing.md +52 -0
- package/.agent/rules/workflow-advisor.md +108 -0
- package/.agent/rules/workflow-skill-convention.md +127 -0
- package/.agent/skills/ai-engineer/SKILL.md +824 -0
- package/.agent/skills/ai-engineer/references/agentic-patterns.md +329 -0
- package/.agent/skills/ai-engineer/references/evaluation.md +493 -0
- package/.agent/skills/ai-engineer/references/llm.md +490 -0
- package/.agent/skills/ai-engineer/references/rag-advanced.md +444 -0
- package/.agent/skills/ai-engineer/references/serving-optimization.md +531 -0
- package/.agent/skills/ai-engineer/vector-db/README.md +137 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +41 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
- package/.agent/skills/backend-developer/SKILL.md +763 -0
- package/.agent/skills/backend-developer/references/general-patterns.md +65 -0
- package/.agent/skills/backend-developer/references/go-echo.md +68 -0
- package/.agent/skills/backend-developer/references/go-gin.md +76 -0
- package/.agent/skills/backend-developer/references/java-springboot.md +83 -0
- package/.agent/skills/backend-developer/references/node-express.md +64 -0
- package/.agent/skills/backend-developer/references/node-nestjs.md +69 -0
- package/.agent/skills/backend-developer/references/python-django.md +67 -0
- package/.agent/skills/backend-developer/references/python-fastapi.md +80 -0
- package/.agent/skills/blockchain-engineer/SKILL.md +975 -0
- package/.agent/skills/blockchain-engineer/references/deployment.md +28 -0
- package/.agent/skills/blockchain-engineer/references/evm.md +14 -0
- package/.agent/skills/blockchain-engineer/references/mechanisms.md +32 -0
- package/.agent/skills/blockchain-engineer/references/solidity.md +32 -0
- package/.agent/skills/business-analysis/SKILL.md +85 -0
- package/.agent/skills/business-analysis/references/best-practices/diagrams.md +141 -0
- package/.agent/skills/business-analysis/references/domains/ai-agent.md +94 -0
- package/.agent/skills/business-analysis/references/domains/blockchain-dapp.md +86 -0
- package/.agent/skills/business-analysis/references/domains/ecommerce.md +77 -0
- package/.agent/skills/business-analysis/references/domains/education.md +42 -0
- package/.agent/skills/business-analysis/references/domains/fintech.md +44 -0
- package/.agent/skills/business-analysis/references/domains/fnb.md +82 -0
- package/.agent/skills/business-analysis/references/domains/healthtech.md +44 -0
- package/.agent/skills/business-analysis/references/domains/internal-tools.md +38 -0
- package/.agent/skills/business-analysis/references/domains/marketplace.md +52 -0
- package/.agent/skills/business-analysis/references/domains/saas.md +36 -0
- package/.agent/skills/business-analysis/references/workflows/collaboration.md +41 -0
- package/.agent/skills/business-analysis/scripts/verify_mermaid.py +86 -0
- package/.agent/skills/business-analysis/templates/brd.md +46 -0
- package/.agent/skills/business-analysis/templates/change-request.md +41 -0
- package/.agent/skills/business-analysis/templates/prd-functional.md +38 -0
- package/.agent/skills/business-analysis/templates/use-case.md +40 -0
- package/.agent/skills/business-analysis/templates/user-story-detailed.md +36 -0
- package/.agent/skills/code-review/SKILL.md +113 -0
- package/.agent/skills/code-review/references/code-review-reception.md +209 -0
- package/.agent/skills/code-review/references/differential_review.md +59 -0
- package/.agent/skills/code-review/references/requesting-code-review.md +105 -0
- package/.agent/skills/code-review/references/spec_compliance.md +43 -0
- package/.agent/skills/code-review/references/verification-before-completion.md +139 -0
- package/.agent/skills/context-engineering/SKILL.md +68 -0
- package/.agent/skills/context-engineering/references/context-compression.md +84 -0
- package/.agent/skills/context-engineering/references/context-degradation.md +93 -0
- package/.agent/skills/context-engineering/references/context-fundamentals.md +75 -0
- package/.agent/skills/context-engineering/references/context-optimization.md +82 -0
- package/.agent/skills/context-engineering/references/evaluation.md +89 -0
- package/.agent/skills/context-engineering/references/memory-systems.md +88 -0
- package/.agent/skills/context-engineering/references/multi-agent-patterns.md +90 -0
- package/.agent/skills/context-engineering/references/project-development.md +97 -0
- package/.agent/skills/context-engineering/references/tool-design.md +86 -0
- package/.agent/skills/debugging/SKILL.md +60 -0
- package/.agent/skills/debugging/references/defense-in-depth.md +130 -0
- package/.agent/skills/debugging/references/root-cause-tracing.md +177 -0
- package/.agent/skills/debugging/references/systematic-debugging.md +295 -0
- package/.agent/skills/debugging/references/verification-before-completion.md +142 -0
- package/.agent/skills/designer/SKILL.md +159 -0
- package/.agent/skills/designer/concepts/apple-glass.md +48 -0
- package/.agent/skills/designer/concepts/aurora-gradients.md +26 -0
- package/.agent/skills/designer/concepts/bento-grids.md +14 -0
- package/.agent/skills/designer/concepts/claymorphism.md +27 -0
- package/.agent/skills/designer/concepts/neo-brutalism.md +32 -0
- package/.agent/skills/designer/data/app-interface.csv +31 -0
- package/.agent/skills/designer/data/charts.csv +26 -0
- package/.agent/skills/designer/data/colors.csv +162 -0
- package/.agent/skills/designer/data/design.csv +1776 -0
- package/.agent/skills/designer/data/icons.csv +106 -0
- package/.agent/skills/designer/data/landing.csv +35 -0
- package/.agent/skills/designer/data/products.csv +162 -0
- package/.agent/skills/designer/data/react-performance.csv +45 -0
- package/.agent/skills/designer/data/styles.csv +85 -0
- package/.agent/skills/designer/data/typography.csv +74 -0
- package/.agent/skills/designer/data/ui-reasoning.csv +162 -0
- package/.agent/skills/designer/data/ux-guidelines.csv +100 -0
- package/.agent/skills/designer/references/accessibility.md +172 -0
- package/.agent/skills/designer/references/branding.md +88 -0
- package/.agent/skills/designer/references/color-theory.md +139 -0
- package/.agent/skills/designer/references/creation.md +118 -0
- package/.agent/skills/designer/references/design-systems.md +219 -0
- package/.agent/skills/designer/references/frontend_design_aesthetics.md +57 -0
- package/.agent/skills/designer/references/layout.md +200 -0
- package/.agent/skills/designer/references/motion.md +92 -0
- package/.agent/skills/designer/references/review.md +100 -0
- package/.agent/skills/designer/references/trends.md +209 -0
- package/.agent/skills/designer/references/typography.md +190 -0
- package/.agent/skills/designer/scripts/remove_background.py +135 -0
- package/.agent/skills/designer/scripts/ui-search/__pycache__/core.cpython-314.pyc +0 -0
- package/.agent/skills/designer/scripts/ui-search/__pycache__/design_system.cpython-314.pyc +0 -0
- package/.agent/skills/designer/scripts/ui-search/core.py +217 -0
- package/.agent/skills/designer/scripts/ui-search/design_system.py +1067 -0
- package/.agent/skills/designer/scripts/ui-search/search.py +114 -0
- package/.agent/skills/designer/templates/design-motion-spec.md +30 -0
- package/.agent/skills/devops-engineer/SKILL.md +90 -0
- package/.agent/skills/devops-engineer/docker-compose/README.md +47 -0
- package/.agent/skills/devops-engineer/references/ci-cd-pipelines.md +76 -0
- package/.agent/skills/devops-engineer/references/cloud-providers.md +57 -0
- package/.agent/skills/devops-engineer/references/codebase-normalization.md +104 -0
- package/.agent/skills/devops-engineer/references/container-orchestration.md +69 -0
- package/.agent/skills/devops-engineer/references/iac-tools.md +63 -0
- package/.agent/skills/devops-engineer/references/observability-security.md +45 -0
- package/.agent/skills/devops-engineer/references/vercel-supabase.md +17 -0
- package/.agent/skills/devops-engineer/templates/release-notes.md +8 -0
- package/.agent/skills/frontend-developer/SKILL.md +125 -0
- package/.agent/skills/frontend-developer/react-nextjs/README.md +90 -0
- package/.agent/skills/frontend-developer/references/angular.md +52 -0
- package/.agent/skills/frontend-developer/references/composition_patterns.md +60 -0
- package/.agent/skills/frontend-developer/references/core-performance.md +68 -0
- package/.agent/skills/frontend-developer/references/modern-signals.md +43 -0
- package/.agent/skills/frontend-developer/references/react_performance_rules.md +55 -0
- package/.agent/skills/frontend-developer/references/vue-nuxt.md +55 -0
- package/.agent/skills/frontend-developer/scripts/validate_compliance.py +65 -0
- package/.agent/skills/frontend-developer/threejs/README.md +89 -0
- package/.agent/skills/frontend-developer/threejs/animation.md +552 -0
- package/.agent/skills/frontend-developer/threejs/fundamentals.md +488 -0
- package/.agent/skills/frontend-developer/threejs/geometry.md +548 -0
- package/.agent/skills/frontend-developer/threejs/interaction.md +660 -0
- package/.agent/skills/frontend-developer/threejs/lighting.md +481 -0
- package/.agent/skills/frontend-developer/threejs/loaders.md +623 -0
- package/.agent/skills/frontend-developer/threejs/materials.md +520 -0
- package/.agent/skills/frontend-developer/threejs/postprocessing.md +602 -0
- package/.agent/skills/frontend-developer/threejs/router.json +181 -0
- package/.agent/skills/frontend-developer/threejs/shaders.md +642 -0
- package/.agent/skills/frontend-developer/threejs/textures.md +628 -0
- package/.agent/skills/game-development/2d-games/SKILL.md +119 -0
- package/.agent/skills/game-development/3d-games/SKILL.md +135 -0
- package/.agent/skills/game-development/SKILL.md +167 -0
- package/.agent/skills/game-development/game-art/SKILL.md +185 -0
- package/.agent/skills/game-development/game-audio/SKILL.md +190 -0
- package/.agent/skills/game-development/game-design/SKILL.md +129 -0
- package/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
- package/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
- package/.agent/skills/game-development/pc-games/SKILL.md +144 -0
- package/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
- package/.agent/skills/game-development/web-games/SKILL.md +150 -0
- package/.agent/skills/lead-architect/SKILL.md +85 -0
- package/.agent/skills/lead-architect/references/application-architecture.md +70 -0
- package/.agent/skills/lead-architect/references/infrastructure.md +51 -0
- package/.agent/skills/lead-architect/references/process.md +42 -0
- package/.agent/skills/lead-architect/references/system-architecture.md +62 -0
- package/.agent/skills/lead-architect/references/web-fullstack.md +82 -0
- package/.agent/skills/lead-architect/templates/adr.md +62 -0
- package/.agent/skills/lead-architect/templates/rfc.md +46 -0
- package/.agent/skills/lead-architect/templates/sdd.md +62 -0
- package/.agent/skills/lead-architect/templates/technical-spec.md +61 -0
- package/.agent/skills/marketer/SKILL.md +66 -0
- package/.agent/skills/marketer/remotion-best-practices/SKILL.md +58 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/3d.md +86 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/animations.md +29 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/assets.md +78 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/audio.md +172 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/calculate-metadata.md +104 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/can-decode.md +75 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/charts.md +58 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/compositions.md +146 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/display-captions.md +126 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/extract-frames.md +229 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/fonts.md +152 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/get-video-duration.md +58 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/gifs.md +138 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/images.md +130 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/import-srt-captions.md +67 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/lottie.md +68 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/measuring-text.md +143 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/sequencing.md +106 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/tailwind.md +11 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/text-animations.md +20 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/timing.md +179 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/transcribe-captions.md +19 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/transitions.md +122 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/trimming.md +53 -0
- package/.agent/skills/marketer/remotion-best-practices/rules/videos.md +171 -0
- package/.agent/skills/mcp-builder/SKILL.md +76 -0
- package/.agent/skills/mcp-builder/references/evaluation.md +602 -0
- package/.agent/skills/mcp-builder/references/mcp_best_practices.md +249 -0
- package/.agent/skills/mcp-builder/references/node_mcp_server.md +970 -0
- package/.agent/skills/mcp-builder/references/python_mcp_server.md +719 -0
- package/.agent/skills/mobile-developer/SKILL.md +83 -0
- package/.agent/skills/mobile-developer/api-routes/SKILL.md +389 -0
- package/.agent/skills/mobile-developer/building-ui/SKILL.md +335 -0
- package/.agent/skills/mobile-developer/building-ui/references/animations.md +220 -0
- package/.agent/skills/mobile-developer/building-ui/references/controls.md +270 -0
- package/.agent/skills/mobile-developer/building-ui/references/form-sheet.md +227 -0
- package/.agent/skills/mobile-developer/building-ui/references/gradients.md +106 -0
- package/.agent/skills/mobile-developer/building-ui/references/icons.md +213 -0
- package/.agent/skills/mobile-developer/building-ui/references/media.md +198 -0
- package/.agent/skills/mobile-developer/building-ui/references/route-structure.md +229 -0
- package/.agent/skills/mobile-developer/building-ui/references/search.md +248 -0
- package/.agent/skills/mobile-developer/building-ui/references/storage.md +121 -0
- package/.agent/skills/mobile-developer/building-ui/references/tabs.md +368 -0
- package/.agent/skills/mobile-developer/building-ui/references/visual-effects.md +197 -0
- package/.agent/skills/mobile-developer/building-ui/references/webgpu-three.md +605 -0
- package/.agent/skills/mobile-developer/cicd-workflows/SKILL.md +107 -0
- package/.agent/skills/mobile-developer/cicd-workflows/scripts/fetch.js +109 -0
- package/.agent/skills/mobile-developer/cicd-workflows/scripts/package.json +11 -0
- package/.agent/skills/mobile-developer/cicd-workflows/scripts/validate.js +84 -0
- package/.agent/skills/mobile-developer/data-fetching/SKILL.md +508 -0
- package/.agent/skills/mobile-developer/deployment/SKILL.md +207 -0
- package/.agent/skills/mobile-developer/deployment/references/app-store-metadata.md +479 -0
- package/.agent/skills/mobile-developer/deployment/references/ios-app-store.md +355 -0
- package/.agent/skills/mobile-developer/deployment/references/play-store.md +246 -0
- package/.agent/skills/mobile-developer/deployment/references/testflight.md +58 -0
- package/.agent/skills/mobile-developer/deployment/references/workflows.md +200 -0
- package/.agent/skills/mobile-developer/dev-client/SKILL.md +181 -0
- package/.agent/skills/mobile-developer/tailwind-setup/SKILL.md +501 -0
- package/.agent/skills/mobile-developer/upgrading-expo/SKILL.md +116 -0
- package/.agent/skills/mobile-developer/upgrading-expo/references/new-architecture.md +79 -0
- package/.agent/skills/mobile-developer/upgrading-expo/references/react-19.md +79 -0
- package/.agent/skills/mobile-developer/upgrading-expo/references/react-compiler.md +59 -0
- package/.agent/skills/mobile-developer/use-dom/SKILL.md +434 -0
- package/.agent/skills/modern-python/SKILL.md +122 -0
- package/.agent/skills/project-manager/SKILL.md +110 -0
- package/.agent/skills/project-manager/references/ba-collaboration.md +62 -0
- package/.agent/skills/project-manager/references/discovery_process.md +52 -0
- package/.agent/skills/project-manager/references/jobs_to_be_done.md +51 -0
- package/.agent/skills/project-manager/references/prd_development.md +52 -0
- package/.agent/skills/project-manager/references/rules-guide.md +55 -0
- package/.agent/skills/project-manager/references/skill-creation.md +98 -0
- package/.agent/skills/project-manager/references/strategic-frameworks.md +62 -0
- package/.agent/skills/project-manager/references/task-decomposition.md +194 -0
- package/.agent/skills/project-manager/references/workflows-guide.md +44 -0
- package/.agent/skills/project-manager/router.json +160 -0
- package/.agent/skills/project-manager/scripts/compare_skill.py +177 -0
- package/.agent/skills/project-manager/scripts/encoding_utils.py +36 -0
- package/.agent/skills/project-manager/scripts/init_skill.py +190 -0
- package/.agent/skills/project-manager/scripts/quick_validate.py +123 -0
- package/.agent/skills/project-manager/templates/pm-strategy-one-pager.md +6 -0
- package/.agent/skills/project-manager/templates/prd-strategic.md +38 -0
- package/.agent/skills/project-manager/templates/skill-questionnaire.md +118 -0
- package/.agent/skills/project-manager/templates/user-story-simple.md +14 -0
- package/.agent/skills/prompt-engineer/SKILL.md +319 -0
- package/.agent/skills/prompt-engineer/skill-creator/README.md +47 -0
- package/.agent/skills/qa-tester/SKILL.md +142 -0
- package/.agent/skills/qa-tester/assets/README.md +8 -0
- package/.agent/skills/qa-tester/references/accessibility_testing.md +35 -0
- package/.agent/skills/qa-tester/references/agent_browser.md +38 -0
- package/.agent/skills/qa-tester/references/automation/api_testing.md +23 -0
- package/.agent/skills/qa-tester/references/automation/best_practices.md +14 -0
- package/.agent/skills/qa-tester/references/automation/jest_vitest.md +26 -0
- package/.agent/skills/qa-tester/references/automation/playwright.md +30 -0
- package/.agent/skills/qa-tester/references/e2e_testing.md +46 -0
- package/.agent/skills/qa-tester/references/integration_testing.md +39 -0
- package/.agent/skills/qa-tester/references/performance_testing.md +44 -0
- package/.agent/skills/qa-tester/references/property_based_testing.md +44 -0
- package/.agent/skills/qa-tester/references/security_audit.md +53 -0
- package/.agent/skills/qa-tester/references/security_testing.md +30 -0
- package/.agent/skills/qa-tester/references/sharp_edges.md +49 -0
- package/.agent/skills/qa-tester/references/static_analysis.md +52 -0
- package/.agent/skills/qa-tester/references/supply_chain_audit.md +54 -0
- package/.agent/skills/qa-tester/references/test_case_standards.md +96 -0
- package/.agent/skills/qa-tester/references/test_report_template.md +32 -0
- package/.agent/skills/qa-tester/references/unit_testing.md +50 -0
- package/.agent/skills/qa-tester/references/visual_testing.md +32 -0
- package/.agent/skills/qa-tester/templates/uat-plan.md +34 -0
- package/.agent/skills/research-first/SKILL.md +118 -0
- package/.agent/skills-manifest.json +264 -0
- package/.agent/workflows/absorb.md +176 -0
- package/.agent/workflows/bootstrap.md +91 -0
- package/.agent/workflows/brainstorm.md +168 -0
- package/.agent/workflows/break-tasks.md +77 -0
- package/.agent/workflows/commit.md +349 -0
- package/.agent/workflows/custom-behavior.md +64 -0
- package/.agent/workflows/debug.md +65 -0
- package/.agent/workflows/development.md +49 -0
- package/.agent/workflows/documentation.md +221 -0
- package/.agent/workflows/gen-tests.md +53 -0
- package/.agent/workflows/guide.md +196 -0
- package/.agent/workflows/implement-feature.md +182 -0
- package/.agent/workflows/install-skill.md +193 -0
- package/.agent/workflows/qa.md +54 -0
- package/.agent/workflows/ui-ux-design.md +108 -0
- package/LICENSE +21 -0
- package/README.md +258 -0
- package/cli/index.js +345 -0
- package/cli/migrate-skills.js +113 -0
- package/cli/verify.js +291 -0
- package/package.json +49 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Icons (SF Symbols)
|
|
2
|
+
|
|
3
|
+
Use SF Symbols for native feel. Never use FontAwesome or Ionicons.
|
|
4
|
+
|
|
5
|
+
## Basic Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { SymbolView } from "expo-symbols";
|
|
9
|
+
import { PlatformColor } from "react-native";
|
|
10
|
+
|
|
11
|
+
<SymbolView
|
|
12
|
+
tintColor={PlatformColor("label")}
|
|
13
|
+
resizeMode="scaleAspectFit"
|
|
14
|
+
name="square.and.arrow.down"
|
|
15
|
+
style={{ width: 16, height: 16 }}
|
|
16
|
+
/>;
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
<SymbolView
|
|
23
|
+
name="star.fill" // SF Symbol name (required)
|
|
24
|
+
tintColor={PlatformColor("label")} // Icon color
|
|
25
|
+
size={24} // Shorthand for width/height
|
|
26
|
+
resizeMode="scaleAspectFit" // How to scale
|
|
27
|
+
weight="regular" // thin | ultraLight | light | regular | medium | semibold | bold | heavy | black
|
|
28
|
+
scale="medium" // small | medium | large
|
|
29
|
+
style={{ width: 16, height: 16 }} // Standard style props
|
|
30
|
+
/>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Common Icons
|
|
34
|
+
|
|
35
|
+
### Navigation & Actions
|
|
36
|
+
- `house.fill` - home
|
|
37
|
+
- `gear` - settings
|
|
38
|
+
- `magnifyingglass` - search
|
|
39
|
+
- `plus` - add
|
|
40
|
+
- `xmark` - close
|
|
41
|
+
- `chevron.left` - back
|
|
42
|
+
- `chevron.right` - forward
|
|
43
|
+
- `arrow.left` - back arrow
|
|
44
|
+
- `arrow.right` - forward arrow
|
|
45
|
+
|
|
46
|
+
### Media
|
|
47
|
+
- `play.fill` - play
|
|
48
|
+
- `pause.fill` - pause
|
|
49
|
+
- `stop.fill` - stop
|
|
50
|
+
- `backward.fill` - rewind
|
|
51
|
+
- `forward.fill` - fast forward
|
|
52
|
+
- `speaker.wave.2.fill` - volume
|
|
53
|
+
- `speaker.slash.fill` - mute
|
|
54
|
+
|
|
55
|
+
### Camera
|
|
56
|
+
- `camera` - camera
|
|
57
|
+
- `camera.fill` - camera filled
|
|
58
|
+
- `arrow.triangle.2.circlepath` - flip camera
|
|
59
|
+
- `photo` - gallery/photos
|
|
60
|
+
- `bolt` - flash
|
|
61
|
+
- `bolt.slash` - flash off
|
|
62
|
+
|
|
63
|
+
### Communication
|
|
64
|
+
- `message` - message
|
|
65
|
+
- `message.fill` - message filled
|
|
66
|
+
- `envelope` - email
|
|
67
|
+
- `envelope.fill` - email filled
|
|
68
|
+
- `phone` - phone
|
|
69
|
+
- `phone.fill` - phone filled
|
|
70
|
+
- `video` - video call
|
|
71
|
+
- `video.fill` - video call filled
|
|
72
|
+
|
|
73
|
+
### Social
|
|
74
|
+
- `heart` - like
|
|
75
|
+
- `heart.fill` - liked
|
|
76
|
+
- `star` - favorite
|
|
77
|
+
- `star.fill` - favorited
|
|
78
|
+
- `hand.thumbsup` - thumbs up
|
|
79
|
+
- `hand.thumbsdown` - thumbs down
|
|
80
|
+
- `person` - profile
|
|
81
|
+
- `person.fill` - profile filled
|
|
82
|
+
- `person.2` - people
|
|
83
|
+
- `person.2.fill` - people filled
|
|
84
|
+
|
|
85
|
+
### Content Actions
|
|
86
|
+
- `square.and.arrow.up` - share
|
|
87
|
+
- `square.and.arrow.down` - download
|
|
88
|
+
- `doc.on.doc` - copy
|
|
89
|
+
- `trash` - delete
|
|
90
|
+
- `pencil` - edit
|
|
91
|
+
- `folder` - folder
|
|
92
|
+
- `folder.fill` - folder filled
|
|
93
|
+
- `bookmark` - bookmark
|
|
94
|
+
- `bookmark.fill` - bookmarked
|
|
95
|
+
|
|
96
|
+
### Status & Feedback
|
|
97
|
+
- `checkmark` - success/done
|
|
98
|
+
- `checkmark.circle.fill` - completed
|
|
99
|
+
- `xmark.circle.fill` - error/failed
|
|
100
|
+
- `exclamationmark.triangle` - warning
|
|
101
|
+
- `info.circle` - info
|
|
102
|
+
- `questionmark.circle` - help
|
|
103
|
+
- `bell` - notification
|
|
104
|
+
- `bell.fill` - notification filled
|
|
105
|
+
|
|
106
|
+
### Misc
|
|
107
|
+
- `ellipsis` - more options
|
|
108
|
+
- `ellipsis.circle` - more in circle
|
|
109
|
+
- `line.3.horizontal` - menu/hamburger
|
|
110
|
+
- `slider.horizontal.3` - filters
|
|
111
|
+
- `arrow.clockwise` - refresh
|
|
112
|
+
- `location` - location
|
|
113
|
+
- `location.fill` - location filled
|
|
114
|
+
- `map` - map
|
|
115
|
+
- `mappin` - pin
|
|
116
|
+
- `clock` - time
|
|
117
|
+
- `calendar` - calendar
|
|
118
|
+
- `link` - link
|
|
119
|
+
- `nosign` - block/prohibited
|
|
120
|
+
|
|
121
|
+
## Animated Symbols
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
<SymbolView
|
|
125
|
+
name="checkmark.circle"
|
|
126
|
+
animationSpec={{
|
|
127
|
+
effect: {
|
|
128
|
+
type: "bounce",
|
|
129
|
+
direction: "up",
|
|
130
|
+
},
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Animation Effects
|
|
136
|
+
|
|
137
|
+
- `bounce` - Bouncy animation
|
|
138
|
+
- `pulse` - Pulsing effect
|
|
139
|
+
- `variableColor` - Color cycling
|
|
140
|
+
- `scale` - Scale animation
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
// Bounce with direction
|
|
144
|
+
animationSpec={{
|
|
145
|
+
effect: { type: "bounce", direction: "up" } // up | down
|
|
146
|
+
}}
|
|
147
|
+
|
|
148
|
+
// Pulse
|
|
149
|
+
animationSpec={{
|
|
150
|
+
effect: { type: "pulse" }
|
|
151
|
+
}}
|
|
152
|
+
|
|
153
|
+
// Variable color (multicolor symbols)
|
|
154
|
+
animationSpec={{
|
|
155
|
+
effect: {
|
|
156
|
+
type: "variableColor",
|
|
157
|
+
cumulative: true,
|
|
158
|
+
reversing: true
|
|
159
|
+
}
|
|
160
|
+
}}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Symbol Weights
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
// Lighter weights
|
|
167
|
+
<SymbolView name="star" weight="ultraLight" />
|
|
168
|
+
<SymbolView name="star" weight="thin" />
|
|
169
|
+
<SymbolView name="star" weight="light" />
|
|
170
|
+
|
|
171
|
+
// Default
|
|
172
|
+
<SymbolView name="star" weight="regular" />
|
|
173
|
+
|
|
174
|
+
// Heavier weights
|
|
175
|
+
<SymbolView name="star" weight="medium" />
|
|
176
|
+
<SymbolView name="star" weight="semibold" />
|
|
177
|
+
<SymbolView name="star" weight="bold" />
|
|
178
|
+
<SymbolView name="star" weight="heavy" />
|
|
179
|
+
<SymbolView name="star" weight="black" />
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Symbol Scales
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
<SymbolView name="star" scale="small" />
|
|
186
|
+
<SymbolView name="star" scale="medium" /> // default
|
|
187
|
+
<SymbolView name="star" scale="large" />
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Multicolor Symbols
|
|
191
|
+
|
|
192
|
+
Some symbols support multiple colors:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<SymbolView
|
|
196
|
+
name="cloud.sun.rain.fill"
|
|
197
|
+
type="multicolor"
|
|
198
|
+
/>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Finding Symbol Names
|
|
202
|
+
|
|
203
|
+
1. Use the SF Symbols app on macOS (free from Apple)
|
|
204
|
+
2. Search at https://developer.apple.com/sf-symbols/
|
|
205
|
+
3. Symbol names use dot notation: `square.and.arrow.up`
|
|
206
|
+
|
|
207
|
+
## Best Practices
|
|
208
|
+
|
|
209
|
+
- Always use SF Symbols over vector icon libraries
|
|
210
|
+
- Match symbol weight to nearby text weight
|
|
211
|
+
- Use `.fill` variants for selected/active states
|
|
212
|
+
- Use PlatformColor for tint to support dark mode
|
|
213
|
+
- Keep icons at consistent sizes (16, 20, 24, 32)
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Media
|
|
2
|
+
|
|
3
|
+
## Camera
|
|
4
|
+
|
|
5
|
+
- Hide navigation headers when there's a full screen camera
|
|
6
|
+
- Ensure to flip the camera with `mirror` to emulate social apps
|
|
7
|
+
- Use liquid glass buttons on cameras
|
|
8
|
+
- Icons: `arrow.triangle.2.circlepath` (flip), `photo` (gallery), `bolt` (flash)
|
|
9
|
+
- Eagerly request camera permission
|
|
10
|
+
- Lazily request media library permission
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
import React, { useRef, useState } from "react";
|
|
14
|
+
import { View, TouchableOpacity, Text, Alert } from "react-native";
|
|
15
|
+
import { CameraView, CameraType, useCameraPermissions } from "expo-camera";
|
|
16
|
+
import * as MediaLibrary from "expo-media-library";
|
|
17
|
+
import * as ImagePicker from "expo-image-picker";
|
|
18
|
+
import * as Haptics from "expo-haptics";
|
|
19
|
+
import { SymbolView } from "expo-symbols";
|
|
20
|
+
import { PlatformColor } from "react-native";
|
|
21
|
+
import { GlassView } from "expo-glass-effect";
|
|
22
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
23
|
+
|
|
24
|
+
function Camera({ onPicture }: { onPicture: (uri: string) => Promise<void> }) {
|
|
25
|
+
const [permission, requestPermission] = useCameraPermissions();
|
|
26
|
+
const cameraRef = useRef<CameraView>(null);
|
|
27
|
+
const [type, setType] = useState<CameraType>("back");
|
|
28
|
+
const { bottom } = useSafeAreaInsets();
|
|
29
|
+
|
|
30
|
+
if (!permission?.granted) {
|
|
31
|
+
return (
|
|
32
|
+
<View style={{ flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: PlatformColor("systemBackground") }}>
|
|
33
|
+
<Text style={{ color: PlatformColor("label"), padding: 16 }}>Camera access is required</Text>
|
|
34
|
+
<GlassView isInteractive tintColor={PlatformColor("systemBlue")} style={{ borderRadius: 12 }}>
|
|
35
|
+
<TouchableOpacity onPress={requestPermission} style={{ padding: 12, borderRadius: 12 }}>
|
|
36
|
+
<Text style={{ color: "white" }}>Grant Permission</Text>
|
|
37
|
+
</TouchableOpacity>
|
|
38
|
+
</GlassView>
|
|
39
|
+
</View>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const takePhoto = async () => {
|
|
44
|
+
await Haptics.selectionAsync();
|
|
45
|
+
if (!cameraRef.current) return;
|
|
46
|
+
const photo = await cameraRef.current.takePictureAsync({ quality: 0.8 });
|
|
47
|
+
await onPicture(photo.uri);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const selectPhoto = async () => {
|
|
51
|
+
await Haptics.selectionAsync();
|
|
52
|
+
const result = await ImagePicker.launchImageLibraryAsync({
|
|
53
|
+
mediaTypes: "images",
|
|
54
|
+
allowsEditing: false,
|
|
55
|
+
quality: 0.8,
|
|
56
|
+
});
|
|
57
|
+
if (!result.canceled && result.assets?.[0]) {
|
|
58
|
+
await onPicture(result.assets[0].uri);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<View style={{ flex: 1, backgroundColor: "black" }}>
|
|
64
|
+
<CameraView ref={cameraRef} mirror style={{ flex: 1 }} facing={type} />
|
|
65
|
+
<View style={{ position: "absolute", left: 0, right: 0, bottom: bottom, gap: 16, alignItems: "center" }}>
|
|
66
|
+
<GlassView isInteractive style={{ padding: 8, borderRadius: 99 }}>
|
|
67
|
+
<TouchableOpacity onPress={takePhoto} style={{ width: 64, height: 64, borderRadius: 99, backgroundColor: "white" }} />
|
|
68
|
+
</GlassView>
|
|
69
|
+
<View style={{ flexDirection: "row", justifyContent: "space-around", paddingHorizontal: 8 }}>
|
|
70
|
+
<GlassButton onPress={selectPhoto} icon="photo" />
|
|
71
|
+
<GlassButton onPress={() => setType(t => t === "back" ? "front" : "back")} icon="arrow.triangle.2.circlepath" />
|
|
72
|
+
</View>
|
|
73
|
+
</View>
|
|
74
|
+
</View>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Audio Playback
|
|
80
|
+
|
|
81
|
+
Use `expo-audio` not `expo-av`:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { useAudioPlayer } from 'expo-audio';
|
|
85
|
+
|
|
86
|
+
const player = useAudioPlayer({ uri: 'https://stream.nightride.fm/rektory.mp3' });
|
|
87
|
+
|
|
88
|
+
<Button title="Play" onPress={() => player.play()} />
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Audio Recording (Microphone)
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import {
|
|
95
|
+
useAudioRecorder,
|
|
96
|
+
AudioModule,
|
|
97
|
+
RecordingPresets,
|
|
98
|
+
setAudioModeAsync,
|
|
99
|
+
useAudioRecorderState,
|
|
100
|
+
} from 'expo-audio';
|
|
101
|
+
import { useEffect } from 'react';
|
|
102
|
+
import { Alert, Button } from 'react-native';
|
|
103
|
+
|
|
104
|
+
function App() {
|
|
105
|
+
const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
|
|
106
|
+
const recorderState = useAudioRecorderState(audioRecorder);
|
|
107
|
+
|
|
108
|
+
const record = async () => {
|
|
109
|
+
await audioRecorder.prepareToRecordAsync();
|
|
110
|
+
audioRecorder.record();
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const stop = () => audioRecorder.stop();
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
(async () => {
|
|
117
|
+
const status = await AudioModule.requestRecordingPermissionsAsync();
|
|
118
|
+
if (status.granted) {
|
|
119
|
+
setAudioModeAsync({ playsInSilentMode: true, allowsRecording: true });
|
|
120
|
+
} else {
|
|
121
|
+
Alert.alert('Permission to access microphone was denied');
|
|
122
|
+
}
|
|
123
|
+
})();
|
|
124
|
+
}, []);
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Button
|
|
128
|
+
title={recorderState.isRecording ? 'Stop' : 'Start'}
|
|
129
|
+
onPress={recorderState.isRecording ? stop : record}
|
|
130
|
+
/>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Video Playback
|
|
136
|
+
|
|
137
|
+
Use `expo-video` not `expo-av`:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
141
|
+
import { useEvent } from 'expo';
|
|
142
|
+
|
|
143
|
+
const videoSource = 'https://example.com/video.mp4';
|
|
144
|
+
|
|
145
|
+
const player = useVideoPlayer(videoSource, player => {
|
|
146
|
+
player.loop = true;
|
|
147
|
+
player.play();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const { isPlaying } = useEvent(player, 'playingChange', { isPlaying: player.playing });
|
|
151
|
+
|
|
152
|
+
<VideoView player={player} fullscreenOptions={{}} allowsPictureInPicture />
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
VideoView options:
|
|
156
|
+
- `allowsPictureInPicture`: boolean
|
|
157
|
+
- `contentFit`: 'contain' | 'cover' | 'fill'
|
|
158
|
+
- `nativeControls`: boolean
|
|
159
|
+
- `playsInline`: boolean
|
|
160
|
+
- `startsPictureInPictureAutomatically`: boolean
|
|
161
|
+
|
|
162
|
+
## Saving Media
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import * as MediaLibrary from "expo-media-library";
|
|
166
|
+
|
|
167
|
+
const { granted } = await MediaLibrary.requestPermissionsAsync();
|
|
168
|
+
if (granted) {
|
|
169
|
+
await MediaLibrary.saveToLibraryAsync(uri);
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Saving Base64 Images
|
|
174
|
+
|
|
175
|
+
`MediaLibrary.saveToLibraryAsync` only accepts local file paths. Save base64 strings to disk first:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { File, Paths } from "expo-file-system/next";
|
|
179
|
+
|
|
180
|
+
function base64ToLocalUri(base64: string, filename?: string) {
|
|
181
|
+
if (!filename) {
|
|
182
|
+
const match = base64.match(/^data:(image\/[a-zA-Z]+);base64,/);
|
|
183
|
+
const ext = match ? match[1].split("/")[1] : "jpg";
|
|
184
|
+
filename = `generated-${Date.now()}.${ext}`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (base64.startsWith("data:")) base64 = base64.split(",")[1];
|
|
188
|
+
const binaryString = atob(base64);
|
|
189
|
+
const len = binaryString.length;
|
|
190
|
+
const bytes = new Uint8Array(new ArrayBuffer(len));
|
|
191
|
+
for (let i = 0; i < len; i++) bytes[i] = binaryString.charCodeAt(i);
|
|
192
|
+
|
|
193
|
+
const f = new File(Paths.cache, filename);
|
|
194
|
+
f.create({ overwrite: true });
|
|
195
|
+
f.write(bytes);
|
|
196
|
+
return f.uri;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Route Structure
|
|
2
|
+
|
|
3
|
+
## File Conventions
|
|
4
|
+
|
|
5
|
+
- Routes belong in the `app` directory
|
|
6
|
+
- Use `[]` for dynamic routes, e.g. `[id].tsx`
|
|
7
|
+
- Routes can never be named `(foo).tsx` - use `(foo)/index.tsx` instead
|
|
8
|
+
- Use `(group)` routes to simplify the public URL structure
|
|
9
|
+
- NEVER co-locate components, types, or utilities in the app directory - these should be in separate directories like `components/`, `utils/`, etc.
|
|
10
|
+
- The app directory should only contain route and `_layout` files; every file should export a default component
|
|
11
|
+
- Ensure the app always has a route that matches "/" so the app is never blank
|
|
12
|
+
- ALWAYS use `_layout.tsx` files to define stacks
|
|
13
|
+
|
|
14
|
+
## Dynamic Routes
|
|
15
|
+
|
|
16
|
+
Use square brackets for dynamic segments:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
app/
|
|
20
|
+
users/
|
|
21
|
+
[id].tsx # Matches /users/123, /users/abc
|
|
22
|
+
[id]/
|
|
23
|
+
posts.tsx # Matches /users/123/posts
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Catch-All Routes
|
|
27
|
+
|
|
28
|
+
Use `[...slug]` for catch-all routes:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
app/
|
|
32
|
+
docs/
|
|
33
|
+
[...slug].tsx # Matches /docs/a, /docs/a/b, /docs/a/b/c
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Query Parameters
|
|
37
|
+
|
|
38
|
+
Access query parameters with the `useLocalSearchParams` hook:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { useLocalSearchParams } from "expo-router";
|
|
42
|
+
|
|
43
|
+
function Page() {
|
|
44
|
+
const { id } = useLocalSearchParams<{ id: string }>();
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For dynamic routes, the parameter name matches the file name:
|
|
49
|
+
|
|
50
|
+
- `[id].tsx` → `useLocalSearchParams<{ id: string }>()`
|
|
51
|
+
- `[slug].tsx` → `useLocalSearchParams<{ slug: string }>()`
|
|
52
|
+
|
|
53
|
+
## Pathname
|
|
54
|
+
|
|
55
|
+
Access the current pathname with the `usePathname` hook:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { usePathname } from "expo-router";
|
|
59
|
+
|
|
60
|
+
function Component() {
|
|
61
|
+
const pathname = usePathname(); // e.g. "/users/123"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Group Routes
|
|
66
|
+
|
|
67
|
+
Use parentheses for groups that don't affect the URL:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
app/
|
|
71
|
+
(auth)/
|
|
72
|
+
login.tsx # URL: /login
|
|
73
|
+
register.tsx # URL: /register
|
|
74
|
+
(main)/
|
|
75
|
+
index.tsx # URL: /
|
|
76
|
+
settings.tsx # URL: /settings
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Groups are useful for:
|
|
80
|
+
|
|
81
|
+
- Organizing related routes
|
|
82
|
+
- Applying different layouts to route groups
|
|
83
|
+
- Keeping URLs clean
|
|
84
|
+
|
|
85
|
+
## Stacks and Tabs Structure
|
|
86
|
+
|
|
87
|
+
When an app has tabs, the header and title should be set in a Stack that is nested INSIDE each tab. This allows tabs to have their own headers and distinct histories. The root layout should often not have a header.
|
|
88
|
+
|
|
89
|
+
- Set the 'headerShown' option to false on the tab layout
|
|
90
|
+
- Use (group) routes to simplify the public URL structure
|
|
91
|
+
- You may need to delete or refactor existing routes to fit this structure
|
|
92
|
+
|
|
93
|
+
Example structure:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
app/
|
|
97
|
+
_layout.tsx — <Tabs />
|
|
98
|
+
(home)/
|
|
99
|
+
_layout.tsx — <Stack />
|
|
100
|
+
index.tsx — <ScrollView />
|
|
101
|
+
(settings)/
|
|
102
|
+
_layout.tsx — <Stack />
|
|
103
|
+
index.tsx — <ScrollView />
|
|
104
|
+
(home,settings)/
|
|
105
|
+
info.tsx — <ScrollView /> (shared across tabs)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Array Routes for Multiple Stacks
|
|
109
|
+
|
|
110
|
+
Use array routes '(index,settings)' to create multiple stacks. This is useful for tabs that need to share screens across stacks.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
app/
|
|
114
|
+
_layout.tsx — <Tabs />
|
|
115
|
+
(index,settings)/
|
|
116
|
+
_layout.tsx — <Stack />
|
|
117
|
+
index.tsx — <ScrollView />
|
|
118
|
+
settings.tsx — <ScrollView />
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
This requires a specialized layout with explicit anchor routes:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
// app/(index,settings)/_layout.tsx
|
|
125
|
+
import { useMemo } from "react";
|
|
126
|
+
import Stack from "expo-router/stack";
|
|
127
|
+
|
|
128
|
+
export const unstable_settings = {
|
|
129
|
+
index: { anchor: "index" },
|
|
130
|
+
settings: { anchor: "settings" },
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export default function Layout({ segment }: { segment: string }) {
|
|
134
|
+
const screen = segment.match(/\((.*)\)/)?.[1]!;
|
|
135
|
+
|
|
136
|
+
const options = useMemo(() => {
|
|
137
|
+
switch (screen) {
|
|
138
|
+
case "index":
|
|
139
|
+
return { headerRight: () => <></> };
|
|
140
|
+
default:
|
|
141
|
+
return {};
|
|
142
|
+
}
|
|
143
|
+
}, [screen]);
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<Stack>
|
|
147
|
+
<Stack.Screen name={screen} options={options} />
|
|
148
|
+
</Stack>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Complete App Structure Example
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
app/
|
|
157
|
+
_layout.tsx — <NativeTabs />
|
|
158
|
+
(index,search)/
|
|
159
|
+
_layout.tsx — <Stack />
|
|
160
|
+
index.tsx — Main list
|
|
161
|
+
search.tsx — Search view
|
|
162
|
+
i/[id].tsx — Detail page
|
|
163
|
+
components/
|
|
164
|
+
theme.tsx
|
|
165
|
+
list.tsx
|
|
166
|
+
utils/
|
|
167
|
+
storage.ts
|
|
168
|
+
use-search.ts
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Layout Files
|
|
172
|
+
|
|
173
|
+
Every directory can have a `_layout.tsx` file that wraps all routes in that directory:
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
// app/_layout.tsx
|
|
177
|
+
import { Stack } from "expo-router/stack";
|
|
178
|
+
|
|
179
|
+
export default function RootLayout() {
|
|
180
|
+
return <Stack />;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
// app/(tabs)/_layout.tsx
|
|
186
|
+
import { NativeTabs, Icon, Label } from "expo-router/unstable-native-tabs";
|
|
187
|
+
|
|
188
|
+
export default function TabLayout() {
|
|
189
|
+
return (
|
|
190
|
+
<NativeTabs>
|
|
191
|
+
<NativeTabs.Trigger name="index">
|
|
192
|
+
<Label>Home</Label>
|
|
193
|
+
<Icon sf="house.fill" />
|
|
194
|
+
</NativeTabs.Trigger>
|
|
195
|
+
</NativeTabs>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Route Settings
|
|
201
|
+
|
|
202
|
+
Export `unstable_settings` to configure route behavior:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
export const unstable_settings = {
|
|
206
|
+
anchor: "index",
|
|
207
|
+
};
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
- `initialRouteName` was renamed to `anchor` in v4
|
|
211
|
+
|
|
212
|
+
## Not Found Routes
|
|
213
|
+
|
|
214
|
+
Create a `+not-found.tsx` file to handle unmatched routes:
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
// app/+not-found.tsx
|
|
218
|
+
import { Link } from "expo-router";
|
|
219
|
+
import { View, Text } from "react-native";
|
|
220
|
+
|
|
221
|
+
export default function NotFound() {
|
|
222
|
+
return (
|
|
223
|
+
<View>
|
|
224
|
+
<Text>Page not found</Text>
|
|
225
|
+
<Link href="/">Go home</Link>
|
|
226
|
+
</View>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
```
|