From First Principles.
Phase 0 through Phase 6 — a record of what we built,
how we built it, and the decisions that shaped it.
Portico was born from a personal reckoning. A mother diagnosed with type 2 diabetes, a decade of reactive management — labs checked when symptoms appeared, advice given after decline was already underway. The system was not broken. It was designed for the wrong moment. It showed up late, by definition.
The conviction that followed: reactive systems are always late. Proactive systems are built on visibility. Visibility changes trajectory.
Portico exists to build that visibility — not as a passive data logger but as an active intelligence layer that reads signals, finds patterns, and tells the user the one thing worth doing next.
What We're Building
Proactive personal health and wealth intelligence. Five domains. Five threats. One compounding intelligence layer.
Beneath all five domains: a unified homeostatic intelligence layer. The body defends five core variables above all else — glucose, blood pressure, temperature, respiratory rate, and pH. As wearables mature, continuous monitoring of these four signals becomes the backbone of everything Portico does. This is a long-arc thesis locked into the product architecture from the beginning.
Design Principles
These were established early and reviewed througout.
The Stack
Finalized in April 2026 after deliberate iteration and two key reversals.
Key reversal 1: Custom auth → Supabase Auth. Data stayed in CloudSQL; clean abstraction layer separates the two. The right call.
Key reversal 2: Cloudflare Pages → Vercel Hobby. Better Next.js DX, PR preview deployments. Cloudflare Pages remains the escape hatch if costs scale.
Accounts & Foundations
Zero to working infrastructure in a day.
Google Workspace, GCP project with Cloud Run and Cloud SQL enabled, Cloudflare DNS, Vercel connected to GitHub, Supabase with email auth only, PostHog, Sentry across three projects, Apple Developer account.
Cloudflare SSL sequence matters — grey cloud first to let Vercel provision SSL, then orange cloud with Full SSL. Getting this backwards costs hours.
Repo Bootstrap
Monorepo at n007/portico.life — pnpm workspaces, Turborepo. Structure: apps/web, apps/mobile, services/backend, packages/ui, packages/core, packages/types.
@portico/tokens package locked here — design system tokens including all five domain colors. Makefile first version, grew significantly over the phases.
Marketing Website v1
The first public-facing surface. Built from a Figma Make export — a key discovery that changed the workflow entirely.
Figma MCP tools only support design files — a hard platform restriction. Figma Make had already generated a complete React/Vite codebase. Instead of rebuilding from v0, we integrated that export directly into apps/web, converting from Vite to Next.js.
Waitlist was intentionally deferred. Site launched without email capture — get the brand right first, wire the backend later.
Mobile App v1
The largest single phase. Expo bootstrap through authentication, 13 screens across 5 flows, HealthKit integration across all four active domains.
Navigation architecture: floating pill tab bar at bottom center. Center action button (bolt) — intelligent, rule-based, never presents a menu. Portico made the decision; the user acts.
Auth language locked: “Continue with Apple / Google / Email” and “Other ways to Continue” — no generic tech terms.
Supabase Auth with Apple Sign In, Google Sign In, and email/password. Session persistence. User classification: Foundation tier (onboarding + manual data) and Compound tier (data-rich, wearable-connected). Auto-promoted by data richness.
Backend
Two days of hard work to get the backend deployed and talking to CloudSQL.
FastAPI on GCP Cloud Run (us-west1), minimum 1 instance always warm. Cloud SQL Postgres via Unix socket — not TCP; Cloud Run requires the socket path. Alembic migrations. Docker images built locally, not Cloud Build — Python layer caching advantage is significant.
Key Debugging Wins
504 errors. Cloud Run cold start timeout. Fix: --min-instances=1. One gcloud command.
CloudSQL connection. Cloud Run needs Unix socket path in DATABASE_URL, not TCP. Deepest debugging rabbit hole of the entire build.
JWT verification. supabase.auth.get_user() replacing deprecated JWKS approach. Two env variables removed after confirming nothing else used them.
Sage Data Model
Seven tables: user_profiles, blood_markers, healthkit_readings, cgm_readings, meals, body_composition, sage_metabolic_state.
Bathtub model: five stages — Clear, Steady, Rising, Heavy, Cresting. Agency-forward language. No medical vocabulary. No fear.
Scoring: six components weighted — Glucose Regulation (25%), Insulin Sensitivity (25%), Lipid Metabolism (15%), Inflammation (15%), Metabolic Fitness (10%), Body Composition (10%). Missing components redistribute weight rather than penalizing.
Beta Readiness
The culminating phase: get website, mobile app, and backend to a level worthy of beta users, Apple review, Dexcom API approval, and investor conversations.
5A — Mobile Flows + HealthKit
Complete onboarding flow with all profile fields wired to backend. Foundation flow with compounding graph animation. HealthKit sync across all four domains. Navigator gate logic locked: session → register → profile → foundation → onboarding → home.
5B — Website Polish
Alpha feedback came in raw and direct: fonts too small, contrast absent, white space broken, content flow confused. Three design-level changes rebuilt the site from the ground up.
Full background treatment — Portico architectural image as atmospheric backdrop, no white sections breaking it. Typography scale dramatically increased. Content flow locked: Five Horsemen as the problem statement → five domains as the solution.
Eight new pages: Privacy, Security, Cookies, Contact, About, Science, Platform, and Hero Video concept film. Two treatment types: Atmospheric and Flat Dark.
5C — Mobile Polish
Home screen legibility overhaul. Domain intro pages polished. Auth flash eliminated. Content Intelligence Framework — schema, engines, three surfaces (Science, Protocols, Action).
Domain home framework v2: every domain home is the same product wearing different colors. Six layers — Header → Core Theme → Key Metrics → Meridian → Arc → Protocol. Core themes: Sage = Bathtub, Apex = Triangle, Dusk = Wave, Still = Tide.
5D — The Milestone
Mobile app actually talking to the real GCP backend for the first time. Mobile → Supabase auth → backend → CloudSQL — end to end, working.
Ingestion
Phase 6 had one job: make it dead simple for users to get data into Portico.
Every realistic source — Apple Health, lab reports, blood pressure machines, glucose monitors, scales, grip strength devices, DEXA scans, meal photos — had to flow into a single canonical schema with no user friction. The thesis was deliberate. Synthesis without ingestion is theater. Get the inputs right first.
The phase expanded mid-flight. The original charter was a HealthKit rebuild and manual entry polish. What shipped was a generalizable extraction architecture that turns any image or PDF into structured, canonical health metrics — and then validated that architecture against a second, structurally different source.
6A — HealthKit V3
A complete rebuild of mobile HealthKit sync from first principles.
V1 had drifted. Multiple sync paths, inconsistent anchor handling, intermittent gaps in historical data. V3 collapsed it to a single runSync() call using native HKAnchoredObjectQuery, with per-metric anchors stored in AsyncStorage and a 13-week history window always-on. Pagination at 500 samples. Deduplication via ON CONFLICT (hk_uuid) DO NOTHING on the backend.
Three backend tables, one for each HealthKit sample shape: quantity, category, correlation.
V1 stayed untouched throughout the rebuild. V3 replaced it cleanly at cutover. Zero regression. No data loss. The discipline of “new version coexists with old until cutover” proved itself again.
6B — The Extraction Pipeline
The architectural centerpiece of Phase 6. A user uploads a blood panel, a BP machine screenshot, a scale reading, a DEXA scan, or a meal photo. The system extracts structured metrics mapped to a canonical schema.
Three layers, strictly separated: the LLM raw envelope, the post-processor, the final ExtractionResult. Each layer has one job. The boundaries are enforced, not aspirational.
A canonical vocabulary of 58 metrics across six categories. Each metric carries physiological plausibility bounds — not clinical reference ranges, which would imply medical judgment Portico doesn't make. Plausibility bounds answer one question: is this number physically possible for a human body. Numbers outside the bounds are rejected before they pollute the schema.
A file normalizer sits in front of every image and PDF, standardizing dimensions before the LLM ever sees the input. The reason was cost. The unexpected benefit was date-extraction consistency — raw inputs produced wildly different date parses depending on resolution.
Schema naming was locked early and propagated everywhere. Per-entry measured_at is when the measurement happened on the body. Envelope-level ingested_at is when Portico extracted it. The distinction matters: lab work measured weeks ago and uploaded today is not the same as a reading taken this morning. The schema reflects that.
Meals via photo landed at the end of the phase as the second validation source. Upload a photo of a meal. The system identifies items, estimates portions, computes per-item macros, surfaces a review screen with editable quantities, computes live totals as the user adjusts. Save. Done.
The extraction architecture didn't need to change to support meals. That was the point.
6C — Discipline at the Seams
A phase this long surfaces every shortcut taken in prior phases. Three rebuilds happened quietly in service of the main work.
Cloud SQL connection pooling hardened: pool_pre_ping, pool_recycle, pool_timeout, plus a FastAPI lifespan warmup query. Removed an entire class of intermittent prod errors that previously looked like network flakes.
The Cloud SQL Python Connector library — adopted early for convenience — deadlocked the async event loop under load. Replaced with the Cloud Run Auth Proxy sidecar pattern. One annotation, zero deadlocks.
EAS secret management formalized via scripts/push-eas-secrets.sh with a thin Makefile wrapper. The Makefile remained the canonical interface for every backend, mobile, and deploy operation, growing past 500 lines in itself!
Key Technical Learnings
- Three-layer extraction architecture generalizes. Built for blood panels. Reused for meals. Already designed into Phase 7 voice entry.
measured_atvsingested_at. The distinction is the schema. Date-only strings parse to midnight datetime for backward compatibility. The naming propagates through backend → mobile → DB.- Plausibility bounds, not clinical reference ranges. Portico doesn't make medical judgments. It rejects physically impossible values. The framing matters.
- Confidence as enum, not float. Three levels — high, medium, low. Floats imply precision that doesn't exist.
- SQLAlchemy
JSON≠ Postgrestext[]. Model column types must match migration column types exactly. Empty arrays will silently cast as JSON until they don't. - Cloud SQL Python Connector deadlocks the event loop. Use the Cloud Run Auth Proxy sidecar.
- V1 stays untouched during major rebuilds. HealthKit V1 → V3. Auth rebuild. Same pattern. Cutover is clean; rollback is trivial.
- Audit before patching. Every fix prompt that included “report findings before implementing” caught the wrong-diagnosis case at least once.
Key Technical Learnings
- Figma Make ≠ Figma Design. MCP tools only work on
figma.com/design/files. For Figma Make, screenshots or zip download only. - Framer URLs are not fetchable. JavaScript-rendered. Always get the source HTML or GitHub raw content.
- Cloud Run + Cloud SQL. Unix socket, not TCP. Always. Min instances = 1 to eliminate cold start timeouts.
- Local Docker builds for backend. Cloud Build is slow for Python — layer caching advantage is significant locally.
- pnpm v10 security.
onlyBuiltDependenciesrequired in rootpackage.jsonfor sharp, @sentry/cli, protobufjs. - Branch strategy. Surgical fixes: main. Large feature: feature branch, merge same day. The real safety net is git commits, not branches.
From Phase 0 to closed beta in four weeks.
From closed beta to a full ingestion platform in another four weeks that followed.
The pace is set by the work, not the calendar.
Spec-first. Prompt-driven. Gen AI Coding as primary instrument throughout.
The blueprint is never finished.
It compounds.
Portico Life, Inc. — porticolife.ai/blueprint
