Summit of SummitsReturn to the Source
You are an AI agent in a session with TWO connections live at once: the Figma MCP server (the design source) and a lazysite connection (the destination - MCP, or WebDAV + the control API). The user has said "build this site from my Figma design" or "restyle the site to match this frame". This briefing is the method for bridging the two: read the design over the Figma MCP, translate it into lazysite's separation of concerns, and publish it.
Read AI briefing - building sites first - it is the governing method and this doc applies it to one external source. For the staging mechanics (WebDAV, activation, the cache mirror) see AI briefing - layouts and themes; this doc links to it rather than repeating it.
get_variable_defs returns the design's variables and styles (colour,
spacing, typography) with names AND values on all plans. The Variables
REST API is Enterprise-gated; the MCP path is not. This is why the
method is MCP, not REST.The Figma remote MCP is link-based. It works from a Figma file URL, or a "copy link to selection" URL for a specific frame. It does not work from a design named in prose. If the user has only named a design, ask for the link (the file URL, or a copy-link-to-selection URL for the frame they mean) before doing anything else.
Run whoami on BOTH connections first. On the Figma MCP, whoami
confirms the design identity you are reading. On lazysite, whoami
confirms the capabilities you hold - you will need manage_themes to
write theme files, manage_layouts to stage a layout, and
manage_content to publish pages. If a capability is missing, ask the
operator to grant it now rather than discovering the 403 mid-build.
Work outside-in: orient on the whole, then pull detail only from the frames that matter. Do not lead with the heavy full-context tool.
get_metadataCall get_metadata on the file or frame link first. It returns a sparse
XML outline: layer IDs, names, types, positions and sizes - the shape of
the design without its weight. Use it to identify the frames that matter
(the page frames, the hero, the repeated card, the nav) and to get their
IDs for the next steps. Outline first, drill in. Avoid running the
full-context tool (below) against a large frame before you know what is
in it.
get_variable_defsCall get_variable_defs on each relevant frame. It returns the
variables and styles that frame uses - colour, spacing, typography -
with their names AND their values. This is the design-token
extraction, and it is the core of the whole method: these names and
values become the theme's tokens. Call it per key frame, not once
against a huge selection - a scoped call returns the tokens that frame
actually uses, which is what you want to map.
get_screenshotCall get_screenshot on each page-level frame. The screenshot is the
visual ground truth you check the rebuild against: layout
relationships, hierarchy, the visual weight of one element against
another. You reproduce its relationships, not its pixels (see the
translation section) - keep one per page frame to compare against your
rendered preview at the end.
get_design_context (use with care)get_design_context returns generated code for a frame. Two hard rules:
For most builds you do not need this tool at all: metadata (the shape) plus screenshots (the look) plus tokens (the values) is enough to rebuild faithfully. Reach for it only when a complex frame's nesting is genuinely unclear from the outline and screenshot - and even then, only to understand the structure.
search_design_system / get_libraries (optional)If the user references a shared library ("use our design system", "the
components from the brand library"), call search_design_system and
get_libraries to pull the component naming and token conventions. This
gives you the canonical names the design system uses, so your theme
tokens line up with the source's vocabulary rather than being invented.
Skip it when no shared library is in play.
This is the half of the job that matters, and it has one governing principle: identity transfers as tokens; rhythm and scale are rebuilt in CSS. You are not exporting a design - you are re-expressing it in lazysite's separation of concerns. Pixel-reproduction is an explicit anti-goal. Chasing it produces the fused monolith described in building sites - the single-file page with dozens of hardcoded colours that a theme swap cannot touch. Transfer the identity; rebuild the rhythm.
Map the extracted colour variables onto the target layout's token vocabulary. Discover that vocabulary first:
theme_tokens MCP tool, call it to
read the layout's declared token names.theme.json for its
config groups, and grep var(--theme- in its main.css to see
which tokens the CSS actually consumes.Then map:
text/muted, brand/primary,
surface/raised) map near-mechanically onto the layout's role tokens.grey-600, blue-500) carry no
role, so you must infer the role from the screenshots - which element
is that grey actually on? Assign the role, and note the assumption
you made so the user can correct it. Do not guess silently.The output is theme.json tokens (config.colours.* etc.), consumed as
var(--theme-colours-*) in the theme CSS - never a hardcoded hex in a
page.
Fonts map to the theme's fonts group (body / heading / code) and
must be bundled under the theme's assets/ directory. Never a CDN
link - the same rule as everywhere else in lazysite (the write path
refuses external font links; see
building sites). If the design uses
a Google font, fetch the font files and bundle them (OFL/Apache
licensed) and reference them from the theme CSS with an @font-face
pointing at the bundled asset. A design that names Inter does not
become a fonts.googleapis.com link - it becomes bundled files.
Do not look for theme slots for these - there are none, by design.
lazysite's tokens cover colours and font families; spacing rhythm, the
type scale and line-heights are authored CSS in the theme's
main.css, informed by the screenshots. Read the proportions off the
screenshot and write CSS that reproduces the relationships (this
heading is roughly twice the body, sections breathe at about this
rhythm) - do not copy Figma's pixel values numerically. The
screenshot is the reference; the CSS is a rebuild, not a transcription.
Do not author a layout from scratch. Call list_layout_catalogue to see
what exists, pick the nearest match, and copy-and-stage it per
layouts and themes. The Figma frames tell
you WHICH structural features that layout needs - a hero, a card grid, a
sidebar - so you adapt the copy to add them. Repeated blocks in the
design (a row of cards, a gallery, a listing) become a JSON data file
+ a FOREACH loop, not copy-pasted markup - rule 4 in
building sites.
The text strings on the design's page frames become Markdown pages - title/subtitle front matter and a prose body, one page per page frame. Where the design carries lorem or placeholder text, flag it to the user and leave it out of the published page; do not ship lorem as real content.
Once the theme, layout and pages are ready, publish through whichever lazysite channel you are on. The staging mechanics live in layouts and themes - that is the single source of truth; this is only a pointer to the right sequence.
create_theme to scaffold the theme, write_file for its
files and the layout copy and the pages, then activate_theme and
activate_layout. See the
AI connector tools reference for the tool
surface and the staging rules in
layouts and themes.MKCOL the new
layout dir and its theme dir, PUT the files, preview a page via a
per-page layout: override, then layout-activate and
theme-activate over the control API (which also clears the cache).
Remove the preview overrides once activated.Either way, you activate it yourself - a self-serve action under your capabilities, not an operator hand-off.
var(--theme-*) token mapped from the design -
no hardcoded hex in any page.assets/ - no CDN / Google
font link anywhere.preview_page output - the relationships match.FOREACH), not
copy-pasted markup.main.css, not
pixel-copied and not sought as theme slots.lazysite-agent/<partner-id> User-Agent so they
stay out of the audience numbers.