Skip to content
OTFotf
All posts

Landing templates: rebrand every section from one site.ts, not a ghost regenerate

D
DaveAuthor
8 min read
Landing templates: rebrand every section from one site.ts, not a ghost regenerate

Every landing template in the OTF pack puts brand copy and imagery in one typed file: src/content/site.ts. Section components under src/sections/ read that object — they do not hard-code headlines, region cards, or photo alts. That split is the rebrand contract. Edit site.ts (and the shipped AI prompts that point agents at it), run bun run build, deploy the static dist/ to Cloudflare Pages. You keep the architecture. You do not ask a sandbox to regenerate a lookalike page you cannot open in git.

This post is that site.ts rebrand path. It is not the general "own the repo" overview — that lives at /blog/landing-templates-kit-own-the-repo. It is not the broader "how to build a landing page with AI" guide — that is /blog/how-to-build-a-landing-page-with-ai. Those posts cover ownership and assembly order. Here the question is narrower: after checkout, how do you rebrand Summit (or Aura, or any of the fifteen) without turning sections into a second content store an agent invents beside the typed config.

What the landing pack already ships

OTF lists the fifteen industry templates on https://otf-kit.dev/templates. Each is sold standalone at $9; all fifteen are included in the kit bundle. Every template is a self-contained Vite + React + TypeScript app that builds to static output — no backend, no accounts, no hosted editor lock-in. Live demos you can click before buying include https://summit.otf-kit.dev (travel / expeditions) and https://aura.otf-kit.dev (SaaS / app landing).

Canonical pack facts (from the internal landing-pack index buyers mirror after sync):

  • Fifteen templates: Summit, Lumen, Maison, Solène, Tempo, Volt, Monolith, Resonance, Orbit, Gallery, Atelier, Frame, Still, Apex, Aura
  • Shared layout: src/sections/ (one file per section), src/content/site.ts (all copy + imagery), src/theme/ (theme system), src/lib/ (shared HeroCanvas, Reveal, SlotImage), src/index.css (design system)
  • WebGL hero via shared HeroCanvas — lazy-loaded, reduced-motion-safe, pauses off-screen
  • Theme system — light/dark plus palettes, switchable from the nav, persisted to localStorage
  • AI-tool config — CLAUDE.md, .cursorrules, and tested prompts under ai/prompts/ (including swap-copy.md and swap-imagery.md on Summit)
  • Build: bun installbun devbun run build → deploy-ready dist/

Summit is the locked reference pattern; templates 02–15 are re-skins of that structure. When you learn the Summit file map, you learn the pack.

Why ghost regenerates fail buyers (and agents)

Three failure modes show up the week after purchase:

  1. Copy baked into JSX — an agent rewrites Hero.tsx and Regions.tsx with new strings. The next prompt that edits site.ts does nothing visible, and two sources of truth drift.
  2. Sandbox regenerate — a prompt asks a hosted builder to "make a new travel landing like Summit." You get a screenshot-shaped page with no site.ts, no HeroCanvas reduced-motion gate, and no Cloudflare Pages dist/ you control.
  3. Parallel content module — an agent invents content/pages.json or a CMS stub beside the typed site object. Sections start importing the new store; the shipped prompts that say "edit site.ts only" become lies.

