# Markdown 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.

- Skill: `chandima/markdown-spec-to-page` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add chandima/markdown-spec-to-page`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chandima/markdown-spec-to-page/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: chandima (https://skillmd.com/u/chandima)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chandima/markdown-spec-to-page

---


# 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:

```markdown
# 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`

```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`

```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`)

```markdown
# 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
```

