This is a pnpm + Turborepo monorepo for Munib Tracker (salah, zikr, qaza).
| App | Path | Role | Dev command |
|---|---|---|---|
| Product | apps/app |
Expo SDK 57 — iOS, Android, Web, Apple TV / Android TV (single codebase) | pnpm dev:app |
| Marketing | apps/marketing-web |
Next.js 16 landing site (port 3000) | pnpm dev:marketing-web |
| Admin | apps/admin |
Next.js ops console (port 3002) — users, reports, broadcasts, platform | pnpm dev:admin |
| API | apps/api |
NestJS 11 — cloud sync, auth, backend services (port 3001) | pnpm dev:api |
Deploy web surfaces to Vercel (four projects): see docs/PRODUCTION.md. Admin ops: docs/ADMIN.md.
OAuth (Google / Apple / Facebook): platform flows, env names, and console setup live in docs/OAUTH_SETUP.md. App Links for Apple on Android: docs/DEEP_LINKS.md.
Important: apps/marketing-web (port 3000), apps/api (port 3001), apps/admin (port 3002), and apps/app web (Expo, ~8081) are different apps.
Import via workspace package names:
@munib-tracker/shared— domain types, constants, validators, admin broadcast contracts@munib-tracker/db— Drizzle schema mirror for the admin console (DDL owned by API TypeORM migrations)@munib-tracker/live-activity-delivery— framework-agnostic ActivityKit APNs client + atomic job claim/deliver (Nest today; Fly worker later)@munib-tracker/surface-push-delivery— Expo + Web Push senders + atomic surface job claim/deliver@munib-tracker/store-screenshots— shared App Store / Play screenshot specs (locales, sizes, capture names)@munib-tracker/theme— design tokens,resolveTheme(), accent palette@munib-tracker/typescript-config— shared TS configs@munib-tracker/vitest-config— Vitest presets@munib-tracker/api-contract— OpenAPI spec exported fromapps/api@munib-tracker/api-client— Orval-generated fetch + TanStack Query SDK
Outside the pnpm workspace: tools/screenshot-studio/ — standalone screenshot editor (port 3010, pnpm dev:screenshot-studio). Workflow: docs/STORE_ASSETS.md.
- Lint/format: Biome at repo root (
pnpm lint,pnpm format-and-lint:fix) - Tests: Vitest (marketing-web, api, packages) + Jest (apps/app). No Playwright/Maestro E2E in CI — Maestro is used only for store screenshot capture (
pnpm screenshots:*,docs/STORE_ASSETS.md). - Product theme: All screens use
useTheme()fromapps/app/src/providers/theme-provider.tsx— no hardcoded colors. - Marketing styling: Tailwind CSS v4.3 with
@sourcescanning monorepo packages inglobals.css. - Fuzzy search: Fuse.js v7 in
apps/app— canonical moduleapps/app/src/lib/search.ts. See apps/app/AGENTS.md and.agents/skills/fuse-js/SKILL.md.
- apps/app/AGENTS.md — Expo product app
- apps/marketing-web/AGENTS.md — Next.js marketing site
- apps/admin/AGENTS.md — Ops / admin console
- apps/api/AGENTS.md — NestJS API server
pnpm install # always from repo root
pnpm generate:api # export OpenAPI + generate typed client (Orval)
pnpm dev # all dev servers (turbo)
pnpm dev:admin # admin console only (port 3002)
pnpm build:admin # production build for apps/admin
pnpm check:ci # same as CI + pre-push: lint → types → test → build → OpenAPI drift
pnpm check:quick # fast local smoke: lint + typecheck (not a git hook)
# Husky: pre-commit = Biome --write --staged + restage; commit-msg = commitlint (Conventional Commits); pre-push = pnpm check:ci
# Commits: prefer `pnpm commit` (Commitizen). See CONTRIBUTING.md.
pnpm turbo run lint check-types test
pnpm test:coverage # unit tests + HTML/Clover reports under */coverage/ (gitignored)
pnpm test:coverage:open # open coverage HTML in the browser (optional: app api shared …)
pnpm --filter app ios # Expo iOS dev build
pnpm --filter app android # Expo Android dev build
pnpm --filter app web # Expo web
pnpm --filter app build:data # regenerate bundled content (adhkar/duas/names/Qur'an/hadith)
# Seed allowlisted admin (needs DATABASE_URL): node apps/admin/scripts/seed-admin.mjs you@example.com
# Native (Expo prebuild / local release — requires apps/app/.env)
pnpm prebuild:app:android # expo prebuild + version sync
pnpm prebuild:app:ios
pnpm prebuild:app:tv # EXPO_TV=1 clean prebuild (Apple TV + Android TV)
pnpm prebuild:app:tv:android
pnpm prebuild:app:tv:ios
pnpm cleanbuild:app:android # prebuild --clean + version sync
pnpm cleanbuild:app:ios
pnpm cleanbuild:app:tv
pnpm doctor:app # expo doctor
pnpm dev:app:tv:android # run after TV prebuild
pnpm dev:app:tv:ios
pnpm dev:app:android:doctor # adb/emulator connectivity repair
pnpm dev:app:android:signs # Gradle signingReport
pnpm dev:app:ios:signs # Xcode signing settings (macOS)
pnpm release:app:android # local signed AAB (Gradle)
pnpm release:app:android:upload # upload AAB to Play internal testing
pnpm release:app:android-tv # Leanback AAB (after TV prebuild)
pnpm release:app:android-tv:apk # Leanback APK (Amazon / sideload)
pnpm release:app:android-tv:upload
pnpm release:app:ios # local signed IPA (xcodebuild, macOS)
pnpm release:app:ios:upload # upload IPA to App Store Connect
pnpm release:app:tvos # tvOS IPA (macOS; after TV prebuild)
pnpm release:app:tvos:upload # altool --type appletvos
pnpm build:app:android:tv # EAS production_tv
pnpm build:app:ios:tv
pnpm submit:app:android:tv
pnpm submit:app:ios:tvReligious content (Qur'an, hadith, adhkar, duas, 99 Names, audio) is sourced from open datasets, never hand-written, and generated into apps/app/assets/data/ (+ a manifest.json credits registry) by the pipeline in apps/app/scripts/build-data/. Bundled JSON is offline-first; extra Qur'an editions and full hadith collections are fetched cache-first from CDNs (apps/app/src/api/{quran,hadith}-remote.ts). Never edit generated content files (packages/shared/src/content/* for adhkar/duas, apps/app/assets/data/*, apps/app/src/lib/quran-loader.ts) by hand — change the builder and re-run build:data. Web first-load / chunk rules: docs/PROFILING.md (use quran-meta / dynamic import() so multi‑MB JSON stays out of __common).
Community / source-available: CONTRIBUTING.md · docs/OPEN_SOURCE.md · LICENSE · NOTICE.
Planning + reference lives in docs/ — start at docs/README.md:
| Doc | Role |
|---|---|
BACKLOG.md |
Open work (product, perf, devices, content) |
FEATURES.md |
Shipped NF-* feature catalog |
OPEN_SOURCE.md |
Public release checklist (PolyForm NC) |
RELEASES.md |
Per-app semver via Release Please (tags, changelogs, build numbers) |
I18N_GUIDE.md |
23-locale i18n ops, scripture rules |
OAUTH_SETUP.md |
Google / Apple / Facebook sign-in (native + web) |
DEEP_LINKS.md |
Custom scheme + HTTPS App Links (incl. Apple OAuth) |
PRODUCTION.md |
Vercel deploys + production env (incl. OAuth + admin) |
ADMIN.md |
Ops console (modules, roles, seed, branding) |
ADMIN_BROADCASTS.md |
In-app / push broadcasts from admin → product |
DATA_INGESTION.md + FREE_OPEN_SOURCE_DATA.md |
Content pipeline & OSS sources |
PROFILING.md |
Web/native perf profile + remaining __common work |
NATIVE_SURFACES.md |
Widgets, Live Activities, Siri, Watch, Wear |
LIVE_ACTIVITY_PUSH.md |
ActivityKit remote push (QStash, cron, future Fly worker) |
WEB_PUSH.md |
Web Push + Android Expo surface phases |
DEVICES.md |
Platform support matrix |
TV.md |
Apple TV / Android TV (EXPO_TV prebuild) |
STORE_ASSETS.md |
App Store / Play screenshots (Maestro) |
IOS_APP_COPY.md · ANDROID_APP_COPY.md |
Store listing copy |
vercel/turborepo— monorepo patternsexpo/skills— Expo / React Nativevercel/next.js— Next.js 16 best practices.agents/skills/nestjs— official NestJS markdown guides (mirrored from nestjs/docs.nestjs.com).agents/skills/fuse-js— Fuse.js fuzzy search (from krisk/Fuse/docs); use for all search bars andapps/app/src/lib/search.ts