AI Template Generation

Required reading for AI clients that need to create reusable Liquid section templates and row templates through the API.

Give the AI a detailed brief

AI results depend on the instructions you provide. Describe your audience, goals, required content, tone, calls to action, constraints, and design direction. Vague or incomplete instructions can produce generic, inaccurate, or otherwise sub-optimal results.

When to create a template

Use Liquid templates when the built-in section and row renderers cannot express the layout cleanly, but the content still needs to stay editable in StaticPagesApi.

An AI builder should understand both template levels: section templates render full page bands, while row templates render reusable child components inside row-driven sections.

Templates should be reusable layout patterns, not one giant page-sized HTML blob. A good AI-generated page usually mixes built-in sections and rows with 1-3 Liquid-backed moments for custom polish.

  • Use templateable_type Section for a full page band such as a custom hero, proof band, metrics strip, feature showcase, comparison band, or CTA.
  • Use templateable_type Row for repeated custom cards, slides, stats, timeline items, proof quotes, custom FAQ rows, or nested components.
  • Create or copy templates before creating the page sections/rows that use them.
  • Use type_of for built-in renderers. Use template_id plus template_data for Liquid-backed renderers. Never send both type_of and template_id on the same section or row.
  • If a section uses a Liquid template_id, every row inside that section must also use a Liquid row template_id. Do not mix built-in row type_of values inside a Liquid-backed section.
  • Prefer copying a close default template before creating a new one from scratch.

Copyable AI instruction

Paste this into an AI client that can call your StaticPagesApi instance.

You are creating Liquid templates for StaticPagesApi through the API.

First fetch:
1. GET /docs/ai-instructions
2. GET /docs/ai-page-generation
3. GET /docs/ai-template-generation
4. GET /api/v1/schema
5. GET /api/v1/templates
6. GET /api/v1/template_library

Reuse an owned template when it fits. Copy a close default template with POST /api/v1/template_library/:id/copy before creating a new one from scratch.

Create templates with POST /api/v1/templates only for reusable layout patterns that built-in sections/rows cannot express cleanly.

Choose one renderer per section or row:
- Built-in renderer: send type_of.
- Liquid renderer: send template_id and template_data.
- Never send type_of and template_id together.

If a section uses a Liquid template_id, every row inside that section must also use a Liquid row template_id. Do not mix built-in row type_of values inside Liquid-backed sections. Render child row templates from the section template with row.rendered_html.

Keep template CSS scoped under one unique root class. Do not write broad selectors such as body, h1, p, .container, .row, .card, or .btn.

Declare editable values in field_schema and read them from section.data.* or row.data.*. Use normal section and row fields for content such as header, subheader, body_html, CTAs, and images.

After creating or copying a template, attach it to sections or rows with template_id and pass custom values through template_data.

Required API sequence

This is the safest sequence for an AI client.

curl https://staticpageapi.com/docs/ai-template-generation

curl https://staticpageapi.com/api/v1/schema \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

curl https://staticpageapi.com/api/v1/templates \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

curl https://staticpageapi.com/api/v1/template_library \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

curl https://staticpageapi.com/api/v1/templates \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d @template.json

Create a section template

A section template renders a whole page band. It can loop through rows, read editable template_data from section.data, and compose Liquid row templates with row.rendered_html.

{
  "templateable_type": "Section",
  "key": "ai_proof_band",
  "name": "AI Proof Band",
  "description": "A reusable proof band with editable eyebrow, heading, body, and repeated rows.",
  "category": "Proof",
  "keywords": ["proof", "testimonials", "ai-generated"],
  "status": "active",
  "template_html": "<section class=\"ai-proof-band\"><div class=\"ai-proof-band__inner\">{% if section.data.eyebrow %}<p class=\"ai-proof-band__eyebrow\">{{ section.data.eyebrow }}</p>{% endif %}<h2>{{ section.header }}</h2>{% if section.body_html %}<div class=\"ai-proof-band__body\">{{ section.body_html }}</div>{% endif %}<div class=\"ai-proof-band__grid\">{% for row in rows %}{{ row.rendered_html }}{% endfor %}</div></div></section>",
  "template_css": ".ai-proof-band { padding: 5rem 0; background: #f8fafc; color: #111827; } .ai-proof-band__inner { width: min(1120px, calc(100% - 2rem)); margin: 0 auto; } .ai-proof-band__eyebrow { margin: 0 0 .75rem; color: #0f766e; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; } .ai-proof-band h2 { margin: 0 0 1rem; max-width: 760px; font-size: clamp(2rem, 4vw, 3.25rem); line-height: 1.05; } .ai-proof-band__body { max-width: 720px; color: #475569; } .ai-proof-band__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; margin-top: 2rem; } .ai-proof-band__card { min-width: 0; padding: 1.25rem; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; box-shadow: 0 10px 30px rgba(15, 23, 42, .08); } .ai-proof-band__card h3 { margin: 0 0 .75rem; font-size: 1.1rem; } .ai-proof-band__source { margin: 1rem 0 0; color: #64748b; font-weight: 600; }",
  "field_schema": {
    "fields": [
      { "key": "eyebrow", "label": "Eyebrow", "type": "text", "default": "Customer proof" }
    ]
  },
  "default_data": {
    "eyebrow": "Customer proof"
  },
  "sample_data": {
    "section": {
      "header": "Teams are launching better pages faster",
      "body_html": "<p>Use this sample to preview the template before attaching it to a real section.</p>",
      "data": { "eyebrow": "Customer proof" }
    },
    "rows": [
      { "header": "Cleaner first drafts", "body_html": "<p>The reusable band keeps layout consistent while copy stays editable.</p>", "subheader": "Marketing team" }
    ]
  }
}

