# MedGen Page Skeleton Contract For CMX

## Permanent Public Source

MedGen should read the current CMX contract before each generation task:

- Human/markdown contract: `https://cmx-medgen-contract.pages.dev/contract.md`
- Machine-readable page format registry: `https://cmx-medgen-contract.pages.dev/page-format-registry.json`
- Public landing page: `https://cmx-medgen-contract.pages.dev/`

If CMX adds a new page, edits an existing page module structure, changes accepted HTML, or changes a page-specific response format, the public contract and registry above must be updated before MedGen is asked to generate that page.

## Purpose

This is the default instruction CMX sends to MedGen for generated sites.

CMX generates the site skeleton: routes, page types, module order, global header/footer, CSS spacing, schema, canonical URLs, preview, approval and deploy gates.

MedGen fills that skeleton. It must not return only plain text. It should return a ready CMX page response where headings, paragraphs, lists, FAQ, CTA labels, image suggestions, alt text, sources and relations are already placed into the approved page/module structure.

CMX then validates the response, mounts allowed fragments into CMS JSON, builds preview, asks for approval and deploys.

## Important Boundary

MedGen returns internal page/module markup, not a full website document.

Allowed:

- localized `h1`, `h2`, `h3`, paragraphs, lists, FAQ and table fragments;
- module props with generated text;
- `html` strings for approved body slots;
- image suggestions and image alt text;
- anchors only when CMX provided or requested a route/relation.

Not part of the MedGen response:

- `<!doctype>`, `<html>`, `<head>`, `<body>`;
- global site header/footer;
- CSS, JS, inline styles or event attributes;
- forms, inputs, scripts, iframes or deployment code;
- Cloudflare/GitHub/VPS settings.

Spacing, visual rhythm and responsive layout are owned by CMX CSS. MedGen may return the approved structural tags; CMX applies the final visual spacing.

## Canonical Response Shape

Preferred response path:

```text
result.cmx_page
```

Backward-compatible fallback:

```text
article.body
```

Expected JSON:

```json
{
  "article": {
    "title": "Localized page title",
    "h1": "Localized H1",
    "seo_title": "Localized SEO title",
    "seo_description": "Localized SEO description",
    "body": "<section><h2>Fallback section</h2><p>Fallback HTML fragment.</p></section>",
    "blocks": [],
    "metadata": {}
  },
  "result": {
    "cmx_page": {
      "version": "cmx-page-skeleton-v1",
      "content_type": "technical_page",
      "route": "/editorial-policy/",
      "locale": "bg_BG",
      "seo": {
        "title": "Localized SEO title",
        "description": "Localized SEO description"
      },
      "modules": [
        {
          "type": "page_header",
          "props": {
            "h1": "Generated H1",
            "lead": "Generated lead paragraph."
          }
        },
        {
          "type": "rich_text",
          "props": {
            "html": "<section><h2>Generated H2</h2><p>Generated paragraph.</p><ul><li>Generated list item.</li></ul></section>"
          }
        }
      ],
      "faq": [],
      "media": [],
      "relations": {}
    },
    "fields": {},
    "sections": [],
    "faq": [],
    "media": [],
    "relations": {}
  }
}
```

## Shared Site Rules

- Each public site has one root locale. For `bg_BG`, Bulgarian content lives at `/`, not `/bg/`.
- CMX provides the route, content path, content type and available relations.
- MedGen fills only the requested page target.
- Index pages summarize collections; individual products, reviews, guides and experts are generated by separate tasks.
- If a product review references a new expert/reviewer, MedGen should return enough expert data to create or update that expert page.
- Page-specific rules live in `page-format-registry.json`. The registry is more precise than this prose document when there is a conflict.

## Home Page Skeleton

CMX route: `/`
CMX path: `content/pages/home.json`
CMX content type: `home_page`

Required modules:

```json
{
  "type": "home_page",
  "modules": [
    {
      "type": "home_hero",
      "props": {
        "brand_slogan": "{{unique localized slogan}}",
        "h1": "{{homepage H1}}",
        "lead": "{{homepage lead}}",
        "image": "{{hero image suggestion}}",
        "image_alt": "{{hero image alt}}"
      }
    },
    {
      "type": "trust_cards",
      "props": {
        "items": [
          {
            "title": "{{trust card heading}}",
            "body": "{{trust card text}}"
          }
        ]
      }
    },
    {
      "type": "homepage_sections",
      "props": {
        "catalog_heading": "{{catalog widget heading}}",
        "reviews_heading": "{{reviews widget heading}}",
        "experts_heading": "{{experts widget heading}}",
        "methodology_heading": "{{methodology widget heading}}"
      }
    }
  ]
}
```

