Designing with AI: My Figma-to-Code Workflow

AI is changing the way experiences are designed. There is a sea change underway, and the old ways of doing things (I'm looking at you Double Diamond) are too slow and rigid for AI-native workflows. For me, AI is obviously a powerful tool that can speed things up - especially at first. But there are limits. I still rely on Figma to design complex interfaces and establish a real design system.

If you find yourself in a situation where the AI is repeatedly failing to create a good design, don't be afraid to mock it up in Figma. It's not a step backward, it's the step that makes the AI actually useful.

Below are a few tips that have helped me.

Auto Layout in Figma is your new best friend

When you hand a design to an AI coding tool, it needs to understand the structure, not just the pixels. Auto Layout in Figma encodes that structure directly: the spacing, padding, alignment, and how elements relate to each other. Without it, you're giving the AI a flat image and hoping it can reverse-engineer your intent. With it, you're giving it a blueprint.

This matters even more when you use "Copy CSS (all layers)" — which I'll get to — because Auto Layout produces clean, predictable CSS that the AI can actually work with.

Create components and Variants with clear naming conventions

Convert designs to components with names based on their function, not just their form. Don't call it "Card v2 final." Call it "ProjectCard" or "InterviewModeSelector."

Why? Because when you and the AI share a common vocabulary, the conversational design process has less friction with fewer mistakes. You can say "build me a new card that follows the same pattern as ProjectCard" and the AI knows exactly what you're referencing. Clear names close the gap between what you picture and what gets built.

Variants are equally important. If your component has multiple states (active, disabled, loading), defining those as Figma Variants gives the AI a complete picture of the component's behavior, not just its default state.

Export a PNG and also paste the CSS

Right-click your component in Figma, then: Copy/Paste as → Copy as code → Copy CSS (all layers).

Upload the PNG and paste the CSS into your AI coding tool. The image shows the AI what the component should look like. The CSS tells it exactly how to build it. The flex properties, the border radii, the font weights, the spacing, alignment, etc. The combination of these two paints a complete picture for the AI to make what you want, correctly, the first time.

Neither one alone is enough. The image without CSS leads to guesswork on spacing and layout. The CSS without the image loses visual context like gradients, shadows, and the overall feel. Together, they're the fastest path from design to working code I've found.

Create a component library backed by a manifest file

I now maintain a “components.yaml” file alongside my component library. It acts as a blueprint manifest and provides a curated registry of every key component in the app, where it lives, what it does, and how it fits into the system.

Here's a simplified example:

yaml

components:
  - id: project-card
    name: Project Card
    path: src/components/projects/ProjectCard.tsx
    description: "Grid card for the projects listing page with hero image, title overlay, and inline CRUD menu."
    status: implemented
    figma: "https://www.figma.com/file/..."

  - id: mode-selector
    name: Mode Selector
    path: src/components/project-view/ModeSelector.tsx
    description: "Three-state pill toggle for switching between Build, Gallery, and Read modes."
    status: implemented
    variants:
      - Build
      - Gallery
      - Read

    

Why this matters

Without something like this, every time you ask the AI to build a new component, it starts from scratch. It has no context about your existing design patterns. It doesn't know your naming conventions, your file structure, or how similar components are already built. The result is inconsistency. One component uses flex-col gap-4, the next uses grid with margin-top, and now you're spending time fixing style drift instead of building features.

The manifest solves this by giving the AI a map. When I say "build a new card component for People," the AI reads the manifest, sees how ProjectCard is structured and described, and builds the new component in the same style. Same naming pattern. Same file location conventions. Same design tokens.

What to include

Keep the manifest curated, not exhaustive. You don't need to register every tiny utility or helper. Focus on domain-level components (i.e. the things that represent real features in your app). For each one, I include:

  • id — a kebab-case identifier

  • name — human-readable name

  • path — where the file lives

  • description — what it does and why it exists (this is the most important field — it's what the AI actually reads to understand your intent)

  • status — implemented, planned, or deprecated

  • figma — optional link back to the source design

Keeping it accurate

A manifest is only useful if it's accurate. I built a simple drift detection script that runs periodically to catch two problems:

  1. Forward drift — new components get added to the codebase but never registered in the manifest

  2. Reverse drift — entries in the manifest point to files that no longer exist

This takes maybe 30 lines of bash and saves you from the worst outcome: an AI confidently building from a stale blueprint.

➡️ You can see a full example of the manifest at github.com/iwyosnick/vibe-coding-workflows.

The takeaway

AI is the fastest builder I've ever worked with, but it still needs blueprints. The more structure you give it the less time you spend correcting it and the more time you spend building. This isn't about AI replacing the design process. It's about giving AI the exact blueprints it needs to build what you pictured.

Next
Next

A One-Command Health Check Workflow for Non-Coders Building with AI