Current Architecture (main)
Overview
Section titled “Overview”The main branch implements a single-tenant-per-infrastructure model. Each client gets their own dedicated buyer portal on Cloudflare Pages and their own Directus CMS container on a shared VPS.
Buyer Portal
Section titled “Buyer Portal”- Runtime: Astro 5 SSR with
@astrojs/nodeadapter (Node.js standalone) - Database: Direct PostgreSQL connection via
pgpool + Drizzle ORM - Hosting: Cloudflare Pages (one project per client)
- Auth: Lucia v3 with Drizzle adapter, passwordless OTP (email/WhatsApp)
- UI: Preact islands for interactive components, Astro components for static parts
- System: Directus 11 (headless CMS)
- Deployment: Docker Compose via Dokploy on shared VPS
- Database: Dedicated PostgreSQL database per client (same VPS instance)
- Auth: Directus built-in auth + Cloudflare Access for CRM protection
- File Storage: Directus-managed uploads (disk or R2 via Directus S3 adapter)
Deployment Flow
Section titled “Deployment Flow”Each client requires:
- Create Cloudflare Pages project —
scripts/cloudflare-pages-setup.mjs - Provision PostgreSQL database —
scripts/provision-client-postgres.sh - Deploy Directus via Dokploy —
scripts/dokploy-deploy-client.mjs - Configure Cloudflare Tunnel —
scripts/cloudflare-tunnel-setup.mjs - Configure Cloudflare Access —
scripts/cloudflare-access-setup.mjs - Run schema setup —
scripts/setup-directus-schema.mjs
Automation: deploy:client npm script orchestrates the full flow.
Data Flow
Section titled “Data Flow”Buyer Action ──> Cloudflare Pages ──> Astro SSR (API route) ──> pg pool ──> PostgreSQL │ v Directus API read ──> PostgreSQL (unit/agent/portal data)Limitations
Section titled “Limitations”- Each new client requires infrastructure provisioning (~30 min)
- Multiple Points of failure per client (Directus container, tunnel, Pages project)
- Directus adds operational overhead (CMS container management)
- Node.js runtime on Pages Functions has cold-start limitations
- No built-in multi-tenant data isolation (separate databases)