Architecture & Design Decisions
This document explains the architecture and design patterns used in Pwask and guidance for production hardening.
High-level stack
- Next.js (App Router) — server rendering, edge/ISR, and API routes.
- Supabase — Postgres, Auth, Storage, Realtime (WS).
- Client: React + Tailwind CSS + IndexedDB for offline persistence.
- PWA: Web App Manifest + Service Worker for caching + background sync.
Key components
Frontend
- App Router pages render server-side where appropriate and hydrate on the client.
- Client-only components (forms, interactive widgets) use React state and hooks.
- next/image for optimized images, backed by Next's image optimizer (or external CDN).
Backend (Supabase)
- Postgres for ACID storage; Row Level Security (RLS) for per-user access rules.
- Supabase Auth for session management (email/password, magic link, OAuth).
- Storage for blobs (images, uploads); use signed URLs for client uploads.
Offline & Sync
- Local cache via IndexedDB (e.g., idb or dexie) for offline reads & write queueing.
- Background sync: queue mutations when offline and replay when online.
- Use optimistic UI updates with conflict resolution policies (last-write-wins or vector-clock if needed).
Service Worker & Caching
- Strategy recommendations:
- Static assets (JS/CSS/images): Cache-first with long TTL; update on new deployment.
- API requests: Network-first with fallback to cache for read endpoints.
- Offline pages: precache an offline shell and critical routes.
- Keep service worker small and test updates carefully — service workers persist until explicitly updated.
Security & Multi-tenant considerations
- RLS must be enforced on every table containing user/tenant data.
- Avoid embedding service_role keys in client bundles — server-only code must use service keys.
- For multi-tenant SaaS:
- Use
tenant_idororg_idcolumns and filter by session metadata. - Consider row-level policies using
auth.uid()or custom claims. - Enforce per-tenant resource limits (uploads, seats).
- Use
Scalability & performance
- Move heavy or long-running jobs to background workers or edge functions (if supported).
- Use Supabase read replicas or a database connection pooler if needed.
- Leverage CDN and edge cache headers for static assets and public API endpoints.
Observability & production readiness
- Add Sentry (or similar) for JS/Server error tracking.
- Add request logging/middleware for server-side performance metrics.
- Add uptime checks and monitoring for Supabase instance health.
Deployment patterns
- Prefer Vercel / Cloudflare Pages for first-class Next.js support.
- Use
pnpm buildandpnpm start(or the platform's build step). - Use ephemeral preview deployments for PRs and pre-production smoke tests.
Where to go next
- Back to Introduction
- Environment & deployment
- FAQ