# As-Saaliyah — website + backend Next.js 15 (App Router) + Prisma + Neon serverless Postgres. This project is **both** the public website and the API the Flutter app consumes. ## Structure ``` website/ ├── app/ │ ├── page.tsx Daily Activities web UI (MVP landing) │ ├── layout.tsx, globals.css │ └── api/ Backend (Route Handlers) │ ├── activities/presets/ GET preset catalogue │ ├── activities/custom/ GET/POST user custom activities │ └── completions/ GET/POST per-day completions ├── prisma/schema.prisma Neon Postgres schema (CustomActivity, Completion) └── src/ ├── domain/ Framework-agnostic core (the source of truth) │ ├── i18n/ LocalizedText, locales (bn/en/ar, RTL) │ ├── time/ Prayer/sahri/iftaar vocabulary │ └── daily-activities/ Types, preset catalogue, scheduling (+ tests) ├── features/daily-activities/ Web UI components └── lib/ prisma client, API envelope, mappers, storage ``` `src/domain` has **no React/Next imports** — it is pure logic, unit-tested, and the conceptual twin of the Dart domain in `app/`. ## Setup ```bash cp .env.example .env # Neon: DATABASE_URL (pooled) + DIRECT_URL (direct) pnpm install pnpm db:generate # generate Prisma client pnpm db:push # sync schema to Neon ``` ## Scripts | Command | Does | |---|---| | `pnpm dev` | Dev server on :3000 | | `pnpm build` | `prisma generate` + production build | | `pnpm test` | Domain unit tests (`tsx --test`) | | `pnpm typecheck` | `tsc --noEmit` | | `pnpm db:studio` | Prisma Studio | ## Deploy (Vercel) Set the project root to `website/`, add `DATABASE_URL` / `DIRECT_URL` env vars (Neon), and deploy. `build` runs `prisma generate` automatically. Preset data is code-defined so `/api/activities/presets` is statically cached. ## Notes - Preset activities live in code (`src/domain/daily-activities/presets.ts`), **not** the DB — only user data (custom activities, completions) is persisted. - Rich domain shapes are stored as Prisma `Json` so they round-trip losslessly to the web UI and the Flutter app. - The web UI currently persists to `localStorage` (offline MVP); the same data shapes are already API-backed for the app and for future account sync.