Create a row template

A row template renders one repeated item inside a compatible section. Use row.data for custom fields and normal row fields for editable content.

{
  "templateable_type": "Row",
  "key": "ai_metric_tile",
  "name": "AI Metric Tile",
  "description": "A reusable metric tile row for stats, outcomes, or proof points.",
  "category": "Metrics",
  "keywords": ["metric", "stat", "proof"],
  "status": "active",
  "template_html": "<article class=\"ai-metric-tile\"><p class=\"ai-metric-tile__value\">{{ row.data.value }}</p><h3>{{ row.header }}</h3>{% if row.body_html %}<div class=\"ai-metric-tile__body\">{{ row.body_html }}</div>{% endif %}</article>",
  "template_css": ".ai-metric-tile { min-width: 0; height: 100%; padding: 1.25rem; border-radius: 8px; background: #111827; color: #fff; } .ai-metric-tile__value { margin: 0 0 .5rem; color: #5eead4; font-size: 2.25rem; font-weight: 800; line-height: 1; } .ai-metric-tile h3 { margin: 0 0 .75rem; font-size: 1.1rem; } .ai-metric-tile__body { color: #cbd5e1; }",
  "field_schema": {
    "fields": [
      { "key": "value", "label": "Metric value", "type": "text", "default": "42%" }
    ]
  },
  "default_data": {
    "value": "42%"
  },
  "sample_data": {
    "row": {
      "header": "More qualified launches",
      "body_html": "<p>Reusable template rows keep custom content structured.</p>",
      "data": { "value": "42%" }
    }
  }
}

Attach templates in a page blueprint

Once the template exists, create sections or rows that use template_id. Leave type_of out for template-backed records. If the section uses template_id, all rows inside it must also use row template_id values.

{
  "slug": "ai-template-demo",
  "status": "draft",
  "meta_title": "AI Template Demo",
  "sections": [
    {
      "template_id": 123,
      "header": "Early customers are seeing the difference",
      "body": "<p>This section uses a Liquid section template, not a built-in type_of renderer.</p>",
      "template_data": {
        "eyebrow": "Proof"
      },
      "rows": [
        {
          "template_id": 456,
          "header": "The page felt custom immediately.",
          "subheader": "Founder",
          "body": "<p>The structure stayed editable, but the layout had a stronger custom look.</p>",
          "template_data": {
            "value": "5/5"
          }
        }
      ]
    },
    {
      "type_of": "rows_in_columns",
      "header": "Reusable metric rows",
      "columns": 3,
      "rows": [
        {
          "template_id": 456,
          "header": "Faster first draft",
          "body": "<p>Template rows make repeated custom pieces easy to reuse.</p>",
          "template_data": {
            "value": "3x"
          }
        }
      ]
    }
  ]
}

Update an existing template

AI clients can refine organization-owned templates after visual review. Keep updates scoped and preserve field_schema keys that existing sections or rows already use.

curl https://staticpageapi.com/api/v1/templates/123 \
  -X PATCH \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template_css": ".ai-proof-band { padding: 5rem 0; background: #f8fafc; color: #111827; } .ai-proof-band__inner { width: min(1120px, calc(100% - 2rem)); margin: 0 auto; }"
  }'

Template safety checklist

Run through this before sending template JSON.

  • Use one unique root class for every template, then scope all CSS under that class.
  • Avoid broad CSS selectors, fixed heights, negative margins, hidden overflow, absolute/fixed positioning, and transform hacks.
  • Keep text and background colors readable with at least 4.5:1 contrast.
  • Use field_schema for every custom editable value the template reads from section.data or row.data.
  • Use section.header, section.subheader, section.body_html, row.header, row.subheader, and row.body_html for normal editable content.
  • Use rows, rows_by_group, or rows_by_column only in section templates.
  • Use row templates for repeated items instead of duplicating custom HTML inside raw_html rows.
  • If a section is Liquid-backed, make every child row Liquid-backed too. Use row.rendered_html in the section template to output each row template.
  • Include analytics attribute strings on template-rendered links when those links should emit customer-owned events.
  • After creating the template, attach it with template_id and template_data. Do not send type_of on that same section or row.