The honest path is the one Summit documents in CLAUDE.md: all page content lives in src/content/site.ts as one typed site object. Section components never hard-code copy, so a content change should not touch any sections/*.tsx file.

One-way path: edit site.ts so section tiles update; no parallel pages.json

11 production screens. Login, database, payments — all wired.

The SaaS Dashboard Kit ships everything already connected. Nothing to set up. Live demo at saas.otf-kit.dev.

See the live demo

The owned rebrand contract: site.ts in, sections stay architecture

Treat rebrand as a content write against one typed object:

  1. Identity — brand name, glyph, nav links, and CTAs live on site.brand / site.nav (and the matching CTA blocks). Do not fork a second brand constant inside Nav.tsx.
  2. Hero — eyebrow, title lines, subtitle, primary/secondary CTAs, stats, videoSrc, and videoPoster image slot stay on site.hero. Clear videoSrc to fall back to the still poster; under prefers-reduced-motion the canvas is not mounted and the poster <img> renders.
  3. Section arrays — regions, experiences, lodges, trails, journal (Summit's nine-section page order) keep the same shape and field counts the layouts expect. The shipped swap-copy.md prompt says it explicitly: keep array lengths so grids stay full; change alts with the copy; do not edit src/sections/.
  4. Imagery — every photo position is a typed ImageSlot: { src, gradient, alt }. Empty src uses the gradient stand-in; a real URL or imported asset renders the photo. Summit ships curated assets via a photo() helper pointed at the OTF landing-pack CDN — swap src for your own URLs when you rebrand.
  5. AI handoff — open Cursor or Claude Code on the buyer repo. Prefer the tested prompts under ai/prompts/ (swap-copy.md, swap-imagery.md, plus theme/recolor prompts) over a free-form "rebuild the landing." Point the agent at CLAUDE.md and .cursorrules so hard constraints stay in force: OTF tokens only, WebGL scoped to HeroCanvas, no inventing a parallel content store.
  6. Build and deploybun run build produces static dist/. Deploy to Cloudflare Pages (build command bun run build, output dist) or upload dist/ directly. Custom domain is a Pages setting, not a sandbox publish button.

Illustrative edit shape (labeled sketch — not a private dump of a buyer's live file):

// Illustrative site.ts rebrand — edit the typed site object only
import type { SiteContent } from "./site"; // your template's exported types

export const site: SiteContent = {
  brand: { name: "Brevik", glyph: "B" },
  nav: { links: ["Regions", "Experiences", "Journal"], cta: "Plan a trip" },
  hero: {
    eyebrow: "Guided fjord expeditions",
    titleLines: [{ text: "Where the water" }, { text: "holds still.", italic: true }],
    subtitle: "Small-group kayaking on Norway's quiet inlets.",
    primaryCta: "Find an expedition",
    secondaryCta: "Watch the film",
    // videoSrc / videoPoster / stats stay on the same hero object
  },
  // regions, experiences, lodges, trails, journal, bookingCta, footer…
  // Keep array lengths; update ImageSlot.alt with the new copy
};

After the edit, run bun dev to verify sections still fill, then bun run build and confirm dist/ is what Cloudflare Pages will serve.

Keep ai/prompts as the rebrand path, not a second page

After you clone a buyer repo (Summit example: otf-kit/summit-landing after sync), do not prompt "regenerate a landing page." Prefer a bounded job:

Read CLAUDE.md, .cursorrules, and ai/prompts/swap-copy.md.
1) Rewrite site.ts copy for [your business] — same field shapes and array lengths
2) Update ImageSlot.alt text to match; leave section JSX untouched
3) Do not invent content/pages.json or hard-code strings in sections/*.tsx
4) Keep HeroCanvas reduced-motion behavior; do not add 3D outside lib/HeroCanvas.tsx
5) Run bun run build and confirm dist/ is the deploy artifact

For imagery-only swaps, use ai/prompts/swap-imagery.md the same way: change ImageSlot.src (and alts), keep layout code. For palette work, use the theme system already wired in src/theme/ and src/index.css — nav switcher + localStorage — instead of pasting hex into section files. Aura's live page even boots palette/mode from localStorage before first paint so the first frame matches the buyer's last choice.

bun run build produces owned dist/ for Cloudflare Pages, not a sandbox preview

Acceptance checks before you call the rebrand done

Run these before you tell a teammate (or an agent) the page is "rebranded":

  1. Grep the sections — no brand-new marketing strings in src/sections/ that should have lived in site.ts.
  2. Shape intact — region/experience/journal arrays still match the counts the grids expect (Summit's swap-copy prompt: 4 regions, 3 experiences, 3 trails, 3 journal articles).
  3. Hero honesty — with reduced motion enabled, you see the poster, not a stuck WebGL canvas; with motion on, the shared displacement hero still lazy-loads.
  4. Theme survives refresh — palette/mode choice from the nav still restores from localStorage.
  5. Static artifactbun run build exits clean and dist/ is what you point Cloudflare Pages at — not a temporary preview URL from a sandbox.
  6. Prompt library still trueai/prompts/swap-copy.md still describes the real edit surface. If you invented a second content module, delete it and put the copy back in site.ts.

That checklist is the difference between owning a template and renting a regenerate. The pack already paid for the architecture: nine Summit sections (nav → hero → regions → experiences → lodges → trails → journal → booking CTA → footer), shared HeroCanvas, theme switcher, and AI configs. Your job after buy is to change the typed content object and ship dist/.

What this is not

If you need a different industry skin, start from the matching live demo on the templates catalog, confirm the same site.ts + sections/ split, and run the same prompt discipline. The filenames stay familiar across the fifteen because Summit locked the pattern on purpose.

Sources

kitstemplatesarchitecture
OTF SaaS Dashboard Kit

Ship the product, not the setup.

  • 11 production screens — auth, billing, team, analytics, settings
  • Real database, payments, and login — all wired on day 1
  • AI configs pre-tuned so your agent extends instead of regenerates