{"id":"home-page","slug":"home","meta":{"title":"Andrew Linh — Systems Architect & Technical Writer","description":"Portfolio and editorial site of Andrew Linh. Backend architecture, structured data infrastructure, developer tools, and AI-native systems — written with precision."},"sections":[{"id":"home-hero-1","type":"home-hero","data":{"label":"Systems architect · technical writer","title":"I design backends that stay honest,","titleHighlight":"then write about why.","description":"Architecture for structured data platforms, developer tools, and AI-native systems — with the calm of a well-tuned terminal.","primaryCta":{"id":"cta-work","label":"View work","href":"/work","variant":"primary"},"secondaryCta":{"id":"cta-blog","label":"Read writing","href":"/blog","variant":"secondary"}},"settings":{"paddingTop":"lg","paddingBottom":"lg"}},{"id":"home-featured-1","type":"featured-projects","data":{"label":"Selected work","title":"Case studies","description":"Four engagements where schema contracts, type safety, and measurable outcomes mattered more than slide decks.","limit":4,"items":{"schemaforge-cms":{"id":"schemaforge-cms","title":"SchemaForge CMS","subtitle":"Schema-driven content publishing for multi-tenant sites","year":2025,"role":"Lead systems architect","context":"A content platform serving 40+ tenants needed deterministic page assembly without CMS drift or silent field mismatches.","problem":"Editors published broken pages weekly because free-form JSON and ad-hoc React sections diverged. Publish errors averaged 12% of releases, and rollback windows stretched past two hours.","architecture":"Introduced Zod collection contracts, keyed collection documents, and section capsules that bind via $ref. Studio inspector surfaces were generated from the same schemas used at render time. CI validated every page and collection against registry schemas before merge.","result":"Publish errors dropped 40%. Mean time to recover from a bad content release fell from 2.1 hours to 18 minutes. New tenant onboarding time moved from weeks to a two-day scaffold.","stack":["TypeScript","Zod","React","Vite","PostgreSQL"],"image":{"url":"https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=1600&q=80","alt":"Dark IDE with structured code on a widescreen monitor"},"tags":["cms","schemas","content-infra"],"featured":true},"typebridge-api":{"id":"typebridge-api","title":"Typebridge API","subtitle":"End-to-end type safety from Zod to OpenAPI to clients","year":2024,"role":"Principal engineer","context":"A developer-tools company shipped three client SDKs from a hand-maintained OpenAPI document that routinely drifted from runtime validators.","problem":"Contract mismatches caused 23 production incidents in six months. SDK releases lagged API changes by an average of nine days.","architecture":"Made Zod schemas the single source of truth. Generated OpenAPI 3.1, TypeScript clients, and contract tests from the same definitions.","result":"Contract-related incidents fell 78%. SDK lag dropped from nine days to same-day.","stack":["Zod","OpenAPI","Node.js","GitHub Actions"],"image":{"url":"https://images.unsplash.com/photo-1518770660439-4636190af475?w=1600&q=80","alt":"Circuit board traces representing API connectivity"},"tags":["api","type-safety","dx"],"featured":true},"agentops-runner":{"id":"agentops-runner","title":"AgentOps Runner","subtitle":"Deterministic evaluation harness for AI agent workflows","year":2025,"role":"Architecture lead","context":"An AI product team needed reproducible evals for multi-step agents before promoting prompts and tools to production.","problem":"Ad-hoc notebook evals produced non-comparable scores. Regressions slipped into production twice a month.","architecture":"Built a runner with frozen fixtures, tool stubs, deterministic seeding, and structured trace artifacts with typed scorecards.","result":"Eval variance across identical runs dropped below 1%. Production agent regressions fell from ~8/month to 1/month.","stack":["Python","TypeScript","Redis","OpenTelemetry","Docker"],"image":{"url":"https://images.unsplash.com/photo-1620712943543-bcc4688e7485?w=1600&q=80","alt":"Abstract neural network visualization on a dark display"},"tags":["ai","evals","observability"],"featured":true},"lakehouse-ledger":{"id":"lakehouse-ledger","title":"Lakehouse Ledger","subtitle":"Structured audit-trail infrastructure for regulated data pipelines","year":2023,"role":"Systems architect","context":"A fintech data platform needed immutable lineage across batch and streaming transforms.","problem":"Compliance reviews could not reconstruct metric definition changes. Audit prep consumed three engineer-weeks per quarter.","architecture":"Designed an append-only ledger of schema versions, transform fingerprints, and partition manifests wired into Spark and Flink jobs.","result":"Quarterly audit prep dropped from three engineer-weeks to four engineer-days. Lineage lookup latency stayed under 200ms p95.","stack":["Apache Iceberg","Spark","Flink","PostgreSQL","gRPC"],"image":{"url":"https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1600&q=80","alt":"Earth from orbit with illuminated city lights"},"tags":["data-infra","audit","lakehouse"],"featured":true}}},"settings":{"paddingTop":"md","paddingBottom":"md"}},{"id":"home-posts-1","type":"recent-posts","data":{"label":"Writing","title":"Latest notes","limit":3,"items":{"schema-driven-content":{"id":"schema-driven-content","title":"Schema-driven content is the missing layer","dek":"Why treating page sections as typed contracts beats free-form CMS blobs for multi-tenant sites.","date":"2026-03-12","readingTime":"9 min","tags":["schemas","cms","content-infra"],"body":"## The quiet failure mode\n\nMost content platforms fail the same way: the editor UI drifts from the renderer, and nobody notices until a publish breaks production.\n\n## Contracts over conventions\n\nSchema-driven content means every section, collection item, and form submission has a Zod contract shared by Studio, CI, and runtime.\n\n## The payoff\n\nYou trade a little authoring friction for operational calm. Publish errors become schema errors you can fix before merge.","image":{"url":"https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=1600&q=80","alt":"Laptop showing structured documents"}},"e2e-type-safety":{"id":"e2e-type-safety","title":"End-to-end type safety without the ceremony","dek":"How to keep Zod, OpenAPI, and generated clients honest without drowning teams in codegen rituals.","date":"2026-01-28","readingTime":"8 min","tags":["type-safety","api","dx"],"body":"## The split brain problem\n\nTeams often maintain three truths: runtime validators, OpenAPI, and handwritten clients.\n\n## One source, many projections\n\nStart with Zod at the boundary. Generate OpenAPI. Generate clients. Contract-test responses against the same types.\n\n## DX that sticks\n\nDevelopers adopt type safety when it removes toil.","image":{"url":"https://images.unsplash.com/photo-1461749280684-dccba630e2f6?w=1600&q=80","alt":"Developer working at a desk with code on screen"}},"ai-agent-tooling":{"id":"ai-agent-tooling","title":"Building AI agent tooling that can be graded","dek":"Deterministic fixtures, typed traces, and golden scorecards turn agent demos into operable systems.","date":"2025-11-04","readingTime":"11 min","tags":["ai","agents","evals"],"body":"## Demos are not systems\n\nAn agent that works in a notebook is not ready for production.\n\n## Make evaluation first-class\n\nDefine scenarios as data. Persist every tool call as a typed event log.\n\n## Calm over clever\n\nThe goal is an agent you can reason about — graded, bisected, and rolled back like any other service.","image":{"url":"https://images.unsplash.com/photo-1677442136019-21780ecad995?w=1600&q=80","alt":"Abstract glowing network suggesting AI systems"}},"dx-of-structured-systems":{"id":"dx-of-structured-systems","title":"Developer experience for structured systems","dek":"Precision tooling should feel quiet: fast feedback, honest errors, and fewer places to look.","date":"2025-09-18","readingTime":"7 min","tags":["dx","tooling","architecture"],"body":"## DX is an architecture outcome\n\nIn structured systems, DX is the system. If the feedback loop is slow, the architecture will be circumvented.\n\n## Terminal aesthetics, human patience\n\nGood tools feel like a well-tuned terminal: dense signal, low noise, predictable commands.","image":{"url":"https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=1600&q=80","alt":"Laptop with code editor beside a notebook"}}}},"settings":{"paddingTop":"md","paddingBottom":"md"}},{"id":"home-bio-1","type":"bio-band","data":{"label":"Briefly","title":"Precision over performance.","body":"I spend most of my time on the seams: schemas that bind editors to runtimes, APIs that stay typed end-to-end, and agent tooling you can actually grade.\n\nThis site is the professional surface and the editorial notebook — same standards in both.","image":{"url":"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=1200&q=80","alt":"Portrait of a man in a dark shirt looking calmly at the camera"},"cta":{"id":"bio-about","label":"Full about","href":"/about","variant":"secondary"}},"settings":{"paddingTop":"md","paddingBottom":"md"}},{"id":"home-cta-1","type":"cta-band","data":{"title":"Need a calm systems partner?","description":"Architecture reviews, schema design, and technical writing for teams shipping structured platforms.","primaryCta":{"id":"cta-contact","label":"Start a conversation","href":"/contact","variant":"primary"}},"settings":{"paddingTop":"lg","paddingBottom":"lg"}}]}