Tooling & Lab
Anvilry
Portfolio with four switchable views and a read-only MCP server over one MDX source
3 min read · 665 words
Anvilry is the engineering portfolio of Sairam Ugge: a Next.js 16 site that lets a recruiter explore the same work as a static page, an AI chat, a 3D graph or a terminal, and lets AI agents read it as structured data. It is a personal site with a single author and 0 GitHub stars; the MIT licence covers the code only, and content/ and the profile data are all rights reserved.
- Classic view — a static (SSG) page that crawlers and first paint always receive; the other views swap in client-side.
- Chat view — a streaming concierge on AWS Bedrock that answers in the owner's first person from an in-context corpus, with a visible notice that the answers are AI-generated, and optional browser voice.
- FAQ cache — repeated first-turn questions are served from Upstash Redis with no model call, each entry tagged with the deployment that wrote it.
- Play view — a React Three Fiber build graph whose nodes open project and work cards, with a DOM index as the fallback.
- Developer view — a keyboard-native terminal with 32 commands (28 visible, 4 hidden), including
integrity, which prints the claims ledger. - Agent surface — a read-only MCP server with 10 tools, plus
llms.txt,llms-full.txt,resume.jsonand RSS. - Consistency gates — a citation check over the codebase index, a hash-chained ledger of the headline metrics, and a first-load bundle budget, all run in CI.
At v3.16.0 (2026-10-22): 876 commits on
main(28 of them Dependabot's) with one human maintainer, 34 GitHub releases and 0 stars; CI was green onmainthat day; no CI job was a required check at the cut, butLint · Type-check · TestandE2E (Playwright)have been since that evening; the claims ledger held two sealed entries, the latest from 2026-10-21.
Architecture
Anvilry is one Next.js 16.3.5 App Router app (cacheComponents: true, React 19.3.0, Tailwind v4) on Vercel. Velite validates the MDX in content/ into typed collections read through src/lib/content.ts, and derivation modules turn it into the Play graph, the chat corpus, the decisions ledger, the MCP results and llms.txt.
Views are a six-member View union in a module-level external store; the server and the first client render always return Classic. The chat route applies a per-IP Upstash limit (8 requests a minute per route class), then the FAQ cache, then src/lib/llm.ts. Cost guards fail open when Upstash is absent.
Vitest runs inside pnpm build. The citation check, claims seal and bundle budget run in CI, so they fail a pull request, never a deploy. The budget caps first-load JavaScript at 988,000 B per route and keeps three.js out of the first-load chunks. The claims ledger shows a claim was not edited since sealing, not that it was accurate.
How It Works
- Author — MDX in
content/;pnpm buildrunsvelite --clean && vitest run && next build && pagefind, so a schema error or failing test stops it. - Derive — the graph, corpus, MCP tools,
llms.txtand decisions ledger read the same collections; Vitest bijection checks fail the build on any node, entry or tool without a source. - Ask — a chat request passes the per-IP limiter and, for a first-turn question, the FAQ cache; a miss streams from Bedrock with the corpus in a one-hour cached system block.
- Fall back — by default Sonnet 4.6, then Haiku 4.5 (opt-in flags can put Sonnet 5 or 5.5 in front, and Opus behind the primary), 15 s to response headers per try. The chain advances only before the first answer byte.
- Render — the client resolves
[[card:work:slug]]tokens against build-time content and drops unknown slugs; answers render throughreact-markdownwithrehype-sanitize. - Release — work lands on
develop(Preview), reachesmain(Production) by merge-commit PR, and each version bump is tagged and released. Tagging lapsed after v2.1.1 (2026-06-18); ten releases, v3.0.0 to v3.6.0, were backfilled on 2026-09-17. - Operate — five Vercel crons fail closed without
CRON_SECRET. DEPLOY.md still lists the weekly eval cron as unfixed at v3.15.0: checked on 2026-10-01, its requests were refused by Vercel deployment protection, so its pass-rate tile records 0 of 12.