MedGen generates the slogan, H1, lead, widget headings, image suggestion, FAQ and SEO fields. CMX renders the final cards, carousels and links.

## Technical Page Skeleton

Routes:

```text
/about/
/methodology/
/editorial-policy/
/sources/
/affiliate-disclosure/
/contact/
/faq/
/how-to-use/
/suggest-supplement/
/disclaimer/
/privacy-policy/
/terms/
/cookie-policy/
```

CMX content type: `technical_page`

Example response for a technical page:

```json
{
  "result": {
    "cmx_page": {
      "version": "cmx-page-skeleton-v1",
      "content_type": "technical_page",
      "route": "/affiliate-disclosure/",
      "locale": "bg_BG",
      "seo": {
        "title": "{{localized SEO title}}",
        "description": "{{localized SEO description}}"
      },
      "modules": [
        {
          "type": "page_header",
          "props": {
            "h1": "{{page H1}}",
            "lead": "{{short page intro}}"
          }
        },
        {
          "type": "rich_text",
          "props": {
            "html": "<section><h2>{{section heading}}</h2><p>{{paragraph}}</p><p>{{paragraph}}</p></section><section><h2>{{section heading}}</h2><ul><li>{{list item}}</li><li>{{list item}}</li></ul></section>"
          }
        },
        {
          "type": "related_pages",
          "props": {
            "items": [
              {
                "route": "/editorial-policy/",
                "label": "{{localized anchor label}}"
              }
            ]
          }
        }
      ],
      "faq": [
        {
          "question": "{{FAQ question}}",
          "answer_html": "<p>{{FAQ answer}}</p>"
        }
      ]
    }
  }
}
```

For `/contact/`, MedGen fills the upper text modules only. CMX keeps the contact form module below the MedGen content.

## Product Card Skeleton

Admin first provides product basics: product name, brand, product image, price, offer URL, currency, route and locale.

CMX route: `/bady/{product_slug}/`
CMX path: `content/pages/supplements/{product_slug}.json`
CMX content type: `product_card`

Example response:

```json
{
  "result": {
    "cmx_page": {
      "version": "cmx-page-skeleton-v1",
      "content_type": "product_card",
      "route": "/bady/{product_slug}/",
      "locale": "bg_BG",
      "seo": {
        "title": "{{product SEO title}}",
        "description": "{{product SEO description}}"
      },
      "modules": [
        {
          "type": "product_hero",
          "props": {
            "name": "{{product name}}",
            "brand": "{{product brand}}",
            "summary_html": "<p>{{short product summary}}</p>",
            "image": "{{product image URL or suggestion}}",
            "image_alt": "{{product image alt}}",
            "price_label": "{{localized price label}}",
            "seller_label": "{{localized buy button label}}"
          }
        },
        {
          "type": "product_details",
          "props": {
            "html": "<section><h2>{{details heading}}</h2><p>{{long product description}}</p><dl><dt>{{fact label}}</dt><dd>{{fact value}}</dd></dl></section>"
          }
        },
        {
          "type": "product_notes",
          "props": {
            "safety_note_html": "<p>{{safety note}}</p>",
            "affiliate_note_html": "<p>{{affiliate note}}</p>",
            "review_cta_label": "{{localized review CTA}}",
            "review_route": "/obzory/{product_slug}-review/"
          }
        }
      ]
    }
  }
}
```

## Product Review Skeleton

Product review should be generated after the product card exists, because it needs the product route, product context and image.

CMX route: `/obzory/{product_slug}-review/`
CMX path: `content/pages/technical/{product_slug}-review.json`
CMX content type: `product_review`

Example response:

