Blog

How I Built My Portfolio With Figma, Claude, and a Lot of Back-and-Forth

A designer, an AI, and a Figma file that held it all together.

Daniyal AdmaneyMarch 20268 min read
Figma canvas showing portfolio design components

The Honest Starting Point

I'm a product/UX designer. I also have a BSc in Information Systems, and my first couple of jobs had me doing front-end development alongside the design work. So I'm not starting from zero. I know how the web works. I understand what TypeScript is complaining about. I can open VS Code, read a component, and figure out why something looks wrong.

What I hadn't done in a while was write a full codebase from scratch. The understanding was there, the muscle memory wasn't. And Claude Code wrote the vast majority of the actual code in this project. That's just true. But the technical foundation meant I wasn't flying blind. When something was off, I could open inspect element, track down the problem, and either fix it myself or explain it precisely enough that Claude Code could fix it properly.

That combination (Claude Code writing the code, me understanding it well enough to verify and correct it) is actually what made this work. Handing off to an AI and checking nothing isn't a workflow, it's a gamble.

I also refused to use a template.

Portfolio templates are fine. They're just not mine. I had a certain design vision for the portoflio, and I didn't want to use Frameror Webflow anymnore. I had always wanted to do this - have my portfolio self hosted, properly built out.

So I designed the whole thing in Figma first. Then I figured out how to actually build it.

The Stack I Landed On

After some research and a few conversations with Claude about what made sense for a portfolio like this, I landed on:

  • FrameworkNext.js with TypeScript
  • StylesTailwind CSS v4 (with design tokens defined in globals.css via @theme)
  • AnimationFramer Motion for animations
  • TypographySelf-hosted fonts because I needed full control over variable font axes

The last one matters more than it sounds. I'd chosen Fraunces as a display typeface specifically for its WONK axis, a variation axis that gives the characters a hand-drawn, slightly quirky quality. Google Fonts strips custom axes. next/font does too. The only way to get the letterforms I'd designed around was to host the TTF files myself and write the @font-face rules manually.

That detail took a whole debugging session to figure out. But when it finally worked, the j in the intro sectio looked exactly like it was supposed to. Worth it.

Animation showing the Fraunces WONK variable font axis in action
The WONK axis in action. This is why you self-host your fonts.

The other fonts: Neue Haas Grotesk Display Pro for body and UI text, Martian Mono for labels, metadata, and anything that needed to feel precise and technical.

VS Code with the portfolio project open — file tree on the left, component on the right
The actual project. File tree on the left, component open on the right.

The Workflow: Figma + Claude Code + Claude Chat

Here's how it actually worked, because I think this is the interesting part.

I used two modes of Claude throughout this project:

Claude chat for planning, design decisions, reading the Figma file via MCP, generating component prompts, and reviewing what was being built. This is where I'd come to think out loud, get a second opinion on a layout decision, or ask "what the hell is happening with this font."

Claude Code is the CLI tool that runs in your project directory. This is where the actual code got written. I'd paste prompts into it, Claude would read my Figma file directly via MCP, and then write the component. I'd check localhost:3000 (eventually hosted via Vercel), come back to chat, iterate, generate the next prompt, paste it into Code, repeat.

Source of truthFigmadesign file + MCP
Think / planClaude Chatdecisions + prompts
BuildClaude Codewrites the code

The rhythm was: Claude chat for thinking, Claude Code for building. The Figma MCP connected both of them to the source of truth.

How the Figma MCP Actually Changed Things

This is the part that stuck out to me.

Without the MCP, you'd describe your design to Claude and it would approximate. With the MCP, Claude can read the actual Figma file: the exact node, the exact values, the exact spacing, the component variants, the color variables. For every component I built, I'd share the Figma node URL and Claude could inspect it directly.

This meant I wasn't translating between design and code. I was just pointing at the design and saying build that.

It wasn't perfect. Claude can read the design data but not always infer intent perfectly. Sometimes a layout decision that's obvious when you're looking at the Figma file needs context about why it's that way. So there was still a real back-and-forth. But it removed an enormous amount of friction from the "describe what you see" phase of the process.

Building Component by Component

The approach was simple: one component at a time, never skip ahead.

Figma canvas showing the full portfolio design with all component breakpoints laid out
The Figma file before a single line of code was written. Every breakpoint, every component variant.

I built in this order:

  1. Design tokens (colors, type scale, spacing) in globals.css
  2. Navbar: desktop right-aligned layout, then mobile hamburger overlay
  3. HeroSection: two columns, decorative arrow SVG, CTA
  4. IntroductionSection: the chapter index with a quote block on the left
  5. PageBreak: the simple three-dot divider between chapters
  6. ColumnHeader: the chapter header with logo, eyebrow, title, and role/location
  7. PictureFrame: polaroid-style photo cards with tape effects
  8. ProjectCard: the work preview with browser bar mockup
  9. ChapterSection: the main container composing all of the above
  10. ChapterNav: the floating sidebar navigation widget

