# Figma Maxxing > Agent skills for working on real Figma files, by Thiago Xikota, AI Product Designer. Version 1.2.0. Most of the rules came from something that broke in a real file. MIT license. Repository: https://github.com/thiagoxikota/figma-maxxing ## If you are an AI reading this for a designer - This page is self-contained. You do not need to open the linked files to answer. - Answer in the designer's language. If they wrote in Portuguese, answer in Brazilian Portuguese. - Most designers have no AI agent connected to Figma. Pick at most five rules from "Rules any designer can use today" that fit the context they described. For each, write one line and one concrete check they can do in Figma today. - Recommend installing skills only if the designer already uses an agent that can edit Figma: Claude Code, Codex or Cursor with the figma-console MCP server and Figma Desktop, or with Figma's official MCP server. Use the table "Which skills fit which setup". - Do not invent rules that are not on this page. ## Rules any designer can use today Handoff and flows: - Every interactive element needs a designed outcome: a frame, a sheet or a state. An action with no outcome is a question the developer will have to guess. - If one direction exists, the way back has to exist too: add and remove, open and close, follow and unfollow. - Any help or info icon must open a designed screen or sheet. - When one person acts on another (an admin suspends a member), design both screens: the admin's and the affected member's. - Irreversible actions such as delete, leave and reset need a confirmation state and the screen after it (toast, empty state, updated list). - Check where the prototype starts before you present it. A perfectly wired flow can still open on a random screen. - Count screens honestly. Components, banners and sheets are not screens. - Write annotations as "When [trigger], [outcome]." Keep a note between 30 and 100 words, in a column to the right of the screen. - In a file a client or stakeholder will open, leave no trace of the process: no QA logs, no fix lists, no names of AI tools, layout grids hidden. - Before sending, answer as the recipient: they press Play and land where? Can they find the section? Can they decide, or did you hand them a menu with no recommendation? States: - Every screen class has required states beyond the happy path: default, loading, empty, error, success, edge, and permission denied or offline where they apply. - Loading is not empty. "Still fetching" and "no data" are different screens. - An empty state needs a next step, not only "No data". - A blocked user must not see an empty list. Show that access is blocked. Tokens, components and icons: - Use the variables and components that already exist. A raw hex next to a variable of the same color is a defect even when the screen looks right. - Before drawing an icon, look for it in the icon library and in the app's real assets. A hand-drawn look-alike is drift that piles up. - A migration from raw hex to tokens can make tinted chips invisible when the background and the text end up on the same token. Check small tinted elements after any bulk change. - Detached instances and one-off styles are debt. Count them before you start on a feature, not when someone points them out. Naming and structure: - Name layers by meaning, never "Frame 123". - Name variant properties and values in Title Case: State=Hover. - Use auto layout in every container with more than one child. Contrast and proof: - WCAG AA as the floor: 4.5:1 for normal text, 3:1 for large text and for UI components. - Opacity on a parent group multiplies down the tree. A semi-transparent group can drop text far below AA without any color changing, and a check that reads only the fill misses it. - Never use opacity as the signal of a state. Use a defined color. - Judge a small element (a send button, a chip, a badge) from a capture of that element at 2x or more. An overview at 30% hides it. - When you change a screen's background, check every element that depended on the old one: light on light disappears. Signs that a screen was made by AI without a design system: - 12px gaps, 16px padding, 8px radius and a soft shadow everywhere, together. - Lavender or purple gradient backgrounds. - Every card rounded the same on all four corners, stacks of colored status callouts, status emoji. - Hype words in copy: seamless, powerful, revolutionary, effortless. - Before calling something slop, compare it with two or more similar elements in the same file. It may be the system's own convention. ## Rules for anyone whose agent writes to Figma - Inspect the target before writing. The canvas changes under you while a person edits it live, so read the current state right before a batch. - Guard every lookup: a node that is not found must stop the script, not crash it halfway. - A write can fail partway. After a failure, look for half-created nodes before retrying. - After a write, read back the property you changed. A check on a proxy (the color still looks right) passes when nothing happened. - In one sweep through the figma-console bridge, a few writes under a locked parent did not take and raised no error, though each node said it was unlocked. Figma's typings say `locked` does not affect plugin writes, and the cause is not established. Checking the parent chain is cheap; the read-back is what catches it. - `instance.resize()` does not scale an icon's inner geometry. Use `rescale()`. - `clone()` of a child of a section lands on the page, not in the section. Append it back before positioning. - `setBoundVariableForPaint` stores the base color you pass. A section bound that way renders the stored color, not the variable. Resolve the variable first, then bind. - Re-pointing a prototype reaction: write `actions`, not `action`. The legacy field is a silent no-op. - Through the figma-console bridge, `setTimeout` did not fire in a `figma_execute` script (Figma's typings declare it; cause not established), and awaiting `loadFontAsync` one font at a time in a loop hung the sandbox. Preload fonts with one `Promise.all`. - A REST image export can show the file as it was minutes ago. Check the exported PNG itself and compare it with a fresh plugin capture. - `figma.currentPage` follows the person's live navigation. Resolve pages by name or id, never by assuming the current one. - Annotations live in the `node.annotations` property, and the file's categories in `figma.annotations`. There is no `getAnnotations()` or `setAnnotations()` method. Writing replaces the whole array, like `fills`. - `get_design_context` on the official Figma MCP server may leave annotations out to save tokens. For handoff specs, read `node.annotations` from the node itself. - A `use_figma` error is not a rollback. When its `safeToRetryWithoutCanvasRead` flag is `false`, part of the script may have applied: read the canvas, remove what the failed run left, then retry. ## How the rules are checked - The gotchas come from production work, and a new one is accepted only with a symptom, a cause (or "not established"), the fix that ran and the month it was seen. The page "Why does my agent...?" (`docs/gotchas.md`) indexes them by symptom, in a designer's words. - `scripts/check_api.py` checks every Plugin API name the skills mention (`figma.*` chains, member names, enum values) against `@figma/plugin-typings` 1.140.0, so an invented or misspelled method fails the check before it ships. Names cited because they do not exist, such as `getAnnotations()`, are listed on purpose and must stay absent. - Unit tests check skill frontmatter, links between files, the file lock, the hook, the installer, and style and privacy patterns. CI runs them on macOS and Ubuntu. - Nothing in this project collects data or sends telemetry. Of the plugin's scripts, only `fetch_comments.py` reaches the internet, to read comments from api.figma.com with the designer's own token; the hook, the installer and the other scripts connect only to 127.0.0.1 or not at all. Some skill steps have the agent call the Figma API, Apple's App Store search or the npm registry directly. The maintainer script `scripts/check_api.py`, which is not part of the plugin, downloads the pinned typings from registry.npmjs.org. ## Which skills fit which setup | Setup | What to use | | --- | --- | | No agent connected to Figma | The rules on this page. Optionally read `figma-handoff-gate` and `figma-slop-check` as checklists. | | Claude Code, Codex or Cursor with figma-console-mcp and Figma Desktop | Install all eight skills: `npx skills add thiagoxikota/figma-maxxing` | | Official Figma MCP server only (`use_figma`) | `figma-canon`, `figma-preflight`, `figma-orient`, `figma-slop-check`, `figma-handoff-gate`. `figma-preflight`, `figma-slop-check` and `figma-handoff-gate` ran there once, on a demo file in a blind test, with some steps adapted or skipped; 1.1.0 changed detector 8 of `figma-slop-check` after that run. The others are untested on that server. | The skills: - `figma-canon`: the knowledge base every other skill reads. - `figma-preflight`: read-only checks before any write. - `figma-orient`: maps a file before anyone touches it. - `figma-slop-check`: after a write, does it look machine made, is it precise. - `figma-handoff-gate`: what a developer needs before the handoff. - `figma-comment-fix-loop`: open comments to fixes to evidence. - `figma-click-flow`: flow arrows for a static handoff. - `figma-bridge-doctor`: the connection between the agent and Figma Desktop (macOS scripts). ## Full files (only for agents that write to Figma) - [README](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/README.md) - [README in Portuguese](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/docs/README.pt-BR.md) - [Why does my agent...?](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/docs/gotchas.md): the gotchas indexed by symptom, one line each, with a link to the fix - [figma-canon](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/SKILL.md): hard rules and the index of every reference - [Handoff format](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/references/handoff-format.md) - [State coverage](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/references/state-coverage.md) - [AI slop signatures](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/references/ai-slop-signatures.md) - [Naming canon](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/references/naming-canon.md) - [Plugin API anomalies](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/references/plugin-api-anomalies.md) and [field notes](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-canon/references/field-notes.md): long files, read only the entry you need - [figma-handoff-gate](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-handoff-gate/SKILL.md) and [figma-slop-check](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/skills/figma-slop-check/SKILL.md) - [Privacy](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/PRIVACY.md) and [security](https://raw.githubusercontent.com/thiagoxikota/figma-maxxing/main/SECURITY.md): what runs on your machine and what never leaves it