```json
{
  "result": {
    "cmx_page": {
      "version": "cmx-page-skeleton-v1",
      "content_type": "product_review",
      "route": "/obzory/{product_slug}-review/",
      "locale": "bg_BG",
      "seo": {
        "title": "{{review SEO title}}",
        "description": "{{review SEO description}}"
      },
      "modules": [
        {
          "type": "review_header",
          "props": {
            "h1": "{{review H1}}",
            "lead": "{{review lead}}",
            "summary_html": "<p>{{review summary}}</p>",
            "hero_image": "{{review hero image suggestion}}",
            "hero_image_alt": "{{review hero image alt}}"
          }
        },
        {
          "type": "review_verdict",
          "props": {
            "rating": "{{rating}}",
            "verdict_html": "<p>{{verdict}}</p>",
            "pros": ["{{pro}}"],
            "cons": ["{{con}}"]
          }
        },
        {
          "type": "review_body",
          "props": {
            "html": "<section><h2>{{section heading}}</h2><p>{{section body}}</p></section><section><h2>{{section heading}}</h2><ul><li>{{list item}}</li></ul></section>"
          }
        },
        {
          "type": "review_relations",
          "props": {
            "product_route": "/bady/{product_slug}/",
            "product_anchor_label": "{{localized product anchor}}",
            "expert_route": "/experts/{expert_slug}/",
            "expert_anchor_label": "{{localized expert anchor}}"
          }
        }
      ],
      "faq": [
        {
          "question": "{{FAQ question}}",
          "answer_html": "<p>{{FAQ answer}}</p>"
        }
      ],
      "sources": []
    }
  }
}
```

## Expert / Reviewer Skeleton

Expert profile can be generated after a review task if the review references a new reviewer.

CMX route: `/experts/{expert_slug}/`
CMX path: `content/pages/authors/{expert_slug}.json`
CMX content type: `expert_profile`

Example response:

```json
{
  "result": {
    "cmx_page": {
      "version": "cmx-page-skeleton-v1",
      "content_type": "expert_profile",
      "route": "/experts/{expert_slug}/",
      "locale": "bg_BG",
      "seo": {
        "title": "{{expert SEO title}}",
        "description": "{{expert SEO description}}"
      },
      "modules": [
        {
          "type": "author_header",
          "props": {
            "name": "{{expert name}}",
            "role": "{{expert role}}",
            "bio_html": "<p>{{short bio}}</p>",
            "portrait_image": "{{portrait image suggestion}}",
            "portrait_image_alt": "{{portrait alt}}"
          }
        },
        {
          "type": "author_body",
          "props": {
            "html": "<section><h2>{{qualification heading}}</h2><p>{{full bio}}</p></section><section><h2>{{reviewed materials heading}}</h2><ul><li>{{review reference}}</li></ul></section>"
          }
        },
        {
          "type": "author_disclosure",
          "props": {
            "html": "<p>{{disclosure text}}</p>"
          }
        }
      ],
      "relations": {
        "reviews_route": "/obzory/",
        "same_as_links": []
      }
    }
  }
}
```

## Guide Article Skeleton

CMX route: `/guides/{guide_slug}/`
CMX path: `content/pages/technical/{guide_slug}.json`
CMX content type: `guide_article`

Example response:

```json
{
  "result": {
    "cmx_page": {
      "version": "cmx-page-skeleton-v1",
      "content_type": "guide_article",
      "route": "/guides/{guide_slug}/",
      "locale": "bg_BG",
      "seo": {
        "title": "{{guide SEO title}}",
        "description": "{{guide SEO description}}"
      },
      "modules": [
        {
          "type": "article_header",
          "props": {
            "h1": "{{guide H1}}",
            "lead": "{{guide lead}}"
          }
        },
        {
          "type": "article_body",
          "props": {
            "html": "<section><h2>{{section heading}}</h2><p>{{section body}}</p></section>"
          }
        }
      ],
      "faq": []
    }
  }
}
```

## Index Page Skeleton

Index pages receive intro SEO content and widget copy, not full product/review/expert content.

Supported index targets:

- `/bady/`
- `/obzory/`
- `/experts/`
- `/guides/`
- `/popular-products/`
- `/sravneniya/`
- `/brands/`
- `/vitamins-minerals/`

Required slots:

- `h1`;
- `lead`;
- `intro_html`;
- `widget_headings`;
- `empty_state_text`;
- `faq`;
- `seo`.

## Pipeline Order

1. Admin creates or selects a site.
2. CMX generates route skeleton, theme and unique visual system.
3. For products, admin enters product basics first.
4. MedGen fills product card skeleton.
5. MedGen fills review skeleton using product route and context.
6. MedGen fills reviewer/expert skeleton if needed.
7. MedGen can fill technical/index/guide skeletons independently.
8. CMX validates returned modules and allowed HTML.
9. CMX builds preview.
10. Operator approves.
11. CMX deploys.
