felipetavares.dev is one of two proof points on this site, alongside Selfwright: the same architectural discipline an enterprise system demands — ports & adapters, a hard cost constraint, a content pipeline with an enforced redaction rule — applied at personal-brand scale. The cards above give the shape; what follows is the full picture.
Architecture
The site runs on Astro 5 in hybrid output on the Cloudflare adapter — pages prerender to
the CDN at build time; the handful of routes that need a server (/api/contact, /api/chat) run
as Workers functions. React is used only for islands — components that genuinely need
client-side interactivity (theme toggle, mobile menu, contact form, chat widget, accessibility
panel) — so content pages ship close to zero client JS.
Underneath, src/core/ is pure TypeScript with zero framework or provider imports, organized as
hexagonal ports & adapters: ContentRepository, LlmProvider, EmbeddingIndex,
EmailSender, RateLimiter. Every page and API route imports through the port’s single binding
point (src/config/site.ts, src/config/llm.ts) — never an adapter directly. Swapping git for
a hosted CMS, or Workers AI for a different model provider, is a new adapter file and a one-line
config change, not a page-level rewrite.
The $0 stack
The one non-negotiable constraint was $0/month recurring, domain already owned. That ruled out a seat-priced hosted CMS and a pay-per-request LLM API as the default path, and pointed at Cloudflare’s free tier: Pages/Workers hosting, KV for sessions, Vectorize for embeddings, and Workers AI as the primary LLM provider (with Anthropic’s API as an optional, config-swappable fallback) — all inside free-tier headroom a personal site won’t bump into.
Git-based CMS, three editing modes
Content is git-backed Astro content collections (MDX for articles/projects, JSON for roles/talks/
site singletons) — one content model, edited through three equivalent paths: a direct file edit,
Claude Code, or the Keystatic UI at /keystatic in dev (storage.kind: 'local' for now;
GitHub-mode storage is a documented TODO pending a GitHub App). astro.config.mjs only registers
the Keystatic integration outside astro build, so no admin routes exist in the deployed site.
Design system
The site uses glass-card surfaces throughout (backdrop-filter: blur() saturate() with solid
fallbacks), a token-first theming layer (one CSS file drives both dark and light themes through
custom properties), and a Deep Signal hero — a vendored WebGL brain canvas that carries the
site’s own content (kinetic type, headline, CTAs) rather than placeholder copy. The galaxy
backdrop (site-wide WebGL layer) sits below all page content and adapts to light and dark themes,
scaling down to fine ink-speck density in light mode so content stays dominant.
One design token source (src/styles/tokens.css) drives both themes through CSS custom
properties switched by a single class on <html>. Tailwind v4’s @theme block maps those
tokens into utility classes, so no component hardcodes a hex value.
Redaction-gated content pipeline
A hard content rule — no employer-tied financial figures or headcounts anywhere on the public site — is enforced editorially across role JSONs, the dossier, the home credibility strip, project MDX, and the chatbot’s index. Metrics either use relative multiples (“cut integration cost by more than half”), magnitude bands (“8-figure portfolio”), or public non-financial facts. The chatbot’s index is rebuilt after every redaction pass so it can’t surface a pre-redaction figure from a stale chunk.
RAG chatbot with a provider router
/api/chat streams answers grounded in this site’s own content via Server-Sent Events. The
retrieval index is built by pnpm build-chat-index (scripts/build-chat-index.ts), chunking
articles, projects, roles, and site copy. LlmRouter tries Workers AI first and falls back to
Anthropic without any component-level change. The chat launcher is a 56px avatar circle (the
owner’s raster brand glyph) with a green presence dot — no persistent server state, no PII
storage.
The publish-kit
pnpm publish-kit <slug> turns one canonical MDX article into four syndication artifacts —
Substack HTML, a LinkedIn post, a Reddit framing note, an X thread — so writing is authored once
and syndicated outward rather than rewritten per platform. Dev.to and Hashnode pull the RSS feed
directly.
The /reading section
/reading is a public log of books, articles, and papers with the owner’s verdict on each —
one way his judgment compounds in public rather than staying in private notes. Each entry carries
a type, domains, and a verdict; filter chips let readers narrow by either axis.
Decisions
Astro over Next.js. The site is mostly static, SEO-critical content read on commutes. Astro’s islands architecture ships near-zero client JS on content pages by default; a Next.js app would have meant fighting its client-first defaults for a site that doesn’t need app-router-grade client state.
Git-based CMS over Sanity/Payload from day one. A hosted CMS adds a seat-priced dependency
and a second source of truth before there’s any evidence the git + Keystatic workflow can’t keep
up with actual publishing cadence. The ContentRepository port keeps that door open without
paying for it now.
Workers AI first, Anthropic as fallback — not the reverse. Workers AI is free within Cloudflare’s tier and colocates with the rest of the stack; routing through it first keeps the chatbot inside the $0 budget for normal traffic, with a paid-API fallback available via config if quality or availability demands it.
Flip page-transition morphs skipped, in favor of stability. The design spec included Astro View Transitions-driven Flip morphs between card and hero states. Landing the higher-value items — Lenis, section reveals, the accessibility control center, card magnetics — cleanly took priority; Flip remains a documented option.
The galaxy backdrop as a deliberate, logged budget exception. The site-wide WebGL galaxy
layer (React Bits Galaxy.tsx, MIT) adds motion-conditional render overhead. It’s gated behind
motionEnabled() && fx !== 'off', scales to low-density on mobile, and near-disappears in light
mode. The trade-off is logged; a config flag drops it instantly if needed.
What this demonstrates
The same discipline used on enterprise systems — ports before adapters, a $0-forced architecture rather than a padded one, redaction as a hard content gate, a design system with one signature device — holds up on a constrained, real, shipped system. The decisions, stack rationale, and a dated changelog are on /engineering.
The reasoning behind the architectural decisions is also written up as an article: Why I Built This Site the Way I Did.
Status
Active — this is the live, deployed site you’re reading. It ships in phases (documented in the
addendum’s delivery table), each gated on pnpm check, pnpm test, pnpm build, and a
Lighthouse/axe pass before merge.