01-projects/phdata

CAF Demo — Read-Only Static vs Live App (Side-by-Side Spec)

2026-06-15·project·status: active — decision spec, awaiting founder framework + phasing call
phDataCAFarchitectureastronextjspostgresrdsawsanthropic-sdk

CAF Demo — Read-Only Static vs Live App

Side-by-side per founder's request (2026-06-15 night), after the live-edit + generate-on-call requirement surfaced (see [[2026-06-15-caf-architecture-decisions-and-meta-council]] decision D, the open fork). Founder's framing: "Read-only may still be good for the hardened second pass, especially if many of the same rails are used." — which is exactly the synthesis below: they're not either/or.

A. Read-only static demo (the original quick-sites pattern)

B. Live app (edit + generate-on-call)

Side-by-side — the cost/complexity delta

Dimension A · Read-only static B · Live app
Core capability Browse a per-client catalog Edit + persist + generate-on-call
Writes None Full CRUD
DB at runtime None (JSON bundle) Postgres/RDS live
Framework Astro / any SSG Next.js / Remix / SvelteKit
Server compute None (static) Required (SSR/functions or Lambda/ECS)
AI None live Anthropic SDK, server-side
Auth/gating CloudFront+Cognito / Amplify access Cognito (login + roles)
Hosting S3 + CloudFront / Amplify static Amplify SSR or Lambda/ECS + RDS in VPC
Rough cost ~pennies–low-$/mo (static + a batch read) RDS floor (~$15–60/mo small/serverless-v2) + compute + per-generation Claude API; scales with usage
Ops burden Very low (rebuild + redeploy) Real (DB ops, backups, auth, server, security, AI)
Attack surface Minimal Meaningful — needs hardening
Best fit External, client-facing, hardened delivery Internal, rep-facing authoring tool

Headline delta: B adds a database, server compute, auth, and an AI backend — each a real ops + security commitment. A is nearly free and nearly unbreakable but read-only.

Shared rails (why building both isn't ~2x)

Founder's instinct is right — most of the system is common:

  1. Data model / schema — one (the ERD). Postgres is the live store; the static bundle is just a query/export of the same data.
  2. The JSON / display contract — the per-client bundle the static site renders is the same shape the live app serves its frontend. Define it once.
  3. UI components — the catalog cards, the use-case detail modal, the capabilities-mapping view render the same contract → built once, used by both (a shared component lib, or the static site reuses the app's components in SSG mode).
  4. Generation logic — the prompts/contract for producing a use case are shared between the offline agent (bundles) and the live server endpoint (on-call generation).
  5. Auth + AWS account + IaC + CI — one Cognito, one account, one deploy pipeline.
  6. Tenancy model — the same "open internal, hard-walled external" call.

So the incremental cost of A on top of B (or vice-versa) is mostly the export/render pipeline, not a second system.

The synthesis (recommended) — one system, two surfaces

This is exactly the founder's "read-only as the hardened second pass":

Open decisions for founder

  1. Framework for the live app: Next.js (largest ecosystem, first-class on Amplify + Vercel, server actions for the edit/generate flow) is my lean; Remix or SvelteKit are fine if the team prefers. Your call.
  2. Confirm the tenancy mapping: live app = internal-only; static read-only = the external client deliverable? (This is the clean version of "open internal, hard-walled external.")
  3. Snowflake's role: source-of-truth/analytics behind Postgres (sync Postgres→Snowflake), or drop Snowflake for this app and let Postgres be the store? (The catalog is small; Postgres alone may be enough.)
  4. RDS shape: Aurora Serverless v2 (scales to near-zero between calls) vs a small provisioned instance.

Cross-references