figma-to-landing-page

Installation
SKILL.md

Figma to Landing Page

1. Overview

Converts Figma designs into production-ready Nuxt 3 pages composed from @rds-vue-ui/* components. This skill implements a two-tier approach to accommodate different Figma account levels:

Tier Input Context Quality When Used
Rich Path (Dev+) Figma URL Full layout tree, typography, colors, component structure get_design_context returns rich data
Screenshot Path (Basic) Figma URL, prototype URL, or image Visual analysis only get_design_context fails, returns limited data, or user provides an image/screenshot

Both tiers produce the same output: a pages/<page-name>.vue file with a companion assets/content/<page-name>.json data file, built entirely from @rds-vue-ui/* components.


2. Prerequisites

Before starting, confirm the following are available:

  1. Figma MCP server — connected and responding (required for Figma URL inputs)
  2. Playwright MCP — available for screenshot capture (required for prototype URLs and visual validation)
  3. rds-component-mapper skill — must be available; it provides the shared component selection decision tree used by both tiers
  4. User input — one of the following:
    • A Figma design URL (e.g. https://figma.com/design/:fileKey/:fileName?node-id=1-2)
    • A Figma prototype URL (e.g. https://figma.com/proto/:fileKey/...)
    • A screenshot or image file of the design

3. Step 1 — Detect Input Type & Account Tier

Determine which processing tier to use based on the input and available Figma access.

3.1 Parse the Input

  1. If Figma design URL → extract fileKey and nodeId from the URL format:

    https://figma.com/design/:fileKey/:fileName?node-id=<nodeId>
    
    • fileKey is the path segment after /design/
    • nodeId is the node-id query parameter (e.g. 1-2)
  2. If Figma prototype URL → extract fileKey from:

    https://figma.com/proto/:fileKey/...
    
    • A prototype URL indicates the Screenshot Path (no design context available)
  3. If screenshot/image → proceed directly to Screenshot Path (Step 2b)

3.2 Probe Account Tier

If a fileKey and nodeId were extracted:

  1. Call get_design_context(fileKey, nodeId) via the Figma MCP server
  2. Evaluate the response:
    • Rich data returned (layout tree, typography tokens, colors, component structure) → proceed to Rich Path (Step 2a)
    • Call fails, times out, or returns limited/empty data → fall back to Screenshot Path (Step 2b)

4. Step 2a — Rich Path (Dev+ Account)

Use this path when get_design_context returns comprehensive design data.

4.1 Extract Design Context

get_design_context(fileKey, nodeId)

From the response, extract:

  • Layout structure — frame hierarchy, auto-layout direction, spacing, padding
  • Typography — font family, size, weight, line height, letter spacing
  • Colors — fills, strokes, effects (map to RDS theme CSS variables)
  • Component structure — instances, variants, nested components

4.2 Get Visual Reference

get_screenshot(fileKey, nodeId)

Capture a screenshot for visual validation later.

4.3 Download Assets

Download any assets (icons, illustrations, images) from the Figma MCP localhost endpoints.

IMPORTANT: Use the localhost URLs returned by the Figma MCP server directly. Do NOT import icon packages or substitute with icon libraries. The Figma assets are the source of truth for the design.

4.4 Handle Large / Truncated Responses

If get_design_context returns a response that is too large or appears truncated:

  1. Call get_metadata(fileKey, nodeId) first to get the top-level structure
  2. Identify child node IDs from the metadata
  3. Fetch each child node individually with get_design_context(fileKey, childNodeId)
  4. Reassemble the full design context from the individual responses

4.5 Map Sections to RDS Components

For each design section identified in the context:

  1. Invoke the rds-component-mapper skill decision tree to select the best @rds-vue-ui/* component for the section's visual intent
  2. Map Figma design tokens to RDS component props:
    • Figma auto-layout → RDS section layout props
    • Figma text styles → RDS typography props (heading level, size, weight)
    • Figma color fills → RDS theme CSS variables (var(--rds-color-*))
    • Figma component instances → nested RDS sub-components
  3. Extract content: headings, body text, CTA labels, image URLs, link targets
  4. Extract colors: map hex values to the closest RDS theme variable

4.6 Compose the Page

Assemble all mapped sections into a single pages/<page-name>.vue file:

<script setup>
const content = await import('~/assets/content/<page-name>.json')
</script>

<template>
  <div>
    <!-- Each section maps to an @rds-vue-ui/* component -->
    <HeroStandardApollo v-bind="content.hero" />
    <SectionCardsApollo v-bind="content.cards" />
    <!-- ... -->
  </div>
</template>

4.7 Create Content JSON

Create assets/content/<page-name>.json with all extracted content:

{
  "hero": {
    "heading": "Extracted heading from Figma",
    "subheading": "Extracted subheading",
    "ctaLabel": "Get Started",
    "ctaUrl": "#",
    "backgroundImage": "/images/hero-bg.jpg"
  },
  "cards": {
    "items": [
      {
        "title": "Card Title",
        "description": "Card description text",
        "image": "/images/card-1.jpg"
      }
    ]
  }
}

4.8 Validate Against Screenshot

Compare the composed page output against the Figma screenshot captured in Step 4.2. Check alignment, spacing, typography, and color fidelity.


5. Step 2b — Screenshot Path (Basic Account / Image Input)

Use this path when rich design context is unavailable.

5.1 Obtain the Screenshot

Input Type Method
Figma design URL Call get_screenshot(fileKey, nodeId) — works on all Figma account tiers
Figma prototype URL Use Playwright MCP: browser_navigate to the URL, then browser_take_screenshot
User-provided image Use the image directly

5.2 Analyze the Screenshot

Use the vision model to analyze the screenshot and identify:

  1. Page sections — hero area, content blocks, testimonial strips, card grids, CTAs, footer
  2. Approximate layout — full-width sections, grid columns (2-col, 3-col, 4-col), sidebars, stacked layouts
  3. Content — headings (H1, H2, H3), body text, button labels, image placeholders
  4. Color palette — dominant colors, accent colors, background tones
  5. Typography hints — relative font sizes, weight variations (bold headings vs. regular body), text alignment

5.3 Map Sections to RDS Components

For each visually identified section:

  1. Invoke the rds-component-mapper skill decision tree to select the closest @rds-vue-ui/* component
  2. Infer props from visual analysis:
    • Section height/width → layout sizing props
    • Observed colors → closest RDS theme CSS variables
    • Text content → extract where readable, use descriptive placeholders where not (e.g. "[Hero heading text]")
    • Image areas → placeholder image paths
  3. Generate placeholder content for any text that cannot be reliably extracted from the screenshot

5.4 Compose the Page

Assemble into pages/<page-name>.vue following the same structure as the Rich Path (Step 4.6).

5.5 Create Content JSON

Create assets/content/<page-name>.json following the same structure as the Rich Path (Step 4.7). Mark placeholder content clearly:

{
  "hero": {
    "heading": "[Hero heading — replace with actual copy]",
    "subheading": "[Subheading — replace with actual copy]",
    "ctaLabel": "Learn More",
    "backgroundImage": "/images/placeholder-hero.jpg"
  }
}

5.6 Visual Comparison

  1. Take a screenshot of the generated page using Playwright MCP (browser_navigatebrowser_take_screenshot)
  2. Compare side-by-side with the original Figma screenshot / user image
  3. Iterate on component selection and props until the output closely matches the original design

6. Translation Rules

Figma MCP outputs React + Tailwind CSS by default. All output must be translated to the RDS stack:

Figma MCP Output RDS Target
React JSX Vue 3 <template> with <script setup>
Tailwind utility classes Bootstrap 5 classes or custom SCSS
Inline style objects SCSS <style lang="scss" scoped> blocks
Hardcoded hex colors RDS theme CSS variables (var(--rds-primary), var(--rds-secondary), etc.)
className class
onClick / onChange @click / @change
{condition && <El/>} v-if="condition"
{items.map(i => ...)} v-for="item in items"
React component imports None — RDS components are auto-imported via Nuxt component scanner

Component Naming

  • Use PascalCase for all component names in templates: <HeroStandardApollo>, <SectionCardsApollo>
  • Do NOT add import statements for @rds-vue-ui/* components — they are auto-imported

Styling

  • Use Bootstrap 5 utility classes where they match the design intent
  • For custom styling beyond Bootstrap, use scoped SCSS:
    <style lang="scss" scoped>
    .custom-section {
      padding: 4rem 0;
      background-color: var(--rds-surface);
    }
    </style>
    
  • Never use Tailwind classes — the project uses Bootstrap 5 + SCSS exclusively

7. Desktop + Mobile

When Both Viewports Are Provided

If the user provides separate Figma nodes for desktop and mobile:

  1. Extract/analyze both viewports
  2. Implement responsive behavior using Bootstrap responsive classes:
    • col-lg-* / col-md-* / col-sm-* for grid columns
    • d-none d-lg-block / d-lg-none for viewport-specific elements
    • order-lg-* for reordering on different breakpoints
  3. Validate both viewports against their respective Figma screenshots

When Only Desktop Is Provided

  1. Implement the desktop design faithfully
  2. Apply sensible mobile defaults using Bootstrap's responsive grid
  3. Stack columns on mobile (col-12 on small screens, col-lg-* on large)

Breakpoint Reference

Bootstrap Class Breakpoint
col-sm-* ≥ 576px
col-md-* ≥ 768px
col-lg-* ≥ 992px
col-xl-* ≥ 1200px
col-xxl-* ≥ 1400px

8. Validation Checklist

Before considering the page complete, verify every item:

  • Layout matches — spacing, alignment, sizing match the Figma design
  • Typography matches — font family, size, weight, line height are correct
  • Colors match — all colors use RDS theme CSS variables (no hardcoded hex)
  • Components used — all sections use @rds-vue-ui/* components where a suitable match exists
  • Content is JSON-driven — all text, images, and data come from assets/content/<page-name>.json
  • No manual imports — no import statements for RDS components (auto-imported)
  • Vue 3 syntax<script setup>, v-if, v-for, @click (no React patterns)
  • Bootstrap 5 only — no Tailwind classes; Bootstrap utilities + SCSS
  • Responsive — desktop and mobile viewports render correctly
  • Assets downloaded — icons and images from Figma are saved locally (not imported from packages)
  • Visual comparison — side-by-side screenshot matches the original design

9. Examples

Example 1: Figma URL with Dev+ Account (Rich Path)

User input:

Build a landing page from this Figma design:
https://figma.com/design/ABC123xyz/campaign-summer-2025?node-id=1-2

Agent workflow:

  1. Parse URL → fileKey = "ABC123xyz", nodeId = "1-2"
  2. Call get_design_context("ABC123xyz", "1-2") → returns rich data:
    Frame "Hero Section"
      - Auto-layout: vertical, gap 24px, padding 64px
      - Background: linear-gradient(#1a2b3c, #2c3d4e)
      - Text "Summer Campaign 2025" — Inter Bold 48px #FFFFFF
      - Text "Discover what's new" — Inter Regular 18px #B0B8C4
      - Button "Explore Now" — fill #FF6B35, text #FFFFFF
    Frame "Features Grid"
      - Auto-layout: horizontal, gap 32px, wrap
      - 3x Card children with icon + title + description
    Frame "Testimonials"
      - Carousel with 4 testimonial cards
    
  3. Call get_screenshot("ABC123xyz", "1-2") → save reference image
  4. Download icon assets from Figma MCP localhost URLs
  5. Invoke rds-component-mapper for each section:
    • "Hero Section" → HeroStandardApollo
    • "Features Grid" → SectionCardsApollo
    • "Testimonials" → SectionTestimonialsApollo
  6. Map Figma tokens to RDS props:
    • #1a2b3c gradient → var(--rds-primary-dark)
    • #FF6B35 button → var(--rds-accent)
    • Inter Bold 48px → heading level 1
  7. Create pages/campaign-summer-2025.vue:
    <script setup>
    import content from '~/assets/content/campaign-summer-2025.json'
    </script>
    
    <template>
      <div>
        <HeroStandardApollo
          :heading="content.hero.heading"
          :subheading="content.hero.subheading"
          :cta-label="content.hero.ctaLabel"
          :cta-url="content.hero.ctaUrl"
          :background-image="content.hero.backgroundImage"
        />
        <SectionCardsApollo
          :heading="content.features.heading"
          :cards="content.features.items"
        />
        <SectionTestimonialsApollo
          :testimonials="content.testimonials.items"
        />
      </div>
    </template>
    
  8. Create assets/content/campaign-summer-2025.json with all extracted text, images, and links
  9. Validate: compare rendered page screenshot against Figma screenshot

Example 2: User Provides a Screenshot (Screenshot Path)

User input:

Here's a screenshot of the design I need built:
[attached: design-mockup.png]

Agent workflow:

  1. No Figma URL → proceed to Screenshot Path
  2. Analyze design-mockup.png with vision model:
    Identified sections:
    - Hero: full-width, dark background, large white heading, subtitle, orange CTA button
    - Stats bar: horizontal row of 4 stat counters with numbers and labels
    - Cards: 3-column grid, each card has an icon, heading, and paragraph
    - CTA banner: accent-colored background, centered heading, two buttons
    - Footer: dark background, 4-column links layout, social icons
    
  3. Invoke rds-component-mapper for each section:
    • Hero → HeroStandardApollo
    • Stats bar → SectionCountersApollo
    • Cards grid → SectionCardsApollo
    • CTA banner → SectionCtaApollo
    • Footer → FooterStandardApollo
  4. Infer props from visual analysis:
    • Dark hero background → var(--rds-primary-dark)
    • Orange CTA → var(--rds-accent)
    • 3-column layout → columns: 3
  5. Create pages/design-mockup.vue:
    <script setup>
    import content from '~/assets/content/design-mockup.json'
    </script>
    
    <template>
      <div>
        <HeroStandardApollo
          :heading="content.hero.heading"
          :subheading="content.hero.subheading"
          :cta-label="content.hero.ctaLabel"
          :cta-url="content.hero.ctaUrl"
        />
        <SectionCountersApollo
          :counters="content.stats.items"
        />
        <SectionCardsApollo
          :heading="content.cards.heading"
          :cards="content.cards.items"
          :columns="3"
        />
        <SectionCtaApollo
          :heading="content.cta.heading"
          :primary-label="content.cta.primaryLabel"
          :secondary-label="content.cta.secondaryLabel"
        />
        <FooterStandardApollo
          :columns="content.footer.columns"
          :social-links="content.footer.socialLinks"
        />
      </div>
    </template>
    
  6. Create assets/content/design-mockup.json with placeholder content:
    {
      "hero": {
        "heading": "[Hero heading — replace with actual copy]",
        "subheading": "[Subheading — replace with actual copy]",
        "ctaLabel": "Get Started",
        "ctaUrl": "#"
      }
    }
    
  7. Take screenshot of rendered page via Playwright MCP
  8. Compare side-by-side with original design-mockup.png
  9. Iterate: adjust component props and layout until visual match is satisfactory
Related skills
Installs
1
First Seen
Mar 17, 2026