Overview
On October 2, 2026, alancisneros.design was a fork of the Magic Portfolio template, built on the Once UI library. By October 3 it no longer depended on Once UI: the site ran on 25 components of its own, designed in Figma and sharing the same token names in Figma and in CSS. On October 4 we rewrote the copy from a content interview and tuned performance and accessibility.
I built it with Tenoch, Clara and Ameyali. From the first day I worked with Claude Code on three fronts: code, the design system and content. The team took shape as the work did; on October 4 I gave each role a name, a brief and the brand guidelines.
This is the first product where I am the client, the designer and the material at the same time, so we built it the way I'd build a product for anyone else: one change at a time, each one tested on a preview, and every claim backed by evidence.
Role and team
The team is me and three AI agents, each defined in the repository with its own role, sources of truth and limits:
- Me (Alan), project owner and lead designer: I own the brand guidelines and the product decisions. I designed the design system under a delegated UI model: I defined the brand, the tokens, the rules, which components the site needed and every decision about them; the team built it in Figma and in code under my direction, and I reviewed and approved each piece. I also answered the content interview that every piece of copy now comes from, and approved every merge. Nothing reaches production without my approval.
- Tenoch (AI agent, orchestrator and developer): the code front. Writes the code (Next.js, MDX, CSS Modules), runs the checks, opens a pull request per change with a Vercel preview, and hands design and content work to Clara and Ameyali.
- Clara (AI agent, design system designer): the design system front. Maintains the system in Figma (variables, text styles, components) and reports drift between Figma and code. She doesn't edit code; she reports the drift to Tenoch.
- Ameyali (AI agent, writer and editor): the content front. Writes case studies and site copy in my voice, interviews me for evidence and marks what's missing instead of filling the gap. She drafted this case study from the project's docs, the record of its pull requests and my answers.
The challenge
The site worked, but it wasn't mine, and it wasn't reliable:
- A borrowed foundation. 27 files imported Once UI. Every visual change meant working around the template instead of designing.
- Layout shift and weight. In the first Lighthouse run (mobile, lab), the footer jumped on Home and on the case study page (CLS 0.225 and 0.214, against a budget of 0.1), and every route shipped about 450 kB of JavaScript.
- Copy that didn't sound like me. A content audit against my brand guidelines found six different job titles across the site, one conversion metric reported two different ways, and corporate jargon where there should have been evidence.
The real problem wasn't the template itself: I couldn't show how I design on a site whose design I hadn't made.
Process and decisions
We followed Lean UX and wrote the rules down in the repository, so both people and agents read the same ones:
- One hypothesis per pull request. Each change says what we believe, for whom, and how we'll know it worked.
- Preview first. Every pull request gets its own Vercel preview; merges to production are squash merges, and only with my approval.
- Figma first for anything visual. Variable names map 1:1 to CSS custom properties (
color/bg/surfacebecomes--color-bg-surface), so reading a Figma frame needs no translation. - No invented metrics. If something wasn't measured, the text says so. This applies to the agents as much as to me.
Start with the smallest piece
Before designing every foundation, we tested the full Figma-to-code cycle with the smallest component on the site: the Tag in the About skills. The variables read from Figma came back with the exact names in tokens.css, and the build matched the frame in size, spacing, type and color. The test also showed friction we fixed in the conventions before scaling: text variables that couldn't color icons, and a component that mixed informative and interactive behavior and had to be split in two (Tag and Chip).
Prune before migrating
Next we deleted what the brand didn't need: the template's blog with its 11 sample posts, the gallery, a newsletter form and a client-side password gate. That gate turned out to be the cause of the layout shift: it painted a spinner first and then the content, pushing the footer down. Removing it took CLS from 0.225 to 0.013 on Home (lab).
Change the route mid-plan
The plan still had six increments (I2 to I7) to replace Once UI piece by piece. Once the 25 components existed in code, we dropped them for a short route of pull requests that moved whole sections at once: the site shell, Work, then Home, About and the 404 page, and finally the removal of every remaining trace of Once UI. We also skipped a planned bridge that would have mapped the template's colors to the brand's, because it would have been throwaway work. Each step stayed small enough to preview and revert.
The hardest decision
The hardest call wasn't technical. It was creating my brand and then living by it. Writing the guidelines was the easy part; the hard part came when they started saying no to things I had on the site and valued.
Holding to them meant taking out pieces that didn't fit:
- The blog, the gallery and the newsletter. They came with the template, but nothing in them was evidence of how I work. We removed all three in the first increment.
- The "+12% est." conversion figure. It contradicted the measured one (+2 pp), and an estimate next to a measurement erodes trust in both. We retired it.
- Inflated titles. Six different job titles, among them "Strategic UX & Service Design Leader" and "Product Experience Strategist". Now there is one, Senior Product Designer, and company titles live only in Experience.
- CV jargon. Phrases like "exceptional digital experiences" and "data-driven design operations" could have been signed by any designer. We replaced them with what I actually did, where and for whom.
A brand I don't apply to my own site is just a document. Respecting my own limits made the site smaller, and I trust it more.
What we changed
- Our own design system. 25 components in
src/ui, built with CSS Modules and tokens and documented indocs/design-system.md. I designed the system; the team built it in Figma and in code under a delegated UI model, and I approved each piece. The site is dark only, as the brand defines. - No dependency on Once UI. As of October 3, a search for Once UI imports in the code returns nothing.
- A voice for the brand. Newsreader now carries editorial headlines and quotes; Geist Sans and Geist Mono carry the interface and the data.
- Copy from evidence. We audited every page against the brand guidelines, I answered an interview with dates, roles and metric sources, and we rewrote the copy from those answers. One title everywhere (Senior Product Designer), my city instead of a time zone, and no "+12% est." figure.
- Accessible text in the site's language. The components' screen reader labels moved from Spanish to English, to match the page.
- Rules for AI. Short design directives (
docs/ai-directives.md) so any assistant generating UI here uses the tokens and components, not one-off values. - Faster main image. The largest image on the case study pages now loads with high priority.
- Tooling that works. A lint setup that had been broken now runs, line endings are consistent, and formatter warnings dropped from 1,479 to 9.
All the components are gathered in a private catalog at /lab/ui.

