- App type: Expo + React Native note-taking app with web support
- Router: Expo Router (
src/app) - UI system: Tamagui (
src/themes/theme.ts) - Data sync: Supabase + Legend-State (
src/services/database) - Forms: Formik + Zod
- Error reporting: Sentry (
src/services/sentry) - Feature flags: Flagsmith (
src/services/flagsmith) - Analytics: Vexo (
src/services/vexo) - Package manager: pnpm 10 (
.npmrc)
- Prefer editing files under
src/unless the task explicitly requires native changes. - Keep route wrappers in
src/appthin and place UI/business logic insrc/screens,src/components,src/hooks, andsrc/services. - Use Tamagui components/tokens for UI primitives and theme values.
- Use the
@/*path alias (maps tosrc/*) over deep relative imports. - Report operational errors via Sentry (
Sentry.captureException(...)) in async/mutation flows.
src/app: Expo Router entrypoints and route layout files.src/screens: Screen implementations (feature-oriented).src/components: Reusable UI building blocks, typically one folder per component withindex.tsx.src/hooks: Custom hooks, grouped asuse-<feature>/index.ts[x].src/contexts: React providers for auth, notes, query client, and feature-specific state.src/services: External and platform integrations (Supabase, Sentry, analytics, flags, storage, AI, toolbar).src/themes: Tamagui theme/font/animation configuration.src/types: Shared domain and integration types (including generated Supabase types).src/utils: Pure helpers and shared test utilities.supabase: Local Supabase config and SQL migrations.assets: App icons/splash/art assets.ios,android: Native projects for prebuild/ejected workflows..github/workflows: CI workflows (codeql.yml,update.yml).
- Route definitions live in
src/app, but route files usually only re-export screens fromsrc/screens. - Route groups are used:
(app)for authenticated/main app routesauthfor auth modal stack- Global provider and stack setup is centralized in
src/app/_layout.tsx. - Canonical route constants live in
src/routers/index.ts(Routesenum). Use these instead of hardcoded paths.
- Notes sync:
notes$observable is configured insrc/services/database/index.ts.- Supabase sync uses realtime + soft delete (
deleted_at) + async persistence. NoteService(src/services/notes/notes.ts) is the primary CRUD surface for note operations.- Auth:
AuthenticationProviderinsrc/contexts/auth/index.tsxwraps Supabase auth state.- Query/mutations:
- React Query client is created in
src/contexts/query/index.tsx. - Feature hooks under
src/hooks/use-*-mutationshould own async side effects and error capture. - Storage:
src/services/storage/index.tswraps MMKV with async-like methods.
- Runtime env is validated with Zod in
src/config/env/index.ts. - Required public env keys:
EXPO_PUBLIC_FLAGSMITH_ENVIRONMENT_IDEXPO_PUBLIC_VEXO_ANALYTICS_API_KEYEXPO_PUBLIC_SUPABASE_ANON_KEYEXPO_PUBLIC_GEMINI_API_KEYEXPO_PUBLIC_SUPABASE_URLEXPO_PUBLIC_SENTRY_DSN- Build/release env keys also used:
SENTRY_AUTH_TOKENSENTRY_PROJECTSENTRY_ORG- App variants are configured in
app.config.tsusingAPP_VARIANT(development,preview,production).
- Language: TypeScript (strict mode on).
- Formatting/Linting: Biome (2-space indentation, double quotes, semicolons, trailing commas
es5). - Imports:
- Enforce group order:
builtin -> external -> internal -> parent -> sibling -> index. - Alphabetize ascending with blank lines between groups.
- Lint highlights:
no-consoleiserror.- Keep one blank line after imports.
- UI:
- Prefer Tamagui components and tokens (
$background,$color,$<accent>). - Use React Native primitives directly only when needed for platform APIs/layout edge cases.
- Types/validation:
- Prefer explicit interfaces/types.
- Use Zod for schema validation and parsing (
src/types,src/utils/validation.ts,src/config/env).
- Framework: Jest with
jest-expo. - Test files:
*.test.tsand*.test.tsx. - Component tests should be colocated in
__tests__directories where practical. - Prefer
src/utils/test.tsxcustom render helper for provider-wrapped component tests. - Snapshot testing is used and acceptable for stable UI structures.
- Coverage is collected from
src/**/*.{ts,tsx}.
pnpm start: Start Expo dev server.pnpm start:web: Start web build (TAMAGUI_TARGET=web).pnpm start:clear: Start with cleared cache.pnpm ios: Run iOS app.pnpm android: Run Android app.pnpm lint: Run Biome lint check.pnpm lint:write: Run Biome lint with auto-fixes.pnpm format: Run Biome formatter check.pnpm format:write: Run Biome formatter with auto-write.pnpm lint_format:check: Run Biome lint+format check.pnpm lint_format:check:write: Run Biome lint+format check with auto-write.pnpm check: TypeScript check (tsc --noEmit).pnpm validate:format + lint.pnpm validate:strict:validate + check.pnpm test: Run all tests.pnpm test -- path/to/file.test.tsx: Run a specific test file.pnpm checkDead: Dead code and unused export scan via Knip.pnpm supabase:start|stop|status|studio: Local Supabase lifecycle.pnpm supabase:db:push|pull|reset: Schema management.pnpm supabase:gen:types: Regeneratesrc/types/supabase.ts.
- Git hooks are managed with Lefthook.
- Pre-commit currently runs:
pnpm lintpnpm exec biome check --write {staged_files}- Commit message hook runs commitlint (
@commitlint/config-conventional). - Allowed commit types:
build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test- CI:
.github/workflows/update.ymlruns on push and executespnpm validate:strictbeforeeas update --auto..github/workflows/codeql.ymlperforms security analysis onmainand on schedule.
- Current base migration creates
notestable with: id,title,note,status,is_private,user_id,created_at,updated_at,deleted_at.- Realtime is enabled for
notes. - Trigger
handle_timesmaintainscreated_atandupdated_at.
- Run
pnpm validate:strictfor production-facing changes. - Run relevant tests (
pnpm testor targeted test files) when behavior changes. - Regenerate Supabase types when schema changes.
- Keep route wrappers thin and avoid business logic in
src/appfiles. - Confirm no secrets are committed from
.envor service credential files.