Appearance
Tech Stack
Package Manager
- pnpm dengan workspace protocol (
workspace:*untuk internal packages). - pnpm workspace catalogs untuk shared dependency versions across packages.
Frontend (apps/web)
- SvelteKit 2.59.1 + Vite 6 — SSR-first framework dengan file-based routing
- Svelte 5.55.5 — runes-based reactivity
- Tailwind CSS 4 + shadcn-svelte
- TanStack Query 5 untuk Svelte (
@tanstack/svelte-query) untuk server state dan mutations - oRPC Client (
@orpc/client+@orpc/openapi-client/fetch) untuk API calls
API (@packages/api)
API code lives in dedicated package @packages/api, mounted via apps/web/src/hooks.server.ts:
- oRPC 1.14.2 (latest stable) — type-safe RPC framework dengan OpenAPI generation
@orpc/server— server-side procedures dan middleware@orpc/contract— contract-first route definitions (zero server deps)@orpc/openapi— OpenAPI spec generation@orpc/openapi/fetch— fetch adapter untuk Cloudflare Workers@orpc/client+@orpc/openapi-client— typed client untuk frontend
- better-auth 1.6.9 (latest stable) — auth dengan Drizzle adapter
- Zod 4 — schema validation (v4, latest stable). Date fields selalu pakai
z.coerce.date()untuk handle serialization wire. - Drizzle ORM — database access via
@packages/db - Pure Cloudflare Workers
fetchhandler (tidak pakai Hono atau HTTP framework tambahan)
Database
- Neon Postgres — Serverless PostgreSQL with edge connectivity
- Drizzle ORM 0.45.2 (latest stable) + drizzle-kit 0.31.10 (latest stable) untuk schema dan migrations via
drizzle-orm/neon-httpadapter
Auth
- better-auth 1.6.9 plugins (Drizzle adapter dengan PostgreSQL provider):
- Google OAuth
- Email / Password (dengan worker-friendly hasher)
- Magic Link / Email OTP
- Bearer —
Authorization: Bearer <token>header auth untuk non-browser clients - JWT —
/api/auth/tokendan/api/auth/jwksendpoints untuk JWT generation dan verification
- Password hashing: scrypt via
node:crypto.scrypt(dengannodejs_compatflag). Verified working di Workers — tidak perlu fallback. - Jangan pakai native bcrypt atau
@node-rs/argon2— requires native bindings yang gagal di Workers. - Role system:
student,teacher,admin,owner(stored dibetter-authuser table viaadditionalFields).
Email
- Resend untuk transactional emails (magic codes, notifications)
Storage
- Cloudflare R2 untuk photo evidence dan payment proof uploads
@packages/storagemenyediakan upload helpers dengan file type dan size validation
Telemetry
- @tigorhutasuhut/telemetry-js — OpenTelemetry SDK abstraction untuk tracing, metrics, dan structured logging.
- API (
@packages/api+apps/web/src/hooks.server.ts): pakai subpath/cloudflaredenganinstrument()wrapper /traceHandler+@traced()decorator di service mixins +withQueryName()untuk DB query spans. - Web browser: eager
instrumentFetch()di app entry (patchglobalThis.fetchsebelum module lain capture reference) + lazyinitSDK()via dynamic import. - Logger:
getLogger()dari telemetry-js — structured logging dengan auto-attachmenttrace_iddanspan_id. Jangan pakaiconsole.log/console.errordi production code. - Semua runtime error pakai
AppErrordari@tigorhutasuhut/telemetry-js/error— menggantikanServiceErrorcustom.
Deployment
- Cloudflare Worker + ASSETS (
apps/web) — SvelteKit SSR + API dalam satu Worker - Cloudflare Pages (
apps/docs) - wrangler CLI untuk local dev dan deploy
worker-configuration.d.tsgenerated bywrangler types(gitignored)
Code Quality
- Biome — single formatter dan linter untuk semua code
- lefthook — pre-commit hooks running
biome check --writeon staged files - turbo — monorepo task orchestration
Constraints
- NO native dependencies (no Rust, no node-gyp).
- Semua packages harus bisa run di Cloudflare Workers runtime (V8 isolates).
- Prefer Web APIs over Node.js APIs.
- Semua env vars diakses melalui
Envbinding atauenvdi Worker fetch context. - Worker (
apps/web) support fullenvkeys diwrangler.jsonc; Pages (apps/docs) TIDAK supportenvkeys — env vars dashboard-managed.