markdown-spec-to-page

Installation
SKILL.md

Markdown Spec to Page

1. Overview

Parses a structured markdown document and generates a complete Nuxt 3 landing page. The markdown spec defines page sections, content, and optionally which RDS Vue UI components to use. When no component is specified, the skill infers the best match using the rds-component-mapper decision tree based on the section name and content.

This skill converts a single markdown specification into two output files:

  • pages/<page-name>.vue — the Nuxt 3 page component
  • assets/content/<page-name>.json — the structured content data

2. Markdown Spec Format

The specification follows a simple, human-readable markdown structure:

# Page Title

## Hero
- component: hero-standard-apollo (optional — will be inferred if omitted)
- title: "Welcome to Our Program"
- subtitle: "Discover opportunities"
- backgroundImage: /images/hero.jpg

## About Section
- component: section-apollo
- title: "About Us"
- body: "We are a leading institution..."

## Programs
- layout: 3-column grid
- component: card-image-article
- items:
  - title: "Program A"
    image: /images/prog-a.jpg
    link: /programs/a
  - title: "Program B"
    image: /images/prog-b.jpg
    link: /programs/b

## Testimonials
- component: section-testimonial-falcon
- quote: "This program changed my life"
- author: "Jane Doe"
- role: "Class of 2025"

## Footer
- component: footer-standard

3. Parsing Rules

Element Syntax Behavior
Page title # Page Title Sets the <title> tag and page meta
Section ## Section Name Each H2 heading becomes a page section
Component (explicit) - component: xxx Use the named RDS component (kebab-case)
Component (inferred) (no component line) Infer via rds-component-mapper from section name + content
Repeated items - items: Indicates a list of repeated components (cards, accordion, etc.)
Grid layout - layout: N-column grid Wraps items in Bootstrap row/col-md-* grid
Props/content - key: value All other key-value pairs become component props or content JSON fields
Nested items Indented - key: value under items: Each indented block is one item in the array

Component Name Resolution

When a - component: line is present, convert from kebab-case to the PascalCase Vue component:

Spec Value Vue Component
hero-standard-apollo HeroStandardApollo
section-apollo SectionApollo
card-image-article CardImageArticle
overlap-accordion-atlas OverlapAccordionAtlas
section-testimonial-falcon SectionTestimonialFalcon
section-stat-apollo SectionStatApollo
carousel-image-apollo CarouselImageApollo
footer-standard FooterStandard
video-apollo VideoApollo
navbar-standard NavbarStandard

Component Inference (when no component specified)

When the - component: line is omitted, infer from the section name and content:

Section Name Pattern Inferred Component Condition
Hero, Banner HeroStandardApollo Default hero
About, Overview, Introduction SectionApollo General content section
Programs, Courses, Services CardImageArticle (grid) Has items: with images
Testimonial(s), Quote(s) SectionTestimonialFalcon Single testimonial
Testimonial(s), Quote(s) CarouselTestimonialApollo Multiple items
FAQ, Questions OverlapAccordionAtlas Has question/answer items
Stats, Numbers, Metrics SectionStatApollo Has numeric values
Gallery, Images, Photos CarouselImageApollo Image collection
Video, Media VideoApollo Video content
Footer FooterStandard Page footer
Contact, Form FormApollo Has form fields
Navigation, Navbar NavbarStandard Top navigation

If no pattern matches, default to SectionApollo as a generic content block.

4. Workflow

  1. Parse — Read the markdown spec from a file path or inline text.
  2. Extract — Build a section list with all key-value pairs per section.
  3. Resolve Components — For each section:
    • If - component: is specified → use it (convert kebab to PascalCase).
    • If not → infer from section name + content via the inference table above.
    • Map remaining key-value pairs to component props.
  4. Handle Items — For sections with - items:, build an array and apply grid layout.
  5. Generate Page — Produce pages/<page-name>.vue with all sections.
  6. Generate Content — Produce assets/content/<page-name>.json from the spec content.
  7. Report — Summarize: N sections, components used, any unmatched sections.

5. Output Format

Page File: pages/<page-name>.vue

<template>
  <div>
    <!-- Section: Hero -->
    <HeroStandardApollo
      :title="content.hero.title"
      :subtitle="content.hero.subtitle"
      :backgroundImage="content.hero.backgroundImage"
    />

    <!-- Section: About -->
    <SectionApollo
      :title="content.about.title"
      :body="content.about.body"
    />

    <!-- Section: Programs -->
    <div class="container py-5">
      <div class="row">
        <div
          v-for="(card, index) in content.programs.items"
          :key="index"
          class="col-md-4 mb-4"
        >
          <CardImageArticle
            :title="card.title"
            :image="card.image"
            :link="card.link"
          />
        </div>
      </div>
    </div>

    <!-- Section: Testimonials -->
    <SectionTestimonialFalcon
      :quote="content.testimonials.quote"
      :author="content.testimonials.author"
      :role="content.testimonials.role"
    />

    <!-- Section: Footer -->
    <FooterStandard />
  </div>
