---
name: generate-template
description: Generate professional multi-page templates for boopixel-builder. Two modes — (A) catalog seeding into app/seeds/templates.json, (B) update an existing project's pages directly via DB (postgres) when the user references a project id/url and wants its design rewritten. Use scripts at boopixel-strategy/scripts (openai_client, pexels, scrape_divi, scrape_divi_modules, screenshot_divi, site_scrape) to source visuals, copy and design ideas. Invoke when the user says "create a template", "novo template", "gerar template", "template para X", "atualize o template/design do projeto N", "atualize o projeto N".
---

# Template Generator Skill

Builds production-grade BooPixel Builder templates: multi-page sites with rich
layouts, real photos, generated copy and every available component used at
least once.

## Inputs

- **Niche / category** — agency, restaurant, SaaS, portfolio, e-commerce,
  fitness, real estate, wedding, podcast, NGO, course, etc. If not given, ask
  one question and stop.
- **Brand mood (optional)** — minimal, bold, dark, pastel, gradient. Default:
  pick the most fitting per niche.
- **Page set (optional)** — default per niche (see PATTERNS.md). Always at
  least Home + About + Contact.

## Workflow (always in this order)

1. **Discover.** Read `scripts/scrape_divi/data/divi_layouts.json` and
   `scripts/scrape_divi_modules/data/divi_modules.json`. Search them for the
   niche slug — e.g. for "yoga" find `yoga-studio`, `meditation`, etc. Note
   pack covers, layout names, descriptions for layout inspiration.
2. **(Optional) Visual reference.** If the user wants exact aesthetic match,
   run `python scripts/screenshot_divi/screenshot_divi.py --pack <slug>
   --limit 3` to grab full-page screenshots into
   `scripts/screenshot_divi/data/screenshots/`. Read those PNGs to ground
   color/typography/structure decisions.
3. **Plan pages.** Decide page list (at least 4: Home, About, Services or
   Menu or Shop, Contact). For each page, sketch sections inline before
   writing JSON.
4. **Generate copy.** Use `scripts/openai_client/openai_client.py` chat API to
   write punchy headlines, subtitles, feature bullets, testimonials and CTAs
   in the brand voice. See PROMPTS.md for tested prompts.
5. **Source images.** Use `scripts/pexels/pexels.py search` with niche-specific
   queries to fetch stock photos. Hero, gallery, team, testimonial avatars,
   collection covers all use real Pexels URLs. Never use `placehold.co`.
6. **Compose layout.** Build the JSON template per the schema in
   `app/seeds/templates.json` (boopixel-builder-api). Reuse helper structures
   from PATTERNS.md (hero, feature grid, pricing, testimonials, FAQ, contact,
   footer).
7. **Diversify components.** A template is incomplete if it does not use at
   least 12 distinct component types from COMPONENTS.md across its pages.
   Push for variety: blurbs, accordions, tabs, sliders, galleries, pricing,
   counters, social icons, maps, forms, etc.
8. **Wire collections.** Add at least one collection (services, posts, team,
   menu, products, projects). Provide ≥3 seed items with real Pexels images
   and OpenAI-generated copy. Reference it via a `repeater` node on the
   relevant page.
9. **Cross-link pages.** All `link` and `button` nodes in the navbar must use
   relative slugs (`home`, `about`, etc) — see PATTERNS.md for the navbar /
   footer recipe.
10. **Persist.** Append the final dict into the array at
    `app/seeds/templates.json` of `boopixel-builder-api`. Set unique `slug`,
    descriptive `name`, `category`, and a `thumbnail` (Pexels hero URL).
11. **Verify.** Run these checks AND **fail the run if any fail**:
    - JSON parse of the new template.
    - Count distinct component types — must be ≥ 14.
    - **Every single image URL must return HTTP 200 on a HEAD request.** Loop
      every URL referenced under `pages` and `collections.items[].data.image`
      / `thumbnail`. If any returns 404 or any non-2xx, replace the URL with
      another Pexels result for the same query and re-check until 200.
      A template is **not** allowed to ship with a broken image — even one
      404 invalidates the run. This is non-negotiable; Pexels regularly
      rotates / removes assets so trusting historical URLs is a bug.
    - Re-run image validation after the final write to disk.