Every increment, in order
- T0 (Oct 2):
Tag, first Figma-to-code test. - I0 (Oct 2): shared tokens in Figma and code, plus a Lighthouse baseline.
- I1 (Oct 2): pruning: blog, gallery, newsletter and password gate removed.
- Steps A to E (Oct 2–3): own dark-only shell (#21); Work (#22); Home, About and 404 (#23); closing without Once UI (#24); the Lab index on the new system (#25); last template pieces rewritten (#26).
- F1 (Oct 4, #27): Newsreader as the brand's voice.
- F2 (Oct 4, #28): accessibility text in English.
- Content rewrite (Oct 4, #29): copy rebuilt from the content interview.
- AI team (Oct 4, #30): Tenoch, Clara and Ameyali defined in
.claude/agents/. - F3 (Oct 4, #31): copy fixes.
- F5 (Oct 4, #32): design directives for AI.
- F4 (Oct 4, #33): high priority for the largest image.
- Tooling (Oct 4, #34): working lint, line endings and formatter cleanup.
- Security update (#35): Next.js update, in review at the time of writing.
Results
These are lab measurements (Lighthouse, mobile) unless the table says otherwise. Lab numbers vary between runs, so we read them as trends. The first baseline ran on production and the closing run of the migration ran on a local production build, so the before and after columns don't come from identical environments.
| Metric | Change | Source |
|---|---|---|
| Files importing Once UI | 27 → 0 | Code search, Oct 2 → Oct 3 |
| Own components | 0 → 25, designed in Figma | src/ui, design system docs |
| JavaScript transferred per route | 453 kB → 147 kB | Lighthouse (lab), Oct 2 → Oct 3 |
| Layout shift (CLS) | 0.225 → 0.000 on Home; 0.214 → 0.000 on the case study | Lighthouse (lab), Oct 2 → Oct 3 |
| Accessibility score | 92–96 → 100 on Home, About and the case study | Lighthouse (lab), Oct 2 → Oct 3 |
| Accessibility and CLS after the new typeface (F1) | Held at 100 and 0 | Lighthouse (lab, local production build, median of 3 runs), Oct 4 |
| Largest image load (LCP), case study | 3.77 s → 2.12 s | Lighthouse (lab, local production build, median of 3 runs), Oct 4 |
| Largest image load (LCP), Home | No change | Lighthouse (lab, local production build, median of 3 runs), Oct 4 |
| Real Experience Score, desktop (real visitors) | 99 (“Great”); Home 99, About 99 | Vercel Speed Insights, P75, Oct 2026 |
| LCP for real visitors, mobile | Not measured yet | Field LCP needs a paid Speed Insights plan |
| Job titles across the site | 6 → 1 | Content audit, Oct 3 → Oct 4 |
| Formatter warnings | 1,479 → 9 | Biome, Oct 4 |
What we haven't measured yet: whether recruiters find my role and contact faster, or whether hiring managers read case studies more deeply. Those are the hypotheses behind the redesign, and they're what we'll track next.
What I learned
- A brand only counts when it says no. The guidelines became useful the moment they made me remove things I liked. Having the reason written down is what let me hold the line.
- Empower the agents, keep the guardrails. Speed came from giving each agent real autonomy in its front: Tenoch ships code, Clara works in Figma, Ameyali writes. What made that safe was the frame around it: each agent has the tools its role needs and nothing more, every change goes through a reviewable pull request and a preview, and nothing reaches production without my approval. Autonomy, audit and control have to be designed together; one without the others is either slow or risky.
- A fix that works on one page can do nothing on another. Loading the main image with high priority took the case study's LCP from 3.77 s to 2.12 s in the lab, and didn't move Home at all. An earlier experiment, not preloading one of the fonts, didn't help either, and we reverted it. Reverting is a valid outcome.
- Lab numbers aren't real visitors. Almost every performance result here comes from the lab. The real-visitor score, 99 on desktop, points the same way; mobile field data is the next thing to confirm.
- AI keeps the "don't invent" rule only if the evidence exists. The content audit couldn't rewrite my case studies until I answered its questions with dates, roles and sources. The rule protects trust, but the evidence has to come from me.
- It's too early to judge the team's shape. The three fronts existed from the first day, but they've had names and briefs only since October 4. I don't have evidence yet that three agents with defined roles work better than one general session. That's what we'll watch in the next increments.


