Fix your Figma file before AI writes the code
HandOffLint reviews your design for layout and structure problems before you hand it off to tools like Cursor, v0, or Claude. Catch messy frames early so the code you get back is clean, responsive, and ready to ship—not a pile of fixes.
Messy designs become messy code
AI coding tools can only work with what they see. When a Figma file is disorganized, the output is hard to maintain.
Designers move fast in Figma—and that speed often leaves problems behind: layers stacked on top of each other, frames without proper containers, elements placed with fixed pixel positions, and half-finished layers buried in the file.
When you ask an AI tool to turn that file into code, it reads the pixels and layer tree as-is. Without clear structure—things like Auto Layout, consistent spacing, and named components—it guesses. Often it copies exact x/y coordinates into your CSS.
The result is brittle code: fixed-position divs that break on different screen sizes, skip accessibility basics, and ignore your design system. Developers then spend hours rewriting what should have been a straightforward handoff.
/* absolute coordinates generated by LLM */
<div className="absolute top-[142px] left-[24px] w-[280px] h-[48px] bg-indigo-600 rounded">
<span className="absolute top-[10px] left-[16px]">
Submit Action
</span>
</div>System Architecture Flow
The multi-staged pipeline designed to process Figma inputs into structured prompt injections.
Ingestion & Server Caching
The pipeline extracts the fileKey and target nodeId. Rather than re-fetching deeply nested trees across subsequent requests, it flattens nodes into Upstash Redis for O(1) property lookup across wizard steps and serverless instances.
Deterministic Analysis
Executes 8 structural TypeScript audits to test spacing alignments, contrast calculations, and Auto Layout bounds. Computes a quantitative design Readiness Score scaled on layout density profiles.
ReAct Vision Loop
A multi-step visual agent inspects the frame image. It executes zero-cost local tools to query cached properties and performs paragraph-chunk keyword RAG checks against GitHub guideline documents. Walkthrough →
1. Input Figma URL
2. Select Profile
3. Launch Vision
4. View Results
/api/agent/init
Parses Figma URL, saves mapped tree flat.
/api/agent/audit
Figma API
Subtree fetcher
GitHub Raw
Style guideline markdown
Vision Agent Evaluations
A proof-of-concept golden dataset — three mobile-app frames — measures how reliably the ReAct vision agent finds cross-modal defects today. Runs are captured once, human-reviewed, then replayed offline in CI. This is an honesty check on model behavior, not a claim that the vision agent is production-ready at scale.
vaxin ×2, Bittersweet modal
Same frame, repeated to surface variance
Mixed — strong on simple frames, weaker on complex modals
Each case pairs a Figma node tree with a rendered frame image. The capture workflow seeds the flat index, runs the vision agent ten times, applies cross-modal guardrails, and commits JSON results under evals/results/. Vitest replays those committed outputs — no live Gemini in CI.
These evals validate the measurement pipeline and show where the agent is already useful (clear typos, obvious hierarchy clashes). They do not mean the vision model is consistent enough for unattended production use across arbitrary Figma files.
Known limitations today
- Only 3 golden cases and one layout profile (mobile-app) — not representative of all handoff scenarios.
- Gemini output is non-deterministic: the Order Details Modal case reaches just 40% full-match across 10 runs, even when individual findings appear more often.
- Large or layered frames are harder — the model sometimes catches layout issues but misses subtle cross-modal text mismatches, or vice versa.
- Capture was constrained by API quota; failed runs are excluded from pass-rate math, which can overstate stability on thin successful-run samples.
Improvements needed before scale
- Expand the golden set — more frames, layout profiles, and defect types.
- Run consensus voting (e.g. require a finding in ≥6/10 runs) before surfacing it.
- Decompose large frames into regions instead of one full-frame vision pass.
- Add per-finding confidence scores and explicit “needs human review” states.
- Tighten guardrails and recalibrate when the model or prompt changes.
Locked case pass rates
Google Pixel 2 - 1
vaxin-1-4
Google Pixel 2 - 4
vaxin-20-0
Order Details Modal
bittersweet-9-153
Pass rate = share of successful runs that matched all locked expected findings. High scores on simple frames and lower scores on complex modals are both useful signals — they show where the agent is ready to assist and where human review is still required.
Deterministic Linter Rules
The 8 automated TypeScript rules used to inspect raw properties before agent execution.
Flags generic names such as "Rectangle 211". Establishes structured naming constraints.
Verifies structural auto-layout configurations to substitute coordinate maps with box models.
Strips stray, disabled draft groups so they do not bloat downstream LLM context payloads.
Validates padding, margin, and alignment coordinates against 4px and 8px grid tolerances.
Computes relative luminance of absolute visual text nodes to satisfy accessibility grades.
Validates height, width, and viewport dimensions inside vector shapes to prevent scaling clips.
Monitors component export profiles to trigger warnings on missing static resources early.
Matches nodes to external instance libraries to direct AI toward pre-built systems.
Project Architecture Specifications
The tech-stack elements compiled for this Capstone implementation.
Next.js App Router Framework
Utilizes server actions and modular API router boundaries. The application orchestrates processes across three logical routes: /api/agent/init, /api/agent/audit, and /api/agent/vision.
Vercel AI SDK & Gemini 2.5 Flash
Drives multi-turn visual agent tool actions via structured system models. The agent uses image analysis alongside local utility executions. Outputs are generated to fulfill strict Zod parsing schema expectations.
Redis Flat Index
Persists flattened Figma node maps in Upstash Redis (figma:flat:fileKey) so init, audit, and vision routes share state across serverless invocations. Falls back to in-process memory when Redis credentials are unset.
Keyword Chunk-Matching RAG
Decouples complicated database structures in favor of lightweight text manipulation. Splits downloaded markdown targets into paragraphs, maps overlaps against incoming user requests, and supplies context lists.