ADR 0026: The public site: preview posture, first-party inquiries and cookieless analytics
- Status
- Accepted
- Date
- Deciders
- Founder
Context
The live site was honest but read like a design document: no metadata, no path to a person, no company page, duplicate hosts, no security headers, empty “None available today” tiers, and a hero that said nothing is available while a console ran live in the dev environment. Three expert critiques and an honesty check produced the specification in PRODUCT-PLAN.md Part 6.
Decision
- Posture: “private preview for design partners” once the two measurements of contract 10.12 are registered (status flip in one commit); until then every status word is data from
site/lib/content.tsstamped with a date; forbidden phrases and speed words are linted. - Lead capture through
POST /api/v1/public/inquiries(first-party, rate-limited, honeypot and time gate, e-mail via the verified mail identity, rows retained 24 months); no third-party forms. - Analytics through
POST /api/v1/public/eventsfrom a 1 KB first-party beacon: aggregate counts only, no cookies, no identifiers, no IP persistence, no banner; described on/privacy. This aggregate table is the one deliberate exception to “every mutation writes an audit row”. - New pages
/contact,/contact/sent,/company(founder-supplied slots),/privacy,/terms(fixed headings, slots,noindexuntil filled); nav label “Security”; real console screenshots framed and labelled; metadata (Open Graph, social card, canonical, JSON-LD, sitemap, robots, manifest); security headers and thewwwredirect in the deploy bundle; subset fonts; CSP report-only for one release.
Consequences
- Routes 155 -> 157; three tables; Settings
inquiry_notify_to,public_rate_salt,public_cors_origin. - Lighthouse results and live-audit reports are review evidence, never copy.
Alternatives considered
- Third-party form or chat widget: inquiry data would leave the account and a vendor name would appear; rejected.
- Cookie analytics with a banner: more data than the site needs; rejected.
- Publishing company facts as placeholders: invented content; rejected, slots render nothing.
Follow-ups
- Fill the company, privacy and terms slots with founder-supplied facts, then remove
noindex. - Move CSP from report-only to enforced after one clean release.
Last updated on