</template>

<script setup>
useHead({ title: 'Welcome to Our Program' })

const { data: content } = await useAsyncData('content', () =>
  import('~/assets/content/welcome.json').then(m => m.default)
)
</script>

Content File: assets/content/<page-name>.json

{
  "hero": {
    "title": "Welcome to Our Program",
    "subtitle": "Discover opportunities",
    "backgroundImage": "/images/hero.jpg"
  },
  "about": {
    "title": "About Us",
    "body": "We are a leading institution..."
  },
  "programs": {
    "items": [
      { "title": "Program A", "image": "/images/prog-a.jpg", "link": "/programs/a" },
      { "title": "Program B", "image": "/images/prog-b.jpg", "link": "/programs/b" }
    ]
  },
  "testimonials": {
    "quote": "This program changed my life",
    "author": "Jane Doe",
    "role": "Class of 2025"
  }
}

6. Grid Layout Calculation

When - layout: N-column grid is specified, calculate Bootstrap column classes:

Columns Class Items per Row
1 col-12 1
2 col-md-6 2
3 col-md-4 3
4 col-md-3 4
6 col-md-2 6

If no layout is specified but items: is present, default to 3-column grid (col-md-4).

7. Section Key to JSON Key Mapping

Section names from H2 headings are converted to JSON keys:

H2 Heading JSON Key
## Hero hero
## About Section about
## Our Programs programs
## Student Testimonials testimonials
## FAQ faq

Rules: lowercase, remove articles (a, an, the, our), take the primary noun, use camelCase for multi-word keys that remain after stripping.

8. Error Handling

Condition Behavior
No # Page Title found Use the file name as page title
No ## sections found Report error: spec contains no sections
Unknown component name Report warning, skip section, continue
Missing required props Report warning, generate with placeholder values
Empty items: array Report warning, generate section with empty array
Duplicate section names Append numeric suffix to JSON key (programs, programs2)

9. Generation Report

After generating, output a summary:

Markdown Spec → Page Generation Report
───────────────────────────────────────
Page title:  Welcome to Our Program
Sections:    5

  # │ Section        │ Component                   │ Source
  ──┼────────────────┼─────────────────────────────┼─────────
  1 │ Hero           │ HeroStandardApollo          │ explicit
  2 │ About          │ SectionApollo               │ explicit
  3 │ Programs       │ CardImageArticle × 2        │ explicit
  4 │ Testimonials   │ SectionTestimonialFalcon     │ explicit
  5 │ Footer         │ FooterStandard              │ explicit

Output:
  → pages/welcome.vue
  → assets/content/welcome.json

Warnings: none

10. Complete Example

Input Spec (spec/engineering.md)

# Engineering Program

## Hero
- title: "Bachelor of Engineering"
- subtitle: "Build the future with us"
- backgroundImage: /images/engineering-hero.jpg

## Program Tracks
- layout: 3-column grid
- items:
  - title: "Computer Science"
    image: /images/cs.jpg
    link: /tracks/cs
    body: "Learn algorithms, AI, and systems design."
  - title: "Electrical Engineering"
    image: /images/ee.jpg
    link: /tracks/ee
    body: "Power systems, circuits, and signal processing."
  - title: "Mechanical Engineering"
    image: /images/me.jpg
    link: /tracks/me
    body: "Thermodynamics, robotics, and manufacturing."

## Stats
- items:
  - label: "Graduates"
    value: "10,000+"
  - label: "Industry Partners"
    value: "200+"
  - label: "Research Labs"
    value: "45"

## Testimonials
- quote: "The hands-on labs prepared me for my career from day one."
- author: "Alex Rivera"
- role: "BS Computer Science, 2024"

## FAQ
- items:
  - question: "What are the admission requirements?"
    answer: "A strong foundation in math and science with a minimum GPA of 3.0."
  - question: "Are internships included?"
    answer: "Yes, all programs include a required industry internship in year 3."
  - question: "Is financial aid available?"
    answer: "Multiple scholarship and aid options are available for qualified students."

## Footer

Generated Output

Report:

Page title:  Engineering Program
Sections:    6

  # │ Section        │ Component                   │ Source
  ──┼────────────────┼─────────────────────────────┼─────────
  1 │ Hero           │ HeroStandardApollo          │ inferred
  2 │ Program Tracks │ CardImageArticle × 3        │ inferred
  3 │ Stats          │ SectionStatApollo           │ inferred
  4 │ Testimonials   │ SectionTestimonialFalcon     │ inferred
  5 │ FAQ            │ OverlapAccordionAtlas        │ inferred
  6 │ Footer         │ FooterStandard              │ inferred

Output:
  → pages/engineering.vue
  → assets/content/engineering.json

Warnings: none
Related skills
Installs
1
First Seen
Mar 17, 2026