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_id or org_id columns and filter by session metadata.
    • Consider row-level policies using auth.uid() or custom claims.
    • Enforce per-tenant resource limits (uploads, seats).

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 build and pnpm start (or the platform's build step).
  • Use ephemeral preview deployments for PRs and pre-production smoke tests.

Where to go next