cfsa-antigravity 1.0.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/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: expo-react-native
|
|
3
|
+
description: Comprehensive Expo and React Native skill covering project setup (Expo CLI, EAS), file-based routing (Expo Router), native modules, platform-specific code, navigation patterns, gestures, animations (Reanimated), asset management, OTA updates, app store builds (EAS Build), push notifications, and debugging. Use when building mobile applications with Expo or React Native.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Expo / React Native
|
|
8
|
+
|
|
9
|
+
Framework for building native mobile apps with React. Expo provides managed workflow tooling, file-based routing, OTA updates, and cloud build services.
|
|
10
|
+
|
|
11
|
+
## Project Setup
|
|
12
|
+
|
|
13
|
+
### Create New Project
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx create-expo-app@latest my-app --template tabs
|
|
17
|
+
cd my-app
|
|
18
|
+
npx expo start
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Key Dependencies
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Navigation (file-based routing)
|
|
25
|
+
npx expo install expo-router expo-linking expo-constants expo-status-bar
|
|
26
|
+
|
|
27
|
+
# Common native modules
|
|
28
|
+
npx expo install expo-camera expo-image-picker expo-location expo-file-system
|
|
29
|
+
npx expo install expo-secure-store expo-haptics expo-clipboard
|
|
30
|
+
|
|
31
|
+
# Animations
|
|
32
|
+
npx expo install react-native-reanimated react-native-gesture-handler
|
|
33
|
+
|
|
34
|
+
# Safe area handling
|
|
35
|
+
npx expo install react-native-safe-area-context react-native-screens
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### app.json / app.config.ts
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// app.config.ts
|
|
42
|
+
import { ExpoConfig, ConfigContext } from 'expo/config';
|
|
43
|
+
|
|
44
|
+
export default ({ config }: ConfigContext): ExpoConfig => ({
|
|
45
|
+
...config,
|
|
46
|
+
name: 'My App',
|
|
47
|
+
slug: 'my-app',
|
|
48
|
+
version: '1.0.0',
|
|
49
|
+
orientation: 'portrait',
|
|
50
|
+
icon: './assets/icon.png',
|
|
51
|
+
scheme: 'myapp', // deep linking scheme
|
|
52
|
+
splash: {
|
|
53
|
+
image: './assets/splash.png',
|
|
54
|
+
resizeMode: 'contain',
|
|
55
|
+
backgroundColor: '#ffffff',
|
|
56
|
+
},
|
|
57
|
+
ios: {
|
|
58
|
+
supportsTablet: true,
|
|
59
|
+
bundleIdentifier: 'com.example.myapp',
|
|
60
|
+
infoPlist: {
|
|
61
|
+
NSCameraUsageDescription: 'This app uses the camera to take photos.',
|
|
62
|
+
NSPhotoLibraryUsageDescription: 'This app accesses your photos.',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
android: {
|
|
66
|
+
adaptiveIcon: {
|
|
67
|
+
foregroundImage: './assets/adaptive-icon.png',
|
|
68
|
+
backgroundColor: '#ffffff',
|
|
69
|
+
},
|
|
70
|
+
package: 'com.example.myapp',
|
|
71
|
+
permissions: ['CAMERA', 'READ_EXTERNAL_STORAGE'],
|
|
72
|
+
},
|
|
73
|
+
plugins: [
|
|
74
|
+
'expo-router',
|
|
75
|
+
['expo-camera', { cameraPermission: 'Allow camera access for photos.' }],
|
|
76
|
+
'expo-secure-store',
|
|
77
|
+
],
|
|
78
|
+
extra: {
|
|
79
|
+
eas: { projectId: 'your-eas-project-id' },
|
|
80
|
+
apiUrl: process.env.API_URL,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Expo Router (File-Based Routing)
|
|
86
|
+
|
|
87
|
+
### Directory Structure
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
app/
|
|
91
|
+
_layout.tsx # Root layout
|
|
92
|
+
index.tsx # / (home screen)
|
|
93
|
+
(tabs)/ # Tab group
|
|
94
|
+
_layout.tsx # Tab layout
|
|
95
|
+
index.tsx # First tab
|
|
96
|
+
explore.tsx # Second tab
|
|
97
|
+
profile.tsx # Third tab
|
|
98
|
+
(auth)/ # Auth group
|
|
99
|
+
_layout.tsx # Auth layout (no tabs)
|
|
100
|
+
sign-in.tsx
|
|
101
|
+
sign-up.tsx
|
|
102
|
+
settings/
|
|
103
|
+
_layout.tsx # Stack layout for settings
|
|
104
|
+
index.tsx # /settings
|
|
105
|
+
notifications.tsx # /settings/notifications
|
|
106
|
+
post/
|
|
107
|
+
[id].tsx # /post/123 (dynamic route)
|
|
108
|
+
[...missing].tsx # Catch-all 404
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Root Layout
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// app/_layout.tsx
|
|
115
|
+
import { Stack } from 'expo-router';
|
|
116
|
+
import { ThemeProvider, DarkTheme, DefaultTheme } from '@react-navigation/native';
|
|
117
|
+
import { useColorScheme } from 'react-native';
|
|
118
|
+
import { useFonts } from 'expo-font';
|
|
119
|
+
import * as SplashScreen from 'expo-splash-screen';
|
|
120
|
+
import { useEffect } from 'react';
|
|
121
|
+
|
|
122
|
+
SplashScreen.preventAutoHideAsync();
|
|
123
|
+
|
|
124
|
+
export default function RootLayout() {
|
|
125
|
+
const colorScheme = useColorScheme();
|
|
126
|
+
const [fontsLoaded] = useFonts({
|
|
127
|
+
'Inter-Regular': require('../assets/fonts/Inter-Regular.ttf'),
|
|
128
|
+
'Inter-Bold': require('../assets/fonts/Inter-Bold.ttf'),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (fontsLoaded) {
|
|
133
|
+
SplashScreen.hideAsync();
|
|
134
|
+
}
|
|
135
|
+
}, [fontsLoaded]);
|
|
136
|
+
|
|
137
|
+
if (!fontsLoaded) return null;
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
|
141
|
+
<Stack>
|
|
142
|
+
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
143
|
+
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
|
|
144
|
+
<Stack.Screen name="settings" options={{ title: 'Settings' }} />
|
|
145
|
+
<Stack.Screen name="post/[id]" options={{ title: 'Post' }} />
|
|
146
|
+
</Stack>
|
|
147
|
+
</ThemeProvider>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Tab Layout
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// app/(tabs)/_layout.tsx
|
|
156
|
+
import { Tabs } from 'expo-router';
|
|
157
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
158
|
+
import { useColorScheme } from 'react-native';
|
|
159
|
+
|
|
160
|
+
export default function TabLayout() {
|
|
161
|
+
const colorScheme = useColorScheme();
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<Tabs
|
|
165
|
+
screenOptions={{
|
|
166
|
+
tabBarActiveTintColor: colorScheme === 'dark' ? '#fff' : '#007AFF',
|
|
167
|
+
tabBarStyle: {
|
|
168
|
+
backgroundColor: colorScheme === 'dark' ? '#1c1c1e' : '#ffffff',
|
|
169
|
+
},
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<Tabs.Screen
|
|
173
|
+
name="index"
|
|
174
|
+
options={{
|
|
175
|
+
title: 'Home',
|
|
176
|
+
tabBarIcon: ({ color, size }) => (
|
|
177
|
+
<Ionicons name="home" color={color} size={size} />
|
|
178
|
+
),
|
|
179
|
+
}}
|
|
180
|
+
/>
|
|
181
|
+
<Tabs.Screen
|
|
182
|
+
name="explore"
|
|
183
|
+
options={{
|
|
184
|
+
title: 'Explore',
|
|
185
|
+
tabBarIcon: ({ color, size }) => (
|
|
186
|
+
<Ionicons name="search" color={color} size={size} />
|
|
187
|
+
),
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
<Tabs.Screen
|
|
191
|
+
name="profile"
|
|
192
|
+
options={{
|
|
193
|
+
title: 'Profile',
|
|
194
|
+
tabBarIcon: ({ color, size }) => (
|
|
195
|
+
<Ionicons name="person" color={color} size={size} />
|
|
196
|
+
),
|
|
197
|
+
}}
|
|
198
|
+
/>
|
|
199
|
+
</Tabs>
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Navigation
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { Link, useRouter, useLocalSearchParams, useGlobalSearchParams, Redirect } from 'expo-router';
|
|
208
|
+
import { Pressable, Text } from 'react-native';
|
|
209
|
+
|
|
210
|
+
function HomeScreen() {
|
|
211
|
+
const router = useRouter();
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<>
|
|
215
|
+
{/* Declarative link */}
|
|
216
|
+
<Link href="/settings" asChild>
|
|
217
|
+
<Pressable>
|
|
218
|
+
<Text>Go to Settings</Text>
|
|
219
|
+
</Pressable>
|
|
220
|
+
</Link>
|
|
221
|
+
|
|
222
|
+
{/* Programmatic navigation */}
|
|
223
|
+
<Pressable onPress={() => router.push('/post/123')}>
|
|
224
|
+
<Text>View Post</Text>
|
|
225
|
+
</Pressable>
|
|
226
|
+
|
|
227
|
+
{/* Replace current screen (no back) */}
|
|
228
|
+
<Pressable onPress={() => router.replace('/(tabs)')}>
|
|
229
|
+
<Text>Go Home</Text>
|
|
230
|
+
</Pressable>
|
|
231
|
+
|
|
232
|
+
{/* Go back */}
|
|
233
|
+
<Pressable onPress={() => router.back()}>
|
|
234
|
+
<Text>Go Back</Text>
|
|
235
|
+
</Pressable>
|
|
236
|
+
|
|
237
|
+
{/* Navigate with params */}
|
|
238
|
+
<Pressable onPress={() => router.push({ pathname: '/post/[id]', params: { id: '456' } })}>
|
|
239
|
+
<Text>View Post 456</Text>
|
|
240
|
+
</Pressable>
|
|
241
|
+
</>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Dynamic route page
|
|
246
|
+
function PostScreen() {
|
|
247
|
+
const { id } = useLocalSearchParams<{ id: string }>();
|
|
248
|
+
return <Text>Post ID: {id}</Text>;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Conditional redirect
|
|
252
|
+
function ProtectedScreen() {
|
|
253
|
+
const { isAuthenticated } = useAuth();
|
|
254
|
+
if (!isAuthenticated) {
|
|
255
|
+
return <Redirect href="/(auth)/sign-in" />;
|
|
256
|
+
}
|
|
257
|
+
return <Text>Protected Content</Text>;
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Platform-Specific Code
|
|
262
|
+
|
|
263
|
+
### Platform Module
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
import { Platform, StyleSheet } from 'react-native';
|
|
267
|
+
|
|
268
|
+
const styles = StyleSheet.create({
|
|
269
|
+
container: {
|
|
270
|
+
paddingTop: Platform.OS === 'ios' ? 44 : 0,
|
|
271
|
+
...Platform.select({
|
|
272
|
+
ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1 },
|
|
273
|
+
android: { elevation: 4 },
|
|
274
|
+
web: { boxShadow: '0 2px 4px rgba(0,0,0,0.1)' },
|
|
275
|
+
}),
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Platform-Specific Files
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
components/
|
|
284
|
+
Button.tsx # Shared
|
|
285
|
+
Button.ios.tsx # iOS override
|
|
286
|
+
Button.android.tsx # Android override
|
|
287
|
+
Button.web.tsx # Web override
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
React Native auto-resolves `import Button from './Button'` to the correct platform file.
|
|
291
|
+
|
|
292
|
+
## Animations (Reanimated)
|
|
293
|
+
|
|
294
|
+
### Basic Animation
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import Animated, {
|
|
298
|
+
useSharedValue,
|
|
299
|
+
useAnimatedStyle,
|
|
300
|
+
withSpring,
|
|
301
|
+
withTiming,
|
|
302
|
+
withRepeat,
|
|
303
|
+
withSequence,
|
|
304
|
+
Easing,
|
|
305
|
+
} from 'react-native-reanimated';
|
|
306
|
+
import { Pressable, View } from 'react-native';
|
|
307
|
+
|
|
308
|
+
function AnimatedBox() {
|
|
309
|
+
const scale = useSharedValue(1);
|
|
310
|
+
const rotation = useSharedValue(0);
|
|
311
|
+
|
|
312
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
313
|
+
transform: [
|
|
314
|
+
{ scale: scale.value },
|
|
315
|
+
{ rotateZ: `${rotation.value}deg` },
|
|
316
|
+
],
|
|
317
|
+
}));
|
|
318
|
+
|
|
319
|
+
function handlePress() {
|
|
320
|
+
scale.value = withSpring(1.5, { damping: 10, stiffness: 100 });
|
|
321
|
+
rotation.value = withTiming(360, { duration: 500, easing: Easing.bezier(0.25, 0.1, 0.25, 1) });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<Pressable onPress={handlePress}>
|
|
326
|
+
<Animated.View style={[{ width: 100, height: 100, backgroundColor: 'blue' }, animatedStyle]} />
|
|
327
|
+
</Pressable>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Layout Animations
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import Animated, { FadeIn, FadeOut, SlideInRight, Layout } from 'react-native-reanimated';
|
|
336
|
+
|
|
337
|
+
function AnimatedList({ items }: { items: Item[] }) {
|
|
338
|
+
return (
|
|
339
|
+
<View>
|
|
340
|
+
{items.map((item) => (
|
|
341
|
+
<Animated.View
|
|
342
|
+
key={item.id}
|
|
343
|
+
entering={FadeIn.duration(300)}
|
|
344
|
+
exiting={FadeOut.duration(200)}
|
|
345
|
+
layout={Layout.springify()}
|
|
346
|
+
>
|
|
347
|
+
<Text>{item.title}</Text>
|
|
348
|
+
</Animated.View>
|
|
349
|
+
))}
|
|
350
|
+
</View>
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Gestures
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
|
|
359
|
+
import Animated, {
|
|
360
|
+
useSharedValue,
|
|
361
|
+
useAnimatedStyle,
|
|
362
|
+
withSpring,
|
|
363
|
+
} from 'react-native-reanimated';
|
|
364
|
+
|
|
365
|
+
function DraggableCard() {
|
|
366
|
+
const translateX = useSharedValue(0);
|
|
367
|
+
const translateY = useSharedValue(0);
|
|
368
|
+
const scale = useSharedValue(1);
|
|
369
|
+
|
|
370
|
+
const panGesture = Gesture.Pan()
|
|
371
|
+
.onUpdate((event) => {
|
|
372
|
+
translateX.value = event.translationX;
|
|
373
|
+
translateY.value = event.translationY;
|
|
374
|
+
})
|
|
375
|
+
.onEnd(() => {
|
|
376
|
+
translateX.value = withSpring(0);
|
|
377
|
+
translateY.value = withSpring(0);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
const pinchGesture = Gesture.Pinch()
|
|
381
|
+
.onUpdate((event) => {
|
|
382
|
+
scale.value = event.scale;
|
|
383
|
+
})
|
|
384
|
+
.onEnd(() => {
|
|
385
|
+
scale.value = withSpring(1);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const composedGesture = Gesture.Simultaneous(panGesture, pinchGesture);
|
|
389
|
+
|
|
390
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
391
|
+
transform: [
|
|
392
|
+
{ translateX: translateX.value },
|
|
393
|
+
{ translateY: translateY.value },
|
|
394
|
+
{ scale: scale.value },
|
|
395
|
+
],
|
|
396
|
+
}));
|
|
397
|
+
|
|
398
|
+
return (
|
|
399
|
+
<GestureDetector gesture={composedGesture}>
|
|
400
|
+
<Animated.View style={[styles.card, animatedStyle]} />
|
|
401
|
+
</GestureDetector>
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Secure Storage
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import * as SecureStore from 'expo-secure-store';
|
|
410
|
+
|
|
411
|
+
// Store sensitive data (tokens, keys)
|
|
412
|
+
async function saveToken(key: string, value: string): Promise<void> {
|
|
413
|
+
await SecureStore.setItemAsync(key, value);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
async function getToken(key: string): Promise<string | null> {
|
|
417
|
+
return await SecureStore.getItemAsync(key);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async function deleteToken(key: string): Promise<void> {
|
|
421
|
+
await SecureStore.deleteItemAsync(key);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Usage
|
|
425
|
+
await saveToken('auth_token', 'eyJhbGciOiJIUzI1NiIs...');
|
|
426
|
+
const token = await getToken('auth_token');
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Push Notifications
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import * as Notifications from 'expo-notifications';
|
|
433
|
+
import * as Device from 'expo-device';
|
|
434
|
+
import { Platform } from 'react-native';
|
|
435
|
+
|
|
436
|
+
// Configure notification handler
|
|
437
|
+
Notifications.setNotificationHandler({
|
|
438
|
+
handleNotification: async () => ({
|
|
439
|
+
shouldShowAlert: true,
|
|
440
|
+
shouldPlaySound: true,
|
|
441
|
+
shouldSetBadge: true,
|
|
442
|
+
}),
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
async function registerForPushNotifications(): Promise<string | null> {
|
|
446
|
+
if (!Device.isDevice) {
|
|
447
|
+
console.warn('Push notifications require a physical device');
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
|
452
|
+
let finalStatus = existingStatus;
|
|
453
|
+
|
|
454
|
+
if (existingStatus !== 'granted') {
|
|
455
|
+
const { status } = await Notifications.requestPermissionsAsync();
|
|
456
|
+
finalStatus = status;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (finalStatus !== 'granted') {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Android requires a notification channel
|
|
464
|
+
if (Platform.OS === 'android') {
|
|
465
|
+
await Notifications.setNotificationChannelAsync('default', {
|
|
466
|
+
name: 'Default',
|
|
467
|
+
importance: Notifications.AndroidImportance.MAX,
|
|
468
|
+
vibrationPattern: [0, 250, 250, 250],
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const { data: token } = await Notifications.getExpoPushTokenAsync({
|
|
473
|
+
projectId: 'your-eas-project-id',
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
return token;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Listen for notifications
|
|
480
|
+
function useNotificationListeners() {
|
|
481
|
+
useEffect(() => {
|
|
482
|
+
// Notification received while app is foregrounded
|
|
483
|
+
const foregroundSub = Notifications.addNotificationReceivedListener((notification) => {
|
|
484
|
+
console.log('Received:', notification.request.content);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// User tapped on a notification
|
|
488
|
+
const responseSub = Notifications.addNotificationResponseReceivedListener((response) => {
|
|
489
|
+
const data = response.notification.request.content.data;
|
|
490
|
+
// Navigate based on notification data
|
|
491
|
+
router.push(data.url as string);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
return () => {
|
|
495
|
+
foregroundSub.remove();
|
|
496
|
+
responseSub.remove();
|
|
497
|
+
};
|
|
498
|
+
}, []);
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## EAS Build and Submit
|
|
503
|
+
|
|
504
|
+
### Configuration
|
|
505
|
+
|
|
506
|
+
```json
|
|
507
|
+
// eas.json
|
|
508
|
+
{
|
|
509
|
+
"cli": { "version": ">= 5.0.0" },
|
|
510
|
+
"build": {
|
|
511
|
+
"development": {
|
|
512
|
+
"developmentClient": true,
|
|
513
|
+
"distribution": "internal",
|
|
514
|
+
"ios": { "simulator": true },
|
|
515
|
+
"env": { "API_URL": "https://dev-api.example.com" }
|
|
516
|
+
},
|
|
517
|
+
"preview": {
|
|
518
|
+
"distribution": "internal",
|
|
519
|
+
"ios": { "simulator": false },
|
|
520
|
+
"env": { "API_URL": "https://staging-api.example.com" }
|
|
521
|
+
},
|
|
522
|
+
"production": {
|
|
523
|
+
"env": { "API_URL": "https://api.example.com" },
|
|
524
|
+
"autoIncrement": true
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
"submit": {
|
|
528
|
+
"production": {
|
|
529
|
+
"ios": {
|
|
530
|
+
"appleId": "your@email.com",
|
|
531
|
+
"ascAppId": "123456789",
|
|
532
|
+
"appleTeamId": "TEAM_ID"
|
|
533
|
+
},
|
|
534
|
+
"android": {
|
|
535
|
+
"serviceAccountKeyPath": "./google-services.json",
|
|
536
|
+
"track": "production"
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### CLI Commands
|
|
544
|
+
|
|
545
|
+
```bash
|
|
546
|
+
# Development build (includes dev tools)
|
|
547
|
+
eas build --profile development --platform ios
|
|
548
|
+
eas build --profile development --platform android
|
|
549
|
+
|
|
550
|
+
# Production build
|
|
551
|
+
eas build --profile production --platform all
|
|
552
|
+
|
|
553
|
+
# Submit to stores
|
|
554
|
+
eas submit --platform ios --latest
|
|
555
|
+
eas submit --platform android --latest
|
|
556
|
+
|
|
557
|
+
# OTA updates (no rebuild needed)
|
|
558
|
+
eas update --branch production --message "Fix login bug"
|
|
559
|
+
eas update --branch preview --message "New feature preview"
|
|
560
|
+
|
|
561
|
+
# Check build status
|
|
562
|
+
eas build:list
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
## OTA Updates
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
// app/_layout.tsx — check for updates on app launch
|
|
569
|
+
import * as Updates from 'expo-updates';
|
|
570
|
+
import { useEffect } from 'react';
|
|
571
|
+
import { Alert } from 'react-native';
|
|
572
|
+
|
|
573
|
+
function useOTAUpdates() {
|
|
574
|
+
useEffect(() => {
|
|
575
|
+
if (__DEV__) return; // skip in development
|
|
576
|
+
|
|
577
|
+
async function checkForUpdates() {
|
|
578
|
+
try {
|
|
579
|
+
const update = await Updates.checkForUpdateAsync();
|
|
580
|
+
if (update.isAvailable) {
|
|
581
|
+
await Updates.fetchUpdateAsync();
|
|
582
|
+
Alert.alert(
|
|
583
|
+
'Update Available',
|
|
584
|
+
'A new version has been downloaded. Restart to apply.',
|
|
585
|
+
[
|
|
586
|
+
{ text: 'Later', style: 'cancel' },
|
|
587
|
+
{ text: 'Restart', onPress: () => Updates.reloadAsync() },
|
|
588
|
+
]
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
} catch (error) {
|
|
592
|
+
console.error('OTA update check failed:', error);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
checkForUpdates();
|
|
597
|
+
}, []);
|
|
598
|
+
}
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
## Image Handling
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
import { Image } from 'expo-image';
|
|
605
|
+
|
|
606
|
+
// expo-image is the recommended image component (replaces RN Image)
|
|
607
|
+
function Avatar({ uri, size = 48 }: { uri: string; size?: number }) {
|
|
608
|
+
return (
|
|
609
|
+
<Image
|
|
610
|
+
source={{ uri }}
|
|
611
|
+
style={{ width: size, height: size, borderRadius: size / 2 }}
|
|
612
|
+
contentFit="cover"
|
|
613
|
+
placeholder={require('../assets/avatar-placeholder.png')}
|
|
614
|
+
transition={200}
|
|
615
|
+
cachePolicy="memory-disk"
|
|
616
|
+
/>
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
## Debugging
|
|
622
|
+
|
|
623
|
+
```bash
|
|
624
|
+
# Start dev server
|
|
625
|
+
npx expo start
|
|
626
|
+
|
|
627
|
+
# Open on specific platform
|
|
628
|
+
npx expo start --ios
|
|
629
|
+
npx expo start --android
|
|
630
|
+
npx expo start --web
|
|
631
|
+
|
|
632
|
+
# Clear cache
|
|
633
|
+
npx expo start --clear
|
|
634
|
+
|
|
635
|
+
# Doctor — check for configuration issues
|
|
636
|
+
npx expo doctor
|
|
637
|
+
|
|
638
|
+
# Prebuild — generate native projects for inspection
|
|
639
|
+
npx expo prebuild --clean
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### React Native Debugger Shortcuts
|
|
643
|
+
|
|
644
|
+
| Action | iOS Simulator | Android Emulator |
|
|
645
|
+
|--------|--------------|-----------------|
|
|
646
|
+
| Open dev menu | Cmd + D | Cmd + M |
|
|
647
|
+
| Reload | Cmd + R | R, R |
|
|
648
|
+
| Toggle inspector | Dev menu > Toggle Inspector | Dev menu > Toggle Inspector |
|
|
649
|
+
|
|
650
|
+
## Anti-Patterns
|
|
651
|
+
|
|
652
|
+
| Anti-Pattern | Correct Approach |
|
|
653
|
+
|-------------|-----------------|
|
|
654
|
+
| Using React Native `Image` for remote images | Use `expo-image` for better caching, transitions, and performance |
|
|
655
|
+
| Storing tokens in AsyncStorage | Use `expo-secure-store` for sensitive data (encrypted storage) |
|
|
656
|
+
| Inline styles on every component | Use `StyleSheet.create` for static styles, shared theme for dynamic |
|
|
657
|
+
| Not handling keyboard on forms | Use `KeyboardAvoidingView` or `react-native-keyboard-aware-scroll-view` |
|
|
658
|
+
| Testing only on simulator | Always test on physical devices before release |
|
|
659
|
+
| Ignoring safe areas | Wrap content in `SafeAreaView` or use `useSafeAreaInsets` |
|
|
660
|
+
| Using `expo eject` when a native module is needed | Use config plugins or development builds instead |
|
|
661
|
+
| Not setting up EAS Update branches | Configure update branches per environment (production, preview, development) |
|
|
662
|
+
| Blocking the JS thread with animations | Use `react-native-reanimated` worklets that run on the UI thread |
|
|
663
|
+
| Using `console.log` in production builds | Remove or conditionally disable logging in production |
|
|
664
|
+
| Large bundle without code splitting | Use lazy loading with `React.lazy` and Expo Router's built-in code splitting |
|
|
665
|
+
| Hardcoding API URLs | Use `app.config.ts` with environment-specific `extra` values |
|