# Allen Zhou > Notes, writing, projects, and ideas from Allen. Essays on building agents, AI tooling, developer infrastructure, and shipping products at Vercel. For agents: every writing post is available as raw markdown at `https://allenzhou.me/w/.md` or by sending `Accept: text/markdown` to the rendered URL. A markdown sitemap is at https://allenzhou.me/sitemap.md, a concatenated dump of every post is at https://allenzhou.me/llms-full.txt, and an agent-facing skill file with install/config/usage examples is at https://allenzhou.me/AGENTS.md. ## Published - [Building incredible MCP clients and servers](https://allenzhou.me/w/building-mcp-clients-and-servers.md): A complete, hands-on guide to the Model Context Protocol from both ends. The client side: how Eve turns an MCP server into model-callable tools with one file, the three auth strategies (static token, Connect-managed OAuth, self-hosted OAuth), lazy discovery, tool filtering, per-connection approval, and the OpenAPI superset. The server side: how to design and build a great MCP server (tool granularity, schemas, errors, auth, transports) that an Eve agent (or any MCP host) can consume. It ends with the one thing Eve cannot do yet (expose itself as an MCP server) and the aspirational shape that capability should take. - [Building a cloud coding agent with Eve](https://allenzhou.me/w/cloud-coding-agent-with-eve.md): A complete guide to a cloud coding agent you trigger from Slack or the web: describe a task, the agent checks the repo out into an isolated sandbox, edits code with shell tools, runs the tests, opens a pull request, and pauses for your approval before pushing. It runs unattended on serverless infrastructure, survives redeploys mid-task, and streams progress back to wherever you triggered it. The guide shows the whole agent/ directory: instructions, the Slack and web channels, the sandbox, tools for branching and opening PRs, human-in-the-loop gates, and deployment. - [Building CodeReview with Eve](https://allenzhou.me/w/codereview-with-eve.md): A full guide to CodeReview: an agent that reviews your pull requests on GitHub. It triggers on opened and updated PRs through the GitHub channel, gets the diff in context and the repo checked out into the sandbox, runs the tests and linters, reasons about correctness and security, posts inline and summary comments, and gates risky verdicts (like requesting changes or auto-approving) behind human approval. The guide shows every file: instructions, review skills, tools for posting comments and running checks, the GitHub channel, and a Linear connection for filing follow-up issues. - [Building a Data Analyst with Eve](https://allenzhou.me/w/data-analyst-with-eve.md): A complete guide to a data-analyst agent that answers questions about your warehouse in Slack and the browser. It connects to a SQL warehouse, runs read-only queries through a typed tool, validates and bounds results, charts them in the sandbox, gates expensive or destructive queries behind human approval, and posts results back to where you asked. The guide covers the whole agent/ directory: instructions, a schema skill, the query tool with guardrails, a charting tool over the sandbox, the warehouse connection, Slack and web channels, and a scheduled daily metrics digest. - [Building a DevRel Bot with Eve](https://allenzhou.me/w/devrel-bot-with-eve.md): A complete guide to a DevRel agent that maintains docs, guides, and sample apps. It pulls context from many sources (the repo, GitHub issues, a changelog, Slack questions, an analytics MCP server), runs on both a heartbeat and a cron, opens docs PRs when it finds drift, answers questions in Slack, and flags sample apps that break against new releases. The guide covers the full agent/ directory: instructions, skills, multi-source connections, the Slack and GitHub channels, two schedules (heartbeat vs cron), subagents, and the difference between a heartbeat and a cron in practice. - [Features Eve Should Add](https://allenzhou.me/w/eve-aspirational-features.md): A companion report to the Eve articles and guides. Throughout the series I leaned on capabilities Eve does not have yet but should. This collects every one of them in a single place, each rooted in a primitive Eve already ships, with the shape it should take and why it matters. The list: an MCP server channel, subagent tool approvals, a typed GitHub PR and review surface, multiple sandboxes per session, a first-class artifact store, declarative tool-result retention, an incremental checkout cache, a real heartbeat primitive, a shared memory store, local network-policy emulation, and a pluggable local binary shim. - [How Eve executes tools, especially MCP](https://allenzhou.me/w/eve-tool-execution-and-mcp.md): A deep look at the machinery between "the model wants to call a tool" and "the tool result is in history," with a focus on MCP connections. It covers the execute(input, ctx) contract, where tools run (the app runtime, not the sandbox), how tool calls survive durable step boundaries and crashes, human-in-the-loop approval, toModelOutput and surviving compaction, dynamic tools, and then the full MCP path: lazy discovery via connection__search, qualified naming, per-step token resolution, the parking-and-resume OAuth flow, and how a remote MCP tool call actually executes at runtime. It ends with what does not exist yet and should. - [Eve vs Codex, OpenCode, and Claude Code](https://allenzhou.me/w/eve-vs-agents.md): A deep, honest comparison of Eve against the leading coding agents. Codex, OpenCode, and Claude Code are local, process-bound loops that live on your laptop. Eve is a filesystem-first framework for durable backend agents that runs on serverless infrastructure and survives crashes, deploys, and multi-day pauses. This post traces the architectures side by side: the agent loop, tool execution, sandboxing, MCP support, the session and state model, and where each one is the right tool. It ends with a frank look at what Eve gives up to get durability, and what it should add next. - [How Eve Works With No Database](https://allenzhou.me/w/eve-with-no-database.md): Most agent frameworks make you provision a database before you can remember a single message. Eve does not. This post traces exactly where an Eve agent keeps its memory without a DB: durable workflow steps for conversation history and state, an append-only event stream for replay, continuation tokens and hooks for parked work, and backend snapshots for the sandbox filesystem. It covers the Workflow SDK World layer (JSON files on disk locally, managed storage plus Queues on Vercel), defineState for per-session working memory, why state is explicitly not a database, and the line where you actually do want an external store. - [Leveraging just-bash in your coding agent](https://allenzhou.me/w/just-bash-coding-agents.md): just-bash is a bash interpreter implemented in TypeScript with an in-memory filesystem: a real shell that runs in-process, with no VM, no container, and no subprocess. This post explains what it is, how Eve uses it as the local sandbox backend so eve dev gives you a working bash environment with zero setup, why an emulated shell is exactly right for development and tests and exactly wrong for production, and how Eve makes the swap to a real Vercel Sandbox microVM transparent. It then shows how to actually leverage a shell-shaped tool surface in a coding agent, and ends with what just-bash and the local backend should grow next. - [Building OpenWiki with Eve](https://allenzhou.me/w/openwiki-with-eve.md): A complete guide to building OpenWiki: an agent that generates and maintains a living wiki for any repository. It checks the repo out into the sandbox, explores the code with bash and grep, writes structured wiki pages to Vercel Blob, serves them through a Next.js frontend, regenerates affected pages when code changes via the GitHub channel, and refreshes everything on a schedule. The guide walks the full agent/ directory: instructions, tools, the GitHub channel, the sandbox, schedules, and deployment, with every file shown. - [Why your agent should be serverless](https://allenzhou.me/w/why-agents-belong-on-serverless.md): Agents look like the worst possible fit for serverless: they're long-running, stateful, and unpredictable, and serverless functions are short-lived, stateless, and time-boxed. This post argues the opposite. The thing that makes agents hard (waiting, pausing, surviving failure) is exactly what durable serverless execution solves, and the thing serverless seems bad at (long-running processes) is a problem you shouldn't have in the first place. It walks through the cost model, the failure model, the scaling model, and the security model, using Eve as the concrete implementation of a durable agent on serverless infrastructure. - [docsbot: an agent that keeps docs current, and why it is built this way](https://allenzhou.me/w/docsbot.md): A deep, code-level walkthrough of docsbot: an agent that watches where product truth lands (code, issues, chat, design docs), drafts and maintains docs as reviewable pull requests, and resurfaces the work to whoever owns the area. Covers the domain model in TypeScript, the event pipeline (ingress, normalize, route, queue, distill, consolidate), per-area agents on a durable workflow engine, two-tier persistence where git stays authoritative and Neon is a rebuildable second brain, and the control plane in real code: a URL-synced DataTable, pages over modals, a one-rule icon system, oklch tokens bridged to Tailwind, a cookie-persisted sidebar, and a hydration-safe theme toggle. - [Animation vocabulary](https://allenzhou.me/w/animation-vocabulary.md): A working glossary of motion: the names I use for animation patterns so I can describe them precisely, whether I am talking to a designer, a teammate, or an AI. Covers entrances and exits, sequencing and timing, transforms, state transitions, scroll, interaction feedback, easing, springs, looping and ambient motion, polish effects, performance, the browser APIs and libraries underneath (CSS transitions and keyframes, the Web Animations API, the View Transitions API, FLIP, Motion, GSAP, Lottie, Rive), and the animation principles that decide when motion is worth it. - [Ash, end to end](https://allenzhou.me/w/ash.md): A long, complete walkthrough of Ash, the filesystem-first framework for durable backend agents. It starts from nothing and ends at expert level: the mental model and three-layer architecture, every authored slot under agent/, tools, skills, connections, sandboxes, hooks, channels, subagents, schedules, the durable session and streaming model, the React and Next.js front-end surface, deployment to Vercel, and how the framework works underneath (discovery, the compiler, artifacts, unified context, and step replay). The last third is for contributors: the boundaries you must respect, the testing tiers, the mechanical invariants, and how to ship a change. - [How Vercel writes docs, as a quiz](https://allenzhou.me/w/writing-guidelines.md): Vercel publishes a single-file writing standard: a few hundred lines of rules for voice, concision, content types, placeholders, typography, and the AI tells that give a draft away. Most of it is more interesting as a test than as a checklist, because every rule has a wrong version that looks fine until you name why it is wrong. So this is the standard reframed as an interactive tour: read the principle, pick the better sentence, lock in your answer, and delve into the reasoning. Covers the by-monkeys passive test, the banned words, Diataxis content types, weasel words, placeholders, units, headings, and the spec-sheet voice that signals a machine wrote the paragraph. ## In progress - [Drawing architecture diagrams with a coding agent](https://allenzhou.me/w/diagrams-with-a-coding-agent.md): The best tool for an architecture diagram is not Figma or Mermaid. It is a coding agent emitting SVG. The output is text, so it diffs, themes, and version-controls like the rest of your repo, and you refine it by describing the change instead of nudging boxes. This walks through the method and rebuilds a routing diagram (paths proxied through Vercel to Discourse and a Next.js app) as a worked example. - [Eve vs Codex, Claude Code, Pi, and OpenCode](https://allenzhou.me/w/eve-vs-harnesses.md): A comparison of Eve against other agent harnesses (Codex, Claude Code, Pi, and OpenCode), and where its durable-serverless design leads to different choices. - [Making a docs site fast, and keeping it fast](https://allenzhou.me/w/docs-performance.md): A field report from a multi-month effort to make a large documentation site fast. The first half is the obvious work: ship less JavaScript. The second half is the part most teams miss: rendering, not data or network, was the real bottleneck, and the fix was to render less and render progressively. Then the durable part, the monitoring that keeps it from sliding back. - [Aurora DSQL versus the alternatives](https://allenzhou.me/w/dsql-vs-alternatives.md): Aurora DSQL is a genuinely new shape of database: serverless, active-active across regions, PostgreSQL-compatible on the wire, and built on optimistic concurrency control instead of locks. That combination is rare, and it comes with sharp edges (no foreign keys, no sequences, transaction limits, and commit-time conflicts you must retry). This is a deep, code-first comparison of DSQL against Neon, provisioned Aurora/RDS, CockroachDB, Spanner and AlloyDB, PlanetScale, Yugabyte, and the edge SQLite options, organized around the axes that actually decide the choice: consistency, write scalability, region topology, Postgres completeness, the connection model, concurrency control, scaling, and cost. Includes real connection, retry, and schema code for DSQL and the closest competitors. Limits cited are accurate as of writing and evolving; always confirm against current docs. - [Heartbeat versus cron for recurring work](https://allenzhou.me/w/heartbeat-vs-cron.md): There are two fundamentally different ways to run recurring or background work: an external scheduler that fires discrete invocations on a clock (cron), or a long-running process that drives itself and proves it is alive with a heartbeat. They look interchangeable and are not. Cron gives you cheap, stateless, time-anchored triggers with at-least-once semantics and no overlap protection. Heartbeats give you continuous, stateful work, sub-second cadence, leader election, and dead-worker detection, at the cost of an always-on process. This goes deep on both models with real code: serverless cron with locking and idempotency, a drift-corrected heartbeat worker loop, lease-based leader election, dead-worker reaping, and the hybrid where cron supervises the heartbeat. - [Why moving an app from SSR to static at the edge makes it faster](https://allenzhou.me/w/ssr-to-static-edge.md): A team recently moved a large authenticated app off server-side rendering to a static Vite plus TanStack Router build served straight from edge workers, and saw time to first byte drop 65% at p75, content appear 50% sooner, and navigation get snappier. That result looks paradoxical if you believe SSR is always faster, so this explains exactly why it is the right call for this shape of app: what TTFB actually measures, why SSR inflates it for an auth-gated streaming product that gets no benefit from server-rendered HTML, how the static-shell-at-the-edge model works end to end, and the real code (TanStack Router auth and preloading, TanStack Query streaming, a Vite build, and a Cloudflare Worker serving assets with an edge auth gate). It closes with the nuance: SSR is still right for content sites, and knowing which side you are on is the whole skill. - [Client state in a large dashboard with Zustand](https://allenzhou.me/w/client-state-zustand.md): In a modern React app most state is already accounted for: server data lives in a fetch cache, URL state lives in the address bar, and component-local state lives in React. Zustand is for the slice left over, the shared, ephemeral client and UI state that does not belong to any one of those. This works through the full state taxonomy, the two Zustand store shapes (the global singleton and the per-instance factory with context), the conventions that keep stores maintainable, the boundary with server state, the SSR gotchas, and, precisely, where each kind of state is physically stored. - [Debugging slow pages on docs and dashboards](https://allenzhou.me/w/debugging-slow-pages.md): Performance reports almost always arrive the same way: 'is the dashboard slow for anyone else?' The skill is turning that one sentence into a root cause. This is the full method, drawn from real incidents on a large Next.js dashboard and docs site: how to reproduce and classify, the mental model of where time goes, the actual tools (network tab, request ids, traces, logs, the React profiler, slow-query logs), and a long series of worked cases with the symptom, the diagnosis, the fix, and the pattern underneath. - [The limits of Next.js 15 without the flags](https://allenzhou.me/w/nextjs-15-limits.md): Cache Components (use cache, partial prerendering) are the headline of Next.js 16, and once you have used them it is worth understanding exactly what stable Next.js 15 cannot do without the experimental flags, because the gap explains why the feature needed framework support in the first place. The root limitation is that a route is either fully static or fully dynamic, never both in one response. This walks the whole boundary: what makes a route dynamic, why Suspense is not a prerender boundary in 15, the cache-directive model and its stable analogues, the two ways to approximate PPR by hand, and the sharp edges (per-user caching, global cache handlers, request reads) you hit along the way. - [Should a Next.js docs and dashboard migrate to TanStack?](https://allenzhou.me/w/nextjs-to-tanstack.md): TanStack Start is stable, host-agnostic, and genuinely good, which makes the migration question real for a docs and dashboard already running on Next.js 15.5.18 and Google Cloud. But migrating a large working app is a rewrite, not a port, because the two frameworks disagree at the root: Next is RSC-first by default, TanStack is isomorphic by default with explicit server functions. This works through what you would actually gain, what you would give up, the concrete migration surface, the self-host-on-GCP lens that changes the math, the cheaper alternatives to try first, and a decision framework that splits the static docs from the interactive dashboard. - [Building a static docs site with a hashed CSP](https://allenzhou.me/w/static-docs-with-hashed-csp.md): A complete, build-it-yourself walkthrough of a Next.js 15.5.18 docs site that is statically exported and served under a strict Content Security Policy with no unsafe-inline and no nonces. The interesting part is not the docs, it is the build pipeline: why nonces force you off the static path, why hashes do not, why the header has to be per-page and not a site-wide union, the exact byte-level semantics of a CSP script hash, and the determinism rules a post-build hashing script has to obey so the policy keeps matching the bytes you serve. - [How to build a great dashboard](https://allenzhou.me/w/build-a-dashboard.md): A build-it-yourself how-to for a high-quality dashboard on Next.js 15.5.18, written as the companion to the docs-site guide so the two compose into one app. The URL as state contract, a static shell with a streamed per-user body, Server Action mutations with optimistic UI, real-time via SSE, and a nonce-based Content Security Policy that coexists with the docs site's hash-based one in a single middleware. - [How to build a world-class docs site](https://allenzhou.me/w/build-a-docs-site.md): A build-it-yourself how-to for a docs site that matches the highest bar shipped today, on Next.js 15.5.18. Static generation from MDX, build-time syntax highlighting, generated navigation and table of contents, an AI-readable markdown surface, a REST API reference generated from OpenAPI, and a strict Content Security Policy that keeps the site fully static by hashing inline scripts instead of using nonces. - [What a design system actually is](https://allenzhou.me/w/design-systems.md): A design system is not a component library. The component package is one layer near the top of a stack that starts with tokens and ends with a distribution mechanism. This is the full anatomy: tokens, typography, icons, components, patterns, content rules, and the governance that keeps them in sync, plus the one-way dependency rule that makes the whole thing pay off. - [The clever parts of docs and dashboards](https://allenzhou.me/w/docs-dashboard-tricks.md): Most of a docs site or a dashboard is unremarkable plumbing. The interesting parts are a set of strategies that quietly do a lot of work: prerendering a static shell and streaming the per-user holes, baking expensive renders with use cache, a strict CSP on a static site by hashing scripts, dual-theme highlighting with zero runtime JS, OpenAPI as the one source of truth, optimistic mutations, URL-as-state, virtualized tables, real-time without a socket server, and a dozen more. Plus a full section on auth and routing in a multi-tenant app: a cheap cookie gate at the edge versus real verification at render, why a redirect changes shape once the shell has flushed, authorizing at every fetch with a deduped session, and instant per-tenant landing straight from a cookie. This is the full set, with the actual code and the trade-offs. - [AI SDK Code Mode](https://allenzhou.me/w/code-mode.md): A long-form deep dive on AI SDK Code Mode: a single model turn that emits a JavaScript or TypeScript program executed in a QuickJS WASM sandbox, calling N tools concurrently with one round trip instead of N. The runtime architecture, what the model sees, the continuation replay mechanism, approvals and host interrupts, observability, and how Code Mode is wired into Ash, the filesystem-first agent framework. - [Building an evals platform](https://allenzhou.me/w/evals-platform.md): A long-form guide to building an evals platform for coding agents from scratch. The hidden hard problems (reproducibility, isolation, heterogeneity, judgment, cost), the architectural core (sandbox plus adapter plus transcript plus judge plus fingerprint), the two validation modes, the comparison primitives that make it useful, the reporting pipeline, the cost discipline, and the two-layer split between harness library and application CLI. - [Two interview problems worth practicing](https://allenzhou.me/w/interview-problems.md): A hit counter and a full-stack autocomplete. Both look small and have a lot of depth. Try them yourself, then walk through the solutions in detail. - [Building docs and dashboards on Google Cloud](https://allenzhou.me/w/gcp-cloudflare.md): A full self-host playbook for Next.js 15.5.18 on Google Cloud with Cloudflare in front, covering both a mostly-static docs surface and a mostly-dynamic dashboard surface. The shared infrastructure, the three cache tiers, the per-surface specifics, the deploy pipeline, cost modeling, observability across the seams, and the migration path to Next.js 16. - [Reading the stack off a URL](https://allenzhou.me/w/site-fingerprinting.md): Every public site leaks its framework, hosting provider, CDN, CMS, and (often) its exact version through HTML, headers, window, URL, and DNS. A walk through how v-ray turns those leaks into a fingerprint, with the full catalog of signals, provider by provider. - [Strict CSP in Next.js](https://allenzhou.me/w/strict-csp.md): What is actually in the inline scripts a Next.js page ships, why the React Server Components streaming protocol requires them to be inline, and how to make a strict Content Security Policy work without breaking the page. The hash path, the nonce path, the external path, why SRI does not solve it, why PPR and a nonce are mutually exclusive, and the per-page-hash approach a static docs site actually ships. - [Agent readiness](https://allenzhou.me/w/agent-readiness.md): Half your readers are not human anymore. What it actually takes to make a site that an LLM can parse: an llms.txt index, an llms-full.txt single-file dump, .md alternates for every post, Accept-header content negotiation, and the small handful of metadata details that make all of it discoverable. - [Docs](https://allenzhou.me/w/docs.md): A 0-to-expert tour of how Vercel does docs. Half of it is the writing discipline pulled from the internal docs handbook (planning, content types, style, rules, quality checklist, AI policy). The other half is the system that serves it: a microfrontend that stitches independent apps into one domain at the edge, a packaged docs runtime, and a Next.js 16 cache-components app that uses MDX files as routes. - [Picking a React stack](https://allenzhou.me/w/react-stack.md): Next.js, React with Vite, TanStack Start, SWR, and TanStack React Query: what each one actually does, the code that uses them, what building the Vercel dashboard or the Vercel docs would look like with each, and a field note on the data-at-the-top vs data-at-the-leaf decision that high-profile teams are actually making in 2026. - [Tests](https://allenzhou.me/w/tests.md): Property testing, simulation, the four-tier model, and mechanical structural enforcement: what tests look like at Vercel today across Ash, vercel-site, and vercel-docs, what is excellent, and where the next frontier lives. - [Dashboard](https://allenzhou.me/w/dashboard.md): A great dashboard is the human-readable view of a control plane that also has an API, a CLI, and an MCP server, and the design choices that make it good are mostly about the seams between those surfaces. - [Work at Vercel](https://allenzhou.me/w/vercel.md): Things I have shipped, launched, and written at Vercel. - [MCP vs CLI vs Plugins](https://allenzhou.me/w/mcp-vs-cli-vs-plugins.md): Three layers (protocol, execution, knowledge) and which one to ship for your tools. - [MCP servers](https://allenzhou.me/w/mcp.md): How to build incredible MCP servers, the clients that make them sing, and the contract between them. ## Backlog - [Compaction](https://allenzhou.me/w/compaction.md): Here’s how to preserve context when agent conversations get long. - [How I Use AGENTS.md](https://allenzhou.me/w/how-i-use-agents-md.md): Here’s how I use AGENTS.md to keep coding agents aligned. - [How I Use Skills](https://allenzhou.me/w/how-i-use-skills.md): Here’s how I use skills to make agents more consistent and useful. - [My Stack](https://allenzhou.me/w/my-stack.md): Here's where I'm currently most productive. - [Tool Execution](https://allenzhou.me/w/tool-execution.md): Here’s how to design reliable tool execution for agents.