Every component was built for four breakpoints: 390px, 768px, 1280px, and 1440px. That's four Figma frames per component, four sets of values to read and translate. The responsiveness wasn't an afterthought. It was baked into each prompt from the start.

The ChapterNav Story

This one deserves its own paragraph because it's my favourite part of the site.

I wanted a floating navigation widget on the left side of the screen that would track which chapter you were currently reading and highlight it. Minimal navigation, that also ties in with the overall story arc.

I hadn't designed it in Figma. I just had the idea while building and wanted to think it through before committing.

So I asked Claude chat to prototype two versions: one with dots only (labels on hover), one with always-visible labels beside each dot. Two interactive widgets, side by side, right in the chat, so I could compare them before touching any code. I could click through them, try the interactions, get a feel for it.

Two ChapterNav prototype variants side by side in Claude chat
Two interactive prototypes, built and compared inside Claude chat before a single component was written.

I picked the minimal dots version. Then asked for a third iteration: dots only, but labels slide in from the right on hover instead of appearing below. That became the design. Then I got the Claude Code prompt to actually build it.

The whole process (idea, comparison, iteration, decision, code) happened in a single conversation without opening Figma or writing a line of code myself. That felt genuinely new.

The implementation used IntersectionObserver to detect which chapter was in view, Framer Motion to animate the active green line growing down toward the current dot, and slide-in labels that appear on hover. Hidden on mobile, obviously. There's no room for it (but i might have an update on that in the works).

The ContiConnect Case Study Page

After the homepage was working, I moved to the first case study page. the one for ContiConnect, a fleet management portal I worked on.

This was more complex. A sticky sidebar navigation. Nine content sections. A full hero split with metadata. Study metrics cards. Before/after comparison layouts. Four breakpoints for everything, again.

I designed all of it in Figma first: every breakpoint, every section, every component variant. Then I wrote out a complete CLAUDE.md-style build document specifying the file structure, component names, Figma node IDs for every component at every breakpoint, and the layout rules for the sticky sidebar system.

That document went into Claude Code as a master brief. Then we built section by section.

What Surprised Me

Claude Code gets things wrong, and you need to know enough to catch it

This is probably the most important thing I'd want another designer to hear. There were sessions where Claude Code produced something that compiled, ran, and vaguely resembled the Figma design but was wrong in ways that mattered. Wrong spacing. Wrong font weight. A layout that broke at 768px in a subtle way. I'd open inspect element, track down what was actually happening, and either fix it directly in VS Code myself or diagnose it precisely enough that the next prompt actually resolved it rather than creating a new problem. The technical background wasn't decorative. It was load-bearing.

How much I still had to think

Claude can read a Figma file and write a component, but it can't feel your design. I still had to decide what mattered, catch things that were aesthetically wrong even when technically correct, and push back when the output didn't match the intent. The judgment calls didn't go away. They just shifted.

How useful prototyping in chat actually is

Before this project I'd never thought to build interactive prototypes directly in Claude chat to make design decisions. Now I'm insanely curious about the possibilites.

Font axes are apparently a whole thing

I spent a surprising amount of time on Fraunces's WONK axis. No regrets.

Context is everything with Claude Code

Vague prompts got vague components. When I'd come to chat first, think through the design, read the Figma node, and write a detailed prompt, the output was close to the Figma spec on the first try. The quality of what you get is almost entirely determined by the quality of what you put in.

What I'd Do Differently

I'd write the CLAUDE.md file from the start. Claude Code has a feature where you can put persistent instructions in a CLAUDE.md file in your project root: coding conventions, design tokens, rules like "never use hardcoded hex values." I only discovered this partway through. Components built before it were less consistent than ones after.

I'd also be less precious about starting the case study content early. I kept telling myself I'd write it later, when the design was more stable. But the writing shapes the design. Once I had real copy in the case study sections, I made better decisions about spacing and layout. Do it earlier.

Portfolio shown at desktop, tablet, and mobile breakpoints
Desktop, tablet, mobile. Four breakpoints designed, four breakpoints built.

The Actual Takeaway

A designer who hadn't written a full codebase in years shipped a production Next.js portfolio: four responsive breakpoints, custom variable fonts, Framer Motion animations, a handcrafted case study system, in a couple weeks of evenings.

Claude Code wrote most of the code. That's true and I'm not going to pretend otherwise. But I understood what it was writing. I caught its mistakes. I fixed things directly when it got it wrong. I made every design and architectural decision. I wrote the Figma design it was building from.

The honest version of this isn't "AI built my portfolio." It's "I built my portfolio, and AI handled the parts that would have taken me ten times longer to write from scratch."

That's a different claim, and a more interesting one. Because it means the barrier isn't "can you code." It's "do you understand enough to be in the loop." That understanding and design instinct, coupled with technical literacy, the ability to read inspect element and know what you're looking at. That's what makes the collaboration actually work. I would still be vary of using for actual product development, what with the security issues enall, but for a static website? Lezzgooo. I'm still exploring. Right now I was desiginig within restraints as well and this is just v1. Stay tuned ;)

Claude handled the parts I was slow at. I handled the parts Claude couldn't feel.

It worked.