Figma to block
A designer hands over a frame link and your Claude writes the block and its schema. One step instead of two.
Your agency builds a client's website in your own Next.js repo. A block is one of your React components plus a small schema saying which parts the client may edit in Snabbsite. This page is about getting from a Figma frame to that pair without building it twice.
The one-line workflow
- The designer sends a Figma frame link.
- In your repo, tell Claude: "gör den här framen till ett block" and paste the link.
- Claude reads the frame through the Figma MCP, writes the component, marks the editable fields, and registers the block in your repo's block map.
That is the whole of it today, and the last step is the one to know about:
there is no command yet that sends the schema to Snabbsite. snabbsajt push
merge-imports a Site Kit package, which is content going into an existing draft,
and it does not touch the block map. So the block is not in the client's
"lägg till sektion" list yet, and its fields are not in the editing panel. The
component and the schema are written and deploy with your own app; they are
waiting on the CLI call, not on you.
When that call lands, what it sends is the schema alone: field names, kinds and labels. Snabbsite never runs, builds or copies your component.
What Claude decides, and what it asks you
It reads every text node, image fill, link, and Figma boolean and variant property in the frame, then decides one of three things per item: mark it editable, fold it into another field, or leave it out. It reports all three lists, and the middle two are the ones worth reading. A field nobody marked is a part of the page the client can never change, which is the failure this whole step exists to prevent.
It asks you only for what the frame cannot say: what the block is called in the palette, and which website it belongs to when your repo serves more than one.
The field kinds
Eight, and nothing else: text, richtext, image, link, select,
boolean, list, icon.
- Keys are lowercase (
^[a-z][a-z0-9_-]*$), so writecta_link, notctaLink. A camelCase key is refused when the schema is registered. richtextis plain text with line breaks. There is no path that stores HTML, so formatting inside a paragraph is your component's job.- A
linkis{href, label?}and onlyhttps:,http:,mailto:,tel:and a leading/are accepted. - An
imageis{assetId, alt?}. The renderer resolves the URL before your component sees it. - A
listis an ordered set of sub-items, each with its ownfields, and it is one level deep: a list inside a list is refused. Give itmaxItemswhen your layout only holds so many. The client reorders the items in their editor, and a list you marklockeddoes not move. - An
iconis aselectover names you register beside your own components. We ship you no icon set and we never draw one: the name travels, and your component decides what it draws. Declare the names inoptions. - A style choice is an ordinary
select. Light or dark, image left or right: your component reads the string. There is no separate kind for it. - Layout choices that change the whole shape are
variantson the block, not fields. Register every variant the Figma component set offers, not only the one in the frame you were sent. - There is still no number kind. A price is a
textline.
When the design changes
Run it again on the same frame. Claude re-reads it, compares the candidates
against the schema you already registered, and changes only what moved. Bump
version when a field's meaning changed, not when the styling did.
Status
The skill and the field vocabulary described here are in place, and so are the
SDK pieces this page names: defineBlock, the block map in
snabbsajt/blocks.ts, and the catch-all route that draws a composed page.
snabbsajt push reads that file and sends what it declares, so a block you
write today reaches your client's editor on your next push. Shipping the skill
through snabbsajt skills install is still being built.
Didn't find the answer, or is something wrong here? Tell us.