Tickd.ai
← The Tickd Guide

Tutorials & Guides

How to Build a Local CLI to Convert Figma SVG Exports into Clean Tailwind React Components Using Claude 3.5 Sonnet

Figma's SVG exports are notoriously cluttered. Stop cleaning them up by hand—build a quick Python CLI that uses Claude 3.5 Sonnet to transform messy vector graphics into production-ready React components styled with Tailwind CSS.

Updated 9/9/2026

The Figma SVG Export Problem

Exporting SVGs from Figma is a daily ritual for most frontend developers. Unfortunately, it is also a daily exercise in cleaning up digital landfill. Figma exports SVGs stuffed with arbitrary IDs, explicit width and height dimensions that ruin responsiveness, redundant <g> nesting, and inline styling that refuses to play nicely with your codebase.

Hand-tuning these SVGs into clean, reusable React components is tedious work. You have to remove the hardcoded dimensions, swap hex codes for Tailwind colour classes, add custom React props, and ensure the SVG is accessible.

Instead of wasting ten minutes per asset faffing about with markup, we can automate the entire process. This tutorial walks you through building a lightweight Python CLI tool that takes any exported Figma SVG and uses Claude 3.5 Sonnet to refactor it instantly into a semantic, highly customizable Tailwind CSS React component.

The Architecture of the CLI

Our CLI tool will take a raw .svg file, send its contents alongside a strict system prompt to the Anthropic API, and write the resulting TypeScript React component (.tsx) directly to your components folder.

To make this utility truly useful, we want it to:

  1. Strip fixed sizes: Replace explicit pixel dimensions with responsive Tailwind sizing classes (e.g., h-6 w-6).
  2. Clean up attributes: Convert standard HTML attributes like stroke-linecap to React camelCase (strokeLinecap).
  3. Inject dynamic props: Allow developers to pass custom className and standard SVG attributes to the finished React component.
  4. Optimise paths: Retain the actual path data whilst stripping out editor-specific junk.

Step 1: Setting Up the Environment

First, make sure you have your Anthropic API key handy. If you run into issues with your developer credentials or API access limits, you can check the troubleshooting resources on the Claude support site.

Let's set up our workspace. Create a new directory and install the necessary dependencies:

`bash mkdir figma-svg-cli cd figma-svg-cli python3 -m venv venv source venv/bin/activate pip install anthropic click `

We are using click to handle the terminal command structure, and anthropic to interface with Sonnet.

Step 2: Crafting the Transformation Prompt

Our prompt needs to be highly prescriptive. LLMs love to include helpful chatty text like "Here is your component!" which will break our CLI when we try to write the file directly to disk. We must enforce that the model returns only valid TSX code.

For a deep dive on building strict generation instructions, check out our prompt generator guide.

Create a file called prompts.py to store the system prompt:

`python SYSTEM_PROMPT = """ You are an expert frontend engineer specialising in React, TypeScript, and Tailwind CSS. Your task is to take a raw SVG string exported from Figma and transform it into a clean, reusable React component.

Adhere strictly to the following rules: 1. Output ONLY the raw TSX component code. Do not wrap it in markdown code blocks. Do not write any introduction or explanation. Begin immediately with the imports. 2. Use TypeScript. The component must accept custom props extending standard SVG attributes: interface ComponentProps extends React.SVGProps<SVGSVGElement> { className?: string }. 3. Forward ref and spread standard props onto the SVG element: {...props}. 4. Replace any hardcoded width and height attributes on the parent SVG tag with Tailwind classes (e.g., use h-6 w-6 by default or leverage dynamic className overrides). 5. Convert all dash-separated SVG attributes to React camelCase (e.g., stroke-width to strokeWidth, fill-rule to fillRule). 6. Replace absolute fill and stroke hex codes with standard Tailwind colour classes where possible, or use the dynamic currentColor value so parent containers can style the SVG icon easily. 7. Ensure the SVG is accessible by adding an appropriate aria-hidden="true" or offering an optional title prop. """ `

Step 3: Writing the CLI Script

Now, let's write our main CLI handler. Create a file called svg_to_tailwind.py. This script ticks every box on our clean-code checklist, parsing parameters and routing them securely to Anthropic's endpoints.

`python import os import sys import click from anthropic import Anthropic from prompts import SYSTEM_PROMPT

Initialize the Anthropic client # Make sure your ANTHROPIC_API_KEY environment variable is set. client = Anthropic()

@click.command() @click.argument('input_path', type=click.Path(exists=True)) @click.option('--out', '-o', default=None, help='Output path for the generated TSX component.') @click.option('--name', '-n', default=None, help='Override the React component name.') def main(input_path, out, name): """Converts raw Figma SVGs into Tailwind React components using Claude 3.5 Sonnet.""" # Derive component name from filename if not specified filename = os.path.basename(input_path) base_name = os.path.splitext(filename)[0] component_name = name or "".join(word.capitalize() for word in base_name.replace('-', '_').split('_')) # Ensure output path is set if not out: out = f"{component_name}.tsx" click.echo(f"Reading SVG: {click.style(input_path, fg='cyan')}") try: with open(input_path, 'r', encoding='utf-8') as f: svg_content = f.read() except Exception as e: click.echo(f"Error reading file: {e}", err=True) sys.exit(1) click.echo("Consulting Claude 3.5 Sonnet...") try: # Invoke the Claude API message = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=4000, temperature=0.1, system=SYSTEM_PROMPT, messages=[ { "role": "user", "content": f"Convert this SVG into a React component named {component_name}:\n\n{svg_content}" } ] ) # Extract the raw output text component_code = message.content[0].text.strip() # Just in case Claude wraps the output in backticks despite instructions if component_code.startswith("`"): lines = component_code.splitlines() if lines[0].startswith("`"): lines = lines[1:] if lines[-1].startswith("`"): lines = lines[:-1] component_code = "\n".join(lines).strip() # Write the clean React component to file with open(out, 'w', encoding='utf-8') as f: f.write(component_code) click.echo(f"Success! Generated {click.style(out, fg='green')}") except Exception as e: click.echo(f"An error occurred during generation: {e}", err=True) sys.exit(1)

if __name__ == '__main__': main() `

Step 4: Testing Your New Converter

Let’s test our tool. If you need some real, design-system-standard vector graphics to put through their paces, browse the clean layout files available on the Figma Weave platform hub.

Create a mock Figma export named icon-heart.svg in your directory:

`xml <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <g id="heart-icon"> <path id="Vector" d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" fill="#FF0000"/> </g> </svg> `

Now, run your conversion script from the terminal:

`bash export ANTHROPIC_API_KEY="your-key-here" python3 svg_to_tailwind.py icon-heart.svg `

Within seconds, the tool generates a brand-new file called IconHeart.tsx. Open it up, and you’ll find a beautifully refactored React component ready to be dropped into your codebase:

`tsx import React, { forwardRef } from 'react';

interface IconHeartProps extends React.SVGProps<SVGSVGElement> { className?: string; }

const IconHeart = forwardRef<SVGSVGElement, IconHeartProps>(( { className, ...props }, ref ) => { return ( <svg ref={ref} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className={h-6 w-6 text-red-500 ${className || ''}} aria-hidden="true" {...props} > <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" fill="currentColor" /> </svg> ); });

IconHeart.displayName = 'IconHeart';

export default IconHeart; `

Notice how Sonnet automatically mapped #FF0000 to a generic Tailwind fallback class (text-red-500) while updating the hardcoded path to use currentColor. This allows you to style your heart icon seamlessly with dynamic utility classes like hover:text-red-600 transition-colors directly on the parent component.

Now you have a fast, zero-nonsense CLI pipeline that bypasses the repetitive frontend styling grind, letting you focus on writing actual application logic.

reacttailwind-cssclaude-3-5-sonnetcli-toolfigma

Keep going

Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.