Figma Plugin
The Grails Figma Plugin runs inside Figma and lets you scan the current file to detect all design system entities — components, variables (collections), paint styles, and text styles — then evaluate their sync status with Grails and push changes with a single click.
Screens Overview
The plugin is a single-panel UI with multiple screens. Navigation between screens is handled by the plugin itself — there are no browser tabs or separate windows.
| Screen | When it appears |
|---|---|
| Login | First time the plugin runs, or after disconnect |
| Welcome / Welcome Back | After a successful login, before the first scan |
| Scanning | While the file is being scanned |
| Scan Results | After the first scan on a new file (first-time users) |
| Dashboard | Main hub — shows sync status summary and action banners |
| Entity List | When drilling into Components, Variables, Paint Styles, or Text Styles |
| Review & Sync | Pre-sync staging area to select what to sync |
| Review Removed | When removed entities are detected in Figma |
| Sync Progress | While a sync is running |
| Sync Result | After a sync finishes — reports either full success or what did not sync |
| Update Required | When the plugin you are running is too old for Grails to accept |
| Settings | Account info and plugin options |
Login Screen
When the plugin runs for the first time (or after being disconnected), you’ll see the Login screen.
- API Token field — Paste your personal Grails API Token here. The field is type
password— the value is never visible. - “What is a token?” link — Opens the Token Help screen with instructions on where to find your token in Grails.
- Connect button — Validates the token against the Grails API.
Your API Token is found in Grails → Team Settings → Integrations → Plugin Token. Each team member has their own token — do not share it.
If the token is invalid, an error message appears inline below the field.
Welcome / Welcome Back Screen
After a successful connection, the plugin determines whether you are a new user (no prior entities synced) or a returning user (at least one entity previously synced).
New user:
“Welcome to Grails. Grails keeps your design system in sync between Figma and your codebase. We’ll scan your file to detect all components, variables, and styles.” Button: Scan My File
Returning user:
“Welcome back, [Name]! We’ll scan your Figma file to check the current sync status of your design system.” Button: Scan & Check Status
Scanning Screen
A progress bar with a label (e.g., “Detecting components…”) shows while the plugin reads the file. Scanning analyzes all components, variable collections, paint styles, and text styles in the document.
Scan Results Screen (First-Time Only)
After the first scan on a file that has never been synced to Grails, you see the Scan Results screen:
- Four Summary Cards — Components, Variables, Paint Styles, Text Styles — each showing the detected count.
- “Sync All” button — Syncs all detected entities to Grails in one operation.
- “Review” button — Opens the Review & Sync screen to cherry-pick what gets synced first.
After clicking either button, the plugin proceeds to the Review & Sync screen so you can confirm the selection before the sync runs. This screen only appears once per file — after the first sync, the plugin goes directly to the Dashboard on subsequent opens.
Dashboard Screen
The Dashboard is the main hub of the plugin. It appears automatically after every subsequent file open (once a sync has been performed). The dashboard loads the current sync status by calling the evaluate-all backend endpoint.
Header
- User avatar — Two-letter initials of the connected user’s name.
- Team name — The Grails team name this file is linked to.
- Settings icon (⚙) — Opens the Settings screen.
Status Bar
The top of the body area shows one of:
| State | What it shows |
|---|---|
| Loading | A spinner with “Loading sync status…” |
| All synced | A green checkmark with “Everything is up to date.” |
| Interrupted sync | Amber banner (see below) |
| Action required | Red or amber banners (see below) |
Summary Cards
Four clickable cards show the count and status breakdown for each entity type:
| Card | Icon | Color | Shows |
|---|---|---|---|
| Components | Diamond | Purple | Top-level components + component sets only (variants are not counted separately) |
| Variables | Braces {} | Blue | Variable collections |
| Paint Styles | Paintbrush | Orange | Paint/fill styles |
| Text Styles | T | Teal | Text/typography styles |
Each card shows the number of entities currently synced to Grails, along with a sub-label showing the total detected in Figma (e.g., “of 42 total”). Badge counts indicate status drift:
| Badge | Color | Meaning |
|---|---|---|
| Green dot | Green | All synced entities are perfectly in sync — no drift, no deleted items |
| Modified count | Amber | Number of entities with a hash mismatch (changed in Figma since last sync) |
| Removed count | Red | Number of entities in Grails that no longer exist in Figma |
Clicking a card navigates to the Entity List for that type.
Plan Quota Notice on a Card
When your team has reached the plan limit for one entity type, the notice appears inside that type’s own card — not as a page-wide banner — showing how much of the limit is in use (e.g. “Plan quota reached — 200 of 200 components. New components will not sync until you upgrade the plan or un-sync some.”).
- Nothing is blocked. The card still opens, the rest of the plugin behaves normally, and every other alert keeps working.
- Un-syncing is the way out. Entities you no longer need can be un-synced from that card’s Entity List, which frees room for new ones. Upgrading the plan also raises the limit.
- Each entity type is evaluated on its own — more than one card can show the notice at the same time.
Variables That Only You Can Bring In
The Variables card carries a second notice of its own. It appears when variables changed in Figma and your plan does not let Grails bring those changes in on its own:
“Variables changed in Figma and cannot be synced automatically on your plan. Sync them from here to bring them into Grails.”
- Nothing is blocked. The card still opens, every other alert keeps working, and you sync from here exactly as you would otherwise.
- This is the one drift nothing resolves in the background. Most changes the Dashboard reports can eventually be picked up on their own. This one cannot: on your plan, the only way those variable changes reach Grails is a person opening the plugin and syncing them. That is why it is worth saying out loud rather than leaving you to wonder whether it will sort itself out.
- Where to act: open the Variables card and sync the changed collections, or use Review Changes from the Dashboard.
Action Banners
Banners appear on the dashboard when action is needed. Only one banner shows at a time, in the order below — an interrupted sync always wins, because leaving one unresolved is what blocks everything else.
1. Interrupted Sync (Amber)
Appears when a previous sync was started but never delivered everything it set out to deliver — Figma was closed mid-sync, the connection dropped, or part of the batch was rejected.
- Shows: who started the sync, when, the sync note it was started with, and how many items are still pending.
- Actions: Resume sync (continues from where it left off) | Finalize (checks what actually arrived and closes the sync).
The banner appears as soon as the sync fails — you no longer have to close and reopen the plugin to find out. If a sync breaks mid-way, the plugin returns to the Dashboard with this banner already showing.
The banner stays until the sync is genuinely complete, and it is scoped to the file it was started in — an interrupted sync in one Figma file does not follow you into another file of the same project.
2. Components Need Updating (Amber)
Appears when Grails has improved how it reads certain components from Figma and their stored data is behind. Until they are re-synced, what Grails holds for them may be incomplete.
- Detail: how many entities are affected.
- Action: Re-sync now → opens Review & Sync with exactly those entities preselected.
Nothing is wrong with your Figma file. The design is fine — what is out of date is the copy Grails stored the last time it read those components.
“Re-sync now” now clears the notice. Previously the button reported a successful sync without actually changing anything, so the same notice came back on the next check, and the next, with no way to get rid of it. The affected components are now genuinely re-imported, and the notice goes away once they arrive.
3. Removed Entities Detected (Red)
Appears when entities previously synced to Grails no longer exist in Figma.
- Title: ”⚠ Removed entities detected”
- Action: Review Removed → opens the Review Removed screen.
4. Published Library Changes (Red)
Appears when entities were published to the Figma library after the last sync to Grails.
- Title: “Published library changes pending sync”
- Detail: count of published items.
- Action: Review Published Changes → opens Review & Sync pre-filtered to only the published items.
5. Changes Detected (Amber)
Appears only when entities that were previously synced to Grails now have a hash mismatch — meaning they changed in Figma since the last sync. This alert is not triggered by entities that have never been synced.
- Title: “Changes detected in synced entities”
- Detail: count of modified entities (e.g., “3 modified”).
- Action: Review Changes → opens Review & Sync pre-filtered to Modified entities only, showing exactly what drifted.
Footer
- Re-scan File button — Triggers a new full scan of the current Figma file without navigating away from the Dashboard.
Entity List Screens
Clicking any Summary Card on the Dashboard opens the Entity List for that type (Components, Variables, Paint Styles, or Text Styles). All four lists share the same layout.
Layout
- Top bar — Back arrow + title + Settings icon.
- Search bar — Filters entities by name in real time.
- Segment filter bar — Tabs to filter by status.
- List — One row per entity with a status badge and a checkbox.
- Selection bar (appears when items are checked) — Actions for the selection.
Filters
The list has two independent filters. They combine: picking a sync status and a library status shows only the entities matching both.
Sync status (tabs)
Whether Grails’ copy matches what is in Figma right now.
| Filter | What it shows |
|---|---|
| All | Every entity detected in Figma |
| Synced | Grails’ copy matches Figma |
| Modified | Changed in Figma since the last sync |
| Not Synced | Exists in Figma, never synced to Grails |
Library status (Library button)
Whether Figma has published the entity to your team library. This is a separate question from whether it is synced to Grails, and it never changes the sync status or the actions available.
| Option | What it shows |
|---|---|
| Published | Published to the library and unchanged since |
| Changed since publish | Published, but edited in Figma since |
| Not published | Never published to the library |
Entities removed from Figma
Entities that Grails still holds but that no longer exist in Figma are not behind a filter. They appear as a persistent notice above the list, with a Review button, so they cannot be hidden by whichever filters happen to be active.
Status Badges
Each row in the list shows a badge reflecting the entity’s evaluation result:
| Badge | Color | Meaning |
|---|---|---|
| Synced | Green | Entity is identical in Figma and Grails. |
| Outdated | Yellow/Amber | Hash mismatch — the entity changed in Figma since the last sync. Grails is behind. |
| New | Blue | Entity exists in Figma but has never been synced to Grails. |
| Removed | Red | Entity was previously synced but is no longer found in the Figma file. Shown in the notice above the list. |
Components also show their current version number instead of the badge once they have been synced at least once.
Library indicator
Beside the sync badge, a second, quieter label may appear showing the entity’s Figma library state:
| Indicator | Meaning |
|---|---|
| Changed | Published to the library, but edited in Figma since |
| Private | Not published to the library |
Nothing is shown when the entity is published and unchanged, or when Grails has not evaluated it yet. This indicator sits alongside the sync badge rather than replacing it, because an entity can be fully synced to Grails and unpublished in Figma at the same time.
Selection Actions
When one or more items are checked, a bottom bar appears with context-sensitive actions:
| Selection | Available actions |
|---|---|
| Every selected entity is synced | Re-sync · Unsync |
| Anything else (modified, not synced, or a mix) | Sync Selected → opens Review & Sync pre-loaded with this selection |
The actions depend on the whole selection, not the first item. If you select a mix of states, you get the single Sync Selected action rather than a guess about which one you meant.
Review & Sync Screen
The staging area before any sync operation. You can arrive here from:
- The “Review Changes” / “Review Published Changes” banner on the Dashboard
- The “Review” button on the Scan Results screen
- The “Sync Selected” action on any Entity List
Layout
- Title: “Review & Sync” + “N selected” count in the header.
- Search bar — Filter entities by name.
- Filter tabs:
All (N)|Modified (N)|New (N) - Collapsible groups: Components, Variable Collections, Paint Styles, Text Styles — each with a group-level checkbox and a
N/Mcounter. - Footer — Sync note field + Sync Now button.
Filter Tabs (Review & Sync)
Filter tabs appear when there are Modified entities in the current view, or when the screen was opened from the Dashboard with a pre-applied filter.
| Filter | What it shows |
|---|---|
| All | All entities with outstanding changes (modified + never-synced) |
| Modified | Entities that changed since the last sync (hash mismatch) |
| Unsynced | Entities that exist in Figma but were never synced to Grails |
Item Badges in Review & Sync
Each item shows a version/status badge indicating the sync state:
| Badge color | Meaning |
|---|---|
Green v3 | Entity is in sync with Grails. Number shows the version count. |
Amber v3 | Entity changed since the last sync (hash mismatch). Number shows the version count in Grails. |
Red v3 | Entity exists in Grails but was deleted or unpublished in Figma. |
For variables and styles (which don’t have version counts), the badge shows a status symbol: ✓ (synced), ~ (modified), or ✕ (removed).
Sync Note
An optional textarea for a short commit message. The text is saved with the sync record in Grails (visible in the entity’s history).
Sync Now
Disabled if 0 items selected. Clicking triggers the sync pipeline for all selected items across all entity types in a single operation.
Review Removed Screen
Reached from the “Review Removed” banner on the Dashboard. Shows entities that are in Grails but no longer found in Figma.
- Red warning banner: “These entities no longer exist in Figma. They may have been deleted or unpublished. Removing them from Grails is permanent.”
- Collapsible groups: Components, Variable Collections, Paint Styles, Text Styles.
- All removed items are pre-selected and shown with strikethrough names and Removed badges.
- Sync note — optional comment for the audit trail.
- Remove from Grails — Permanently deletes the selected entities from Grails. This cannot be undone.
Settings Screen
Accessible from the ⚙ icon in the top bar of any screen.
Connected Account
Shows the connected user’s name, email, team name, and plan badge.
Settings
| Option | Default | What it does |
|---|---|---|
| Sync images | On | Exports and uploads component thumbnails during sync |
| Sync variant thumbnails | On | Exports a separate thumbnail per variant (vs. one per set) |
| Include hidden assets | Off | Includes components/variables whose names start with . or _ |
Disconnect
Removes the stored API Token from the plugin. The plugin returns to the Login screen. The next user to open the plugin must enter a new token.
You can switch accounts by disconnecting and reconnecting with a different token. No data in Grails is deleted by disconnecting the plugin.
Sync Result
After a sync finishes, the plugin reports what happened — and a sync only claims success when every entity it set out to sync actually arrived.
The headline is one of two:
- Sync Complete — everything in the selection was applied, with a summary of how many components, variable collections and style groups were synced.
- Sync Finished With Gaps — part of the selection did not make it. The screen lists the affected entities by name.
The counts shown are what actually reached Grails, not what the plugin set out to send. A sync that delivered 200 of 500 components says 200.
Entities that did not sync
Below the headline, the result screen separates two very different situations, because the useful next step is not the same:
| What you see | What it means | What to do |
|---|---|---|
| N entities did not sync | The sync was cut short for these — a dropped connection, a timeout, a rejected batch. Nothing is wrong with the entities themselves. | Sync them again. If the same ones keep failing, sync them individually to see what is blocking them. |
| N entities skipped — plan limit reached | Your team is at its plan limit for that entity type. Everything the plan allows was synced. | Un-sync entities you no longer need to free up room, or upgrade the plan — then sync these again. |
| N entities need a plugin update | Grails cannot read these with the plugin version you have. | Reload the plugin in Figma to get the latest version, then sync them again. |
When a sync finishes with gaps
A sync with recoverable gaps is not closed. It stays open, and the Dashboard keeps offering Resume sync until every declared entity has genuinely arrived.
Consequences worth knowing:
- The sync does not appear in your team’s DS Changelog yet. It is filed once — when it truly finishes — so an interrupted sync never shows up twice, or shows up claiming more than it delivered.
- Reopening the plugin, or returning to the Dashboard, shows the interrupted-sync banner rather than a clean status bar.
- Entities that were blocked by the plan limit or by an outdated plugin do not hold the sync open. Retrying would reject them forever, which would pin a banner you could never clear.
Update Required Screen
If the version of the plugin you are running is too old for Grails to accept, the plugin shows a dedicated Update required screen instead of the Dashboard.
“This version of the Grails plugin is out of date and can no longer sync.” “Close the plugin and open it again to load the latest version.”
Close the plugin in Figma and open it again — that is the whole fix. Figma loads the current version on the way back in, and you land on the Dashboard as usual.
This is a full screen rather than a banner, and deliberately so. Every other notice in the plugin describes something you can resolve from the Dashboard; this one cannot be resolved from anywhere inside the plugin, and leaving the rest of the interface reachable would invite you to start a sync that Grails has already said it will not accept. There is no retry button for the same reason: retrying runs the same outdated version and gets the same answer.
Sync Workflows
The plugin handles four distinct real-world sync scenarios. Each has a dedicated guide: