How this site shipped with AI
Directed AI build of this portfolio — workflow, Cursor spend, and token receipts refreshed at build time from local logs.
Thanks for reading. I built this site as a recruiter-facing hub — work, CV, lab, contact — with Cursor Agent on Pro ($20/mo) doing most of the implementation while I set direction and taste. The numbers are live from local Cursor logs, not hand-edited.
Live receipts · Cursor Pro · refreshed at build
Built with Cursor Agent on Pro —87 sessions,~272 typed turns,~123 browser picks,~4,609 tool calls,~65 files /~9,569 lines in src/.
Mostly steered via typed prompts; browser picks were secondary.
How I direct AI
| Me · Product owner | Agent · Strong implementer |
|---|---|
| Intent, taste, and accept/reject — not vibe coding | Executes under constraints — not a co-author of intent |
| Audience, scope, and stop rules | Scaffold and implementation under the brief |
| Kit fidelity and release readiness | Local edits from pointed browser picks |
| Loop: brief → build → review → correct | Runs each pass inside the brief |
| Ship gates: adversarial review + fail-fast UI | Surfaces kit mismatches before release |
Loop
Brief
Decide what the site must do for recruiters before any UI
whya vague brief lets the agent invent work you never asked for
Build
Lock Astro + a living design kit first — the kit is the shared visual language the agent must copy, then fill pages from that frame
whywithout a kit, the agent invents a new look each pass and the site drifts
Review
Read the result as a recruiter and as a senior engineer — against the kit
whycatch taste and fidelity issues before they pile up
Correct
Click the exact UI problem in the browser and fix only that
whysmall, pointed fixes beat vague “redesign this” prompts
Cursor usage
| Sessions | Est. API spend | Tokens (total / fresh) |
|---|---|---|
| 87 | $120.34 | 138,251,159 / 12,015,540 |
I build on Cursor Pro. The $ figure is Cursor’s usage export priced at API rates for conversations in this project — useful for volume, not my Pro subscription invoice. Per-conversation Cursor export stores spend only; tokens are prorated from each calendar day’s machine totals by spend share.
Agent tool mix
Stack
| workbench | Cursor Agent (Pro) |
|---|---|
| framework | Astro 7 (static) |
| content | Content collections + MDX |
| icons | astro-icon + Lucide / Simple Icons |
| design | Signal Map kit — light B&W, IBM Plex Sans + Mono |
| host | Vercel |
| domain | hoanluu.dev |
| src/ | ~65 files / ~9,569 lines (at last receipts refresh) |
Milestone snapshots
Frozen totals at major updates (not every build). Delta is vs the previous milestone.
| When | Milestone | Est. $ | Tokens | Δ est. $ | Δ tokens |
|---|---|---|---|---|---|
| Initial ship — blog + live receiptsFirst public receipts + milestone history | $75.77 | 68,388,104 | — | — | |
| System Map hover + messagingVerified hover copy; Kafka/BullMQ messaging; AI personal workflow; ops stack | $111.95 | 121,071,105 | +$36.18 | +52,683,001 | |
| Polish About + blog receipts | $120.34 | 138,251,159 | +$8.39 | +17,180,054 |
What I am not claiming
- I did not type every line by hand. I directed product and taste; the agent wrote and rewrote most of the surface.
- Design was not one-shot. The Signal Map kit and homepage went through many visual revisions.
- I am on Cursor Pro. The dollar figure is an API-priced estimate from Cursor’s usage export (what that volume would cost on usage billing) — not my Pro subscription invoice.
- Cursor tokens for a conversation are prorated from day totals by spend share (the per-chat export stores dollars more cleanly than tokens).
- Live totals refresh on
npm run receipts/prebuild. Major ships freeze a row vianpm run receipts:snap -- "label".