## Mode B — Update existing project via DB

Trigger: user gives a project id (or `site.boopixel.com/projects/N`) and asks
to update the **template / design** of that project. The skill never hits the
production HTTP API — it talks to Postgres directly.

### Workflow

1. **Working directory.** Put every artifact under
   `boopixel-strategy/temp/`: scrape JSON, generated layouts, build script,
   URL validator, layout backups. Never pollute `scripts/output/` for Mode B.
2. **DB connection.** Read `DATABASE_URL` from
   `boopixel-builder-api/.env`. Schema:
   - `projects(id, name, slug, ...)`
   - `pages(id, project_id, slug, title, layout JSONB, updated_at, ...)`
3. **Snapshot current state.**
   - `SELECT id, name, slug FROM projects WHERE id=<id>`
   - `SELECT id, slug, title, length(layout::text) FROM pages WHERE project_id=<id> ORDER BY id`
   - Dump each `pages.layout` to `temp/backup_pN/page_<id>.json` before any
     change.
4. **Reference inputs.** If the user provides a public URL (live site to
   mirror) run `python scripts/site_scrape.py <url> --out temp/scrape_<slug>.json`.
   Re-use the scraped `images[]`, `headings[]`, `lists[]` and per-section
   text as canonical content. Asset URLs from the live site are allowed —
   you do not need to re-host into Pexels for Mode B since the user owns the
   reference site.
5. **Build layouts script.** Author `temp/build_layouts.py` with one
   function per page (`page_home`, `page_services`, `page_about`,
   `page_contact`, etc) returning `{"components": [...]}`. Share helpers
   (`navbar`, `footer`, palette consts). Add `--apply` flag that runs
   `UPDATE pages SET layout=%s::jsonb, updated_at=NOW() WHERE id=%s AND project_id=<id>`
   inside one psycopg transaction.
6. **Validate every URL.** Author `temp/validate_urls.py` — extract every
   `https?://...` from `temp/layouts/*.json` and HEAD-check. Fail hard if
   any URL is non-2xx. Re-run after every layout edit.
7. **Dry-run first.** Run the builder without `--apply` to write JSON files
   into `temp/layouts/page_<id>.json`, then validate URLs, then run
   `--apply`. Never apply on the first invocation.
8. **Verify.** After apply, run `SELECT id, length(layout::text) FROM pages
   WHERE project_id=<id>` and confirm row count and that layouts grew /
   changed as expected.

### Hard rules for Mode B

- **Do not delete or recreate pages.** Only `UPDATE pages.layout`. Page ids
  and slugs stay stable so existing routes keep working.
- **Backup every layout** to `temp/backup_pN/` before the apply step. Keep
  it until the user confirms the new design.
- **Localization follows the source site.** Mode B mirrors a real client
  site — if the live reference is in Portuguese, keep Portuguese. The
  English-only rule below applies only to Mode A (catalog templates).
- **One transaction per project.** All page UPDATEs in a single commit so a
  failure rolls back cleanly.
- **Never run `--apply`** until the dry-run JSON has been written and URL
  validation has passed for every image, video, link.
- **Never push code or commit** the generated `temp/` files. They are
  scratch — the user's deploy memory rule still holds.

## Hard rules

- **Never invent image URLs.** Only use URLs returned by Pexels or already
  persisted under the project's S3 / asset bucket.
- **Never use emojis as content** — wrap them as `icon` nodes (see
  COMPONENTS.md). The renderer no longer accepts emoji-as-text per project
  feedback memory.
- **Never write CSS in user-facing strings.** No raw `linear-gradient(...)`
  in `text` content; always use the `background` prop on a container.
- **All pages must work standalone.** Header, footer, hero, content,
  contact CTA on every page.
- **Use Icon nodes from the shipped library** (sparkles, zap, shield,
  rocket, etc.). Do not invent icon names.
- **Mobile-friendly first.** Avoid hard pixel widths on text columns. Prefer
  `maxWidth: '720px'` etc.
- **Localization.** ALL user-visible copy must be in English — every page, headline, subtitle, CTA, item name, navbar link, footer, alert, form label, success message. Never Portuguese. Even when the user mentions a Brazilian or Portuguese-language niche, write strings in English. Phone numbers, addresses and currency may stay localized only if the user explicitly asks.

## Diversity rules

Every new template **must look different from the previous five**. Before
writing JSON, pick one combination from each axis below — and avoid any
combination already in `app/seeds/templates.json`.

### Hero patterns (pick 1 per template)

1. **Photo + gradient mesh** — full-bleed photo with a 30–50% gradient
   overlay; centered eyebrow, headline, subtitle, CTA.
2. **Split asymmetric** — `widths: "5fr 4fr"` columns; left = headline +
   double CTA + trust badges, right = product mockup or photo.
3. **Stacked editorial** — narrow column (`maxWidth: 720px`), no photo,
   oversized serif-like headline, single CTA, then 3-up logo strip below.
4. **Background video / muted loop** — `video` node behind a translucent
   container; copy in white. Useful for restaurants, fitness, events.
5. **Pricing-forward** — small headline, prominent pricing card or CTA box
   right inside the hero block. Good for SaaS / e-commerce drops.
6. **Color block + product photo** — solid bold color on left
   (`background: #...`), product photo on right with `objectFit: contain`.
7. **Map-anchored** — for local businesses: half hero, half embedded map.
8. **Diagonal split** — container with non-rectangular feel achieved by
   mixing `radius`, `padding` and an inner offset image.

### Page structures (vary across pages even within one template)

- Standard centered (`maxWidth ~1200px`)
- Magazine wide (`maxWidth 1320px+`) with asymmetric columns
- Long-form narrow (`maxWidth 720px`) with big imagery between sections
- Sidebar-style (one tall column with sticky-ish navbar + content column)

### Header / navbar variation (mandatory)

Every template **must use a different navbar pattern from the previous five**. Pick one variant; never repeat the same combination of `nav layout × CTA button color × background tone` already in `app/seeds/templates.json`.

| Variant | Layout | When to pick |
|---|---|---|
| `top-bar` | Logo left, text links right | Editorial / quiet brands |
| `centered` | Logo centered above link row | Wedding, fashion, formal |
| `cta-pill` | Logo left, links right + bold CTA pill button | SaaS, e-commerce, donation, enrollment |
| `dark` | Dark bg navbar with bright accent CTA | Bold tech, conferences, drops |
| `announcement` | Top announcement strip + standard navbar below | Sales, launches, events |
| `borderless` | Transparent floating navbar over hero | Yoga, meditation, fashion, lifestyle |

**Each template's CTA button (when present) must use a unique accent color** — never reuse the same hex across two templates. Suggested accents per palette:
- Aurora → `#7c3aed`
- Ocean → `#0284c7`
- Sunset → `#f97316`
- Forest → `#16a34a`
- Night → `#fbbf24`
- Candy → `#ec4899`
- Mint → `#14b8a6`
- Peach → `#f59e0b`
- Warm → `#b66a4a`

Footer also gets a complementary accent — pick one that contrasts with navbar accent.

### Item detail pages (mandatory for any list)

Every template that ships a `repeater` over a collection **must** make each
item clickable to a detail page. This is automatic in the renderer:

- `Repeater` already wraps each card in `<a href="{itemHrefBase}/{itemId}">`
  when `itemHrefBase` is set.
- `TemplatePreviewPage` injects `itemHrefBase = /templates/{slug}/items/{collectionSlug}`
  for every repeater so the catalog preview is fully clickable.
- `PublicPreviewPage` injects `itemHrefBase = /preview/{user}/{project}/{collectionSlug}/items`
  so published projects route correctly.
- The detail UI is rendered by `TemplateItemPage` — generic, field-driven, no
  per-template work needed.

When designing a template with collections, **you do not need to author a
detail page** — but you must:

- Include at least one `image` field in the collection's `fields[]`
  (used as hero on the detail page).
- Provide a meaningful first text field (used as detail page title).
- Set sensible `slug` per item.

### Section structures (mix ≥ 4 distinct shapes per template)

- 3-up feature grid
- 2-col content (image left / right) — **alternate direction between sections**
- Repeater grid (cases, courses, products)
- Counter / metric strip
- Tabs OR accordion (FAQ-flavoured)
- Slider / gallery
- Pricing band
- Testimonial wall (3 cols) or single quote
- Color block CTA before footer

### Color & typography

- Pick **one** primary palette per template (Aurora / Ocean / Sunset / Forest
  / Night / Candy / Mint / Peach / Custom photo-derived).
- Choose **one** alternate accent for buttons / counters that contrasts.
- Vary headline sizes per page; avoid 56 everywhere. Try 40, 48, 56, 64,
  72, 88 across pages.
- Vary `maxWidth` per section — never 1100 everywhere.

### Component-mix targets

- Use ≥ 14 distinct types per template (up from 12 baseline).
- Always include ≥ 1 of: `slider`, `gallery`, `tabs`, `accordion`,
  `counter`, `pricing`, `testimonial`, `team`, `form`, `social`, `map`,
  `quote`, `alert`, `bar_counter`.
- Footer must include 3-column layout with social.

## Output persistence

Every run **must** write artifacts to
`boopixel-strategy/scripts/output/` so they can be reused:

- `output/pexels/{slug}.json` — list of `{role, query, urls, alts}` chosen
- `output/openai/{slug}.json` — every `{prompt, response}` pair generated
- `output/templates/{slug}.json` — the full template JSON before merging
- `output/runs/{timestamp}-{slug}.md` — short note: niche, palette, hero
  pattern picked, distinct types count, image count

Before starting a run, read `output/templates/{slug}.json` if present and
reuse — don't regenerate copy or images already on disk.

## Five reference templates (contract)

Each flagship template **uses a different hero pattern, max-width and
section rhythm**. Treat this as the locked-in signatures — new templates
must avoid duplicating any row's combination of palette, max-width and
hero type.

| slug | niche | hero pattern | max-width | section rhythm |
|------|-------|--------------|-----------|----------------|
| `studio-aurora-agency` | Creative agency | (1) Photo + gradient mesh — AURORA | 1320px (wide magazine) | 3-up case repeater · counter strip · dark CTA band |
| `nimbus-saas` | SaaS | (3) Stacked editorial narrow + 4-up logo strip — OCEAN | 960px (centered narrow) | feature grid 3-up · pricing band · FAQ accordion |
| `photon-portfolio` | Portfolio | (6) Color block + portrait photo — CANDY | 880px (long-form narrow) | alternating 2-col image/text · gallery before footer |
| `verde-bistro` | Restaurant | (7) Map-anchored half-hero — FOREST | 1180px (standard) | menu repeater 2-up · tabs hours-by-day · contact + map strip |
| `lumen-commerce` | E-commerce | (2) Split asymmetric (drop + product) — AURORA | 1340px (wide magazine) | products grid 4-up · drop CTA band · gallery |

When refreshing one of these five, **never duplicate another row's
combination**. Pick a different combo from the hero-patterns and
page-structures matrices above.

## Reference files (read on demand)

- `COMPONENTS.md` — every renderer component, props, defaults, when to use
- `PATTERNS.md` — reusable section recipes: navbar, hero, feature grid,
  pricing, testimonial wall, FAQ, footer, contact band
- `PROMPTS.md` — OpenAI prompts for copy generation (taglines, hero subtitle,
  pricing copy, testimonials, CTAs, FAQs)
- `EXAMPLES.md` — fully assembled example template (compact) for reference

## When in doubt

Be **maximalist**: more sections, more components, richer collections. Then
trim. A template with 7 pages × 8 sections × varied components beats a thin
3-page boilerplate every time.
