reference-to-landing-page
Reference-to-Landing-Page
1. Overview
This skill takes a reference website URL plus a user modification prompt and produces a complete Nuxt 3 landing page built entirely with @rds-vue-ui/* components. It uses Playwright MCP for browser automation to capture the reference page, then translates every section into the RDS design system.
Inputs:
- A URL to an existing web page (the "reference")
- Natural-language instructions describing how the new page should differ
Outputs:
pages/<page-name>.vue— the composed landing pageassets/content/<page-name>.json— JSON-driven content for the page- Screenshots of both reference and final page for visual comparison
2. Prerequisites
Before executing this skill, verify:
- Playwright MCP server is connected (
@playwright/mcp@latest). Test withbrowser_navigate. - rds-component-mapper skill is available — it is required for Step 4 (component selection).
- User has provided:
- A reference URL (must be publicly accessible or accessible from the current network)
- Natural-language description of desired modifications
- Project context: You are working inside a Nuxt 3 project scaffolded from the
rds-lp-factorytemplate with@rds-vue-ui/*packages available.
3. Workflow
Execute these steps in order. Do not skip steps.
Step 1: Capture the Reference Page
Use Playwright MCP tools to fully capture the reference page:
1. browser_navigate({ url: "<reference-url>" })
2. Wait for page to fully load (network idle)
3. browser_take_screenshot({ fullPage: true })
→ Save/note this as "reference screenshot"
4. browser_snapshot()
→ This returns the accessibility tree — the primary structural data
For long pages (common with landing pages):
5. browser_execute_javascript({ script: "document.body.scrollHeight" })
→ Get total page height
6. If height > 3000px, scroll in increments and capture additional screenshots:
- browser_execute_javascript({ script: "window.scrollTo(0, 1500)" })
- browser_take_screenshot()
- Repeat until entire page is captured
7. browser_snapshot() again after scrolling to ensure all lazy-loaded content is captured
What to extract from the accessibility tree:
- Document title and meta description
- Navigation structure (links, dropdowns)
- All text content (headings, paragraphs, list items)
- Image alt text and approximate placement
- Link targets and button labels
- Form fields and their labels
- ARIA landmarks (banner, main, contentinfo, navigation)
Step 2: Analyze Page Structure
Parse the accessibility snapshot into a section inventory. Identify each distinct section of the page and classify it:
| Section Type | What to Look For |
|---|---|
| Navigation | <nav> landmark, logo, menu links, CTA button |
| Hero/Banner | First large section, prominent heading (h1), background image, CTA |
| Introduction | Short text block after hero, often with subheading |
| Features/Benefits | Grid of items with icons/images + short text, often 3-4 columns |
| Card Grid | Repeated card-like structures with image + title + description |
| Testimonials | Quotes with attribution, photos, star ratings |
| Statistics/Numbers | Large numbers with labels (e.g., "500+ students") |
| Video Section | Embedded video or play button with thumbnail |
| Parallax/Full-width Image | Full-width background image with overlaid text |
| Call to Action | Prominent button/form section urging user action |
| Form Section | Input fields, labels, submit button |
| FAQ/Accordion | Question-answer pairs, expandable items |
| Footer | Contact info, social links, copyright, secondary nav |
For each identified section, record:
- section_index: 1
type: hero
purpose: "Primary hero with program headline and apply CTA"
content:
heading: "Welcome to the MBA Program"
subheading: "Transform your career..."
cta_text: "Apply Now"
cta_url: "/apply"
background_image: true
layout: full-width, centered text
approximate_style: "dark overlay on image, white text, large heading"
Step 3: Apply User's Modification Intent
Parse the user's natural-language prompt and categorize the requested changes:
| Change Category | Examples | How to Apply |
|---|---|---|
| Content swap | "Make it for basketball instead of baseball" | Replace all program-specific text, images, links |
| Branding change | "Use maroon and gold colors" | Update color variables, theme selection |
| Section addition | "Add a video hero section" | Insert new section in appropriate position |
| Section removal | "Remove the contact form" | Delete section from inventory |
| Section reorder | "Put testimonials before features" | Rearrange section order |
| Layout change | "Make the cards 2 columns instead of 3" | Adjust grid configuration |
| CTA change | "Change apply button to schedule a visit" | Update CTA text, URL, styling |
| Tone/audience | "Make it more casual and student-focused" | Rewrite copy with new tone |
Produce a modified section inventory that reflects all user changes applied to the original structure.
Step 4: Map to RDS Components
For every section in the modified inventory, select the appropriate @rds-vue-ui/* component.
IMPORTANT: Invoke the rds-component-mapper skill for component selection. Do not guess component names — use the decision tree from that skill.
Mapping process for each section:
1. Take the section type + purpose from Step 2/3
2. Match against the rds-component-mapper decision tree:
- Hero → HeroStandardApollo | HeroVideoApollo | HeroArticleAtlas
- Card grid → SectionCardApollo | SectionCardAtlas + CardIcon | CardImageArticle | etc.
- Testimonials → SectionTestimonialFalcon | SectionTestimonialAtlas | etc.
- Video → SectionVideoApollo | SectionVideoModal
- Parallax → SectionParallaxApollo | SectionParallaxAtlas
- FAQ → RdsAccordion | OverlapAccordionAtlas
- Footer → FooterDefault | FooterPartner
- Navigation → NavbarDefault | NavbarSticky
- Forms → RdsInput, RdsCheckbox, RdsDropdown, etc.
3. Record: component name, package name, required props, slot content
Component selection constraints:
- Every visible section MUST use an RDS component — no raw HTML sections
- If no exact match exists, use the closest container (
SectionApollo,SectionContainerAtlas) and compose with smaller RDS components inside - Cards inside card sections must also be RDS card components
- Bootstrap 5 grid (
container,row,col-*) is allowed for custom layout within sections
Step 5: Compose the Landing Page
5a. Create the content JSON file
Create assets/content/<page-name>.json with all page content:
{
"meta": {
"title": "Page Title",
"description": "Meta description for SEO"
},
"hero": {
"heading": "Main Headline",
"subheading": "Supporting text...",
"ctaText": "Apply Now",
"ctaUrl": "/apply",
"backgroundImage": "/images/hero-bg.jpg"
},
"features": {
"heading": "Why Choose Us",
"items": [
{
"icon": "fa-star",
"title": "Feature One",
"description": "Description text..."
}
]
},
"testimonials": {
"heading": "Student Stories",
"items": [
{
"quote": "This program changed my life...",
"name": "Jane Doe",
"title": "Class of 2024",
"image": "/images/testimonial-1.jpg"
}
]
}
}
5b. Create the page component
Create pages/<page-name>.vue:
<template>
<div>
<!-- Navigation -->
<NavbarDefault v-bind="navbarProps" />
<!-- Hero Section -->
<HeroStandardApollo v-bind="heroProps">
<template #content>
<h1>{{ content.hero.heading }}</h1>
<p>{{ content.hero.subheading }}</p>
<a :href="content.hero.ctaUrl" class="btn btn-primary">
{{ content.hero.ctaText }}
</a>
</template>
</HeroStandardApollo>
<!-- Features Section -->
<SectionCardApollo v-bind="featuresProps">
<template #cards>
<CardIcon
v-for="(item, index) in content.features.items"
:key="index"
v-bind="mapFeatureToCardProps(item)"
/>
</template>
</SectionCardApollo>
<!-- Additional sections... -->
<!-- Footer -->
<FooterDefault v-bind="footerProps" />
</div>
</template>
<script setup>
import content from '~/assets/content/<page-name>.json'
// Map content to component props
const heroProps = computed(() => ({
// ... map from content.hero
}))
</script>
<style lang="scss" scoped>
// Use RDS theme variables for any custom styling
// @use '~/assets/scss/variables' as *;
</style>
Composition rules:
- Use
<script setup>with Composition API - All RDS components are auto-imported — do NOT add import statements for them
- Content comes from JSON file, imported at the top of
<script setup> - Use
computed()to map JSON content to component props - Use Bootstrap 5 grid classes for layout adjustments
- Use SCSS with RDS theme variables for any custom styling
- Sections are composed vertically in the
<template>, one after another
Step 6: Visual Validation
If a dev server is running (or can be started):
1. browser_navigate({ url: "http://localhost:3000/<page-name>" })
2. Wait for page to fully render
3. browser_take_screenshot({ fullPage: true })
→ Save as "output screenshot"
4. Compare visually with the reference screenshot from Step 1
5. Check for:
- Missing sections (compare section count)
- Broken layout (overlapping elements, misaligned grids)
- Missing content (text, images, links)
- Spacing inconsistencies (too cramped or too spread out)
- Color/theme mismatches
6. Fix any issues found and re-screenshot until satisfactory
If no dev server is available, perform a code review instead:
- Verify every section from the modified inventory is present in the template
- Verify all content JSON keys are referenced in the template
- Verify component props match the rds-component-mapper documentation
- Verify no raw HTML is used where an RDS component exists
4. Translation Rules
These rules are mandatory and must not be violated:
-
Never copy source code from the reference page. The reference is visual inspiration only — all code must be freshly written using
@rds-vue-ui/*components. -
Every section uses an RDS component. If the reference has a custom HTML section, find the closest RDS component match. Use
SectionApolloorSectionContainerAtlasas generic wrappers when needed. -
Content is JSON-driven. All text, image URLs, links, and configuration live in the content JSON file, not hardcoded in the template.
-
Components are auto-imported. Never write
import { HeroStandardApollo } from '...'— the Nuxt component scanner handles this. -
Use Bootstrap 5 grid for custom layout needs within sections. Do not use CSS Grid or Flexbox utilities directly when Bootstrap classes suffice.
-
Style with SCSS using RDS theme variables. Do not use inline styles or Tailwind-like utility classes.
-
Respect the user's modifications. The final page must reflect ALL changes the user requested, not just a copy of the reference.
-
Preserve accessibility. Use semantic HTML, proper heading hierarchy (h1 → h2 → h3), alt text on images, and ARIA labels where needed.
5. Examples
Example 1: Content Swap
User prompt: "Take mlb.asu.edu and make a version for the ASU basketball program"
Process:
- Capture mlb.asu.edu — hero, program highlights, faculty cards, testimonials, CTA
- Structure: Hero → Intro → Card Grid (programs) → Testimonials → CTA → Footer
- Modifications: Replace all "MLB" with "Basketball", swap images, update stats/facts
- Map: HeroStandardApollo, SectionApollo (intro), SectionCardApollo + CardImageArticle, SectionTestimonialFalcon, SectionParallaxApollo (CTA), FooterDefault
- Generate
pages/basketball.vue+assets/content/basketball.json
Example 2: Structural Modification
User prompt: "Use example.com as inspiration but add a video hero and remove the contact form"
Process:
- Capture example.com — identify all sections including the contact form
- Modifications: Replace standard hero with video hero, delete form section
- Map: HeroVideoApollo (instead of HeroStandardApollo), remove form section entirely
- All other sections mapped normally via rds-component-mapper
- Generate page files
Example 3: Complete Redesign with Same Content
User prompt: "Take our current research page and rebuild it with a modern parallax layout"
Process:
- Capture the research page — extract all content
- Modifications: Restructure as alternating content/parallax sections
- Map: HeroStandardApollo, then alternate SectionApollo ↔ SectionParallaxApollo
- Same content, completely different visual structure
- Generate page files with parallax-oriented layout
6. Error Handling
| Error | Resolution |
|---|---|
| Playwright cannot reach URL | Ask user to verify URL is accessible; check for auth walls |
| Page requires login/auth | Ask user to provide credentials or a public alternative |
| Reference page is a SPA with lazy loading | Scroll the entire page first, wait for network idle, then snapshot |
| No RDS component matches a section | Use SectionApollo or SectionContainerAtlas as a wrapper and compose with smaller RDS components |
| Content JSON structure unclear | Follow the pattern from existing pages in the project; check assets/content/ for examples |
| Dev server not available for validation | Perform code-level validation (Step 6 fallback) |
| Reference page has dynamic/interactive elements | Translate to the closest static RDS equivalent; note limitations to user |
7. Output Checklist
Before declaring the task complete, verify:
-
pages/<page-name>.vueexists and contains all sections -
assets/content/<page-name>.jsonexists with all content - Every section uses an
@rds-vue-ui/*component (no raw HTML sections) - No component import statements (auto-import only)
- Content is driven by JSON, not hardcoded
- All user-requested modifications are applied
-
<script setup>with Composition API is used - SCSS styling uses RDS theme variables
- Heading hierarchy is correct (single h1, then h2s, h3s)
- Reference screenshot and output screenshot captured (if dev server available)
- No code was copied from the reference page source
More from chandima/rds-lp-factory
rds-component-mapper
Maps visual descriptions, design context, or screenshots to the closest @rds-vue-ui/* design system components. Use when you need to select RDS components for a landing page section based on visual intent, Figma data, or natural-language descriptions.
2markdown-spec-to-page
Converts a markdown specification document into a complete Nuxt 3 landing page using RDS Vue UI components. Use when user provides a markdown file or text describing the desired page structure, components, and content.
1figma-to-landing-page
Translates Figma design URLs into complete Nuxt 3 landing pages using RDS Vue UI components. Supports both Dev+ accounts (rich design context) and Basic accounts (screenshot-based). Use when user provides a Figma URL or screenshot of a design to implement.
1iterative-build-page
Builds a Nuxt 3 landing page section-by-section from natural language descriptions using RDS Vue UI components. Use when user describes page sections incrementally (e.g., "Add a hero with video background", "Now add a 3-column card grid").
1