Pick a named layout per section. No code changes needed.
Every major section of the landing page ships in three layouts. Pick one by name per section — no code changes required.
Loop's landing page is assembled from sections: nav, hero, social proof, features, testimonials, pricing, FAQ, CTA, and footer. Each one has three interchangeable designs, and each one has its own set of three names.
// src/config/site.ts
sectionVariants: {
nav: "flat",
hero: "centered",
social: "marquee",
features: "tabbed",
testimonials: "masonry",
pricing: "toggle",
faq: "tabbed",
cta: "centered",
footer: "columns",
}
Swap any value for a sibling from that key's list and reload. The section renderer reads the name and mounts the matching layout.
The valid names are declared once, at the top of the same file:
export const SECTION_VARIANT_NAMES = {
nav: ["flat", "grouped", "mega"],
hero: ["centered", "split", "typographic"],
social: ["marquee", "grid", "quotes"],
features: ["cards", "zigzag", "tabbed"],
testimonials: ["masonry", "carousel", "videoSplit"],
pricing: ["cards", "toggle", "matrix"],
faq: ["twoColumn", "stacked", "tabbed"],
cta: ["centered", "split", "fullbleed"],
footer: ["columns", "minimal", "newsletter"],
} as const;
Each key is typed to its own three names, so hero: "matrix" is a compile error rather than a silent fallback to the default layout.
The three options aren't cosmetic tweaks — they're genuinely different layouts:
cards is a six-up grid, zigzag three alternating full-width rows, tabbed a single panel with a vertical tab railcards is a plain three-up, toggle adds the monthly/annual switch, matrix drops the cards for a full comparison tabletwoColumn deals the questions into two accordion columns, stacked keeps one narrow column, tabbed filters by categoryVARIANTS.md, at the project root, describes all 48 names — sections and pages — and names the file each one lives in.
You don't have to edit the config to explore variants. The built-in TweakPanel lets you flip every section live in the browser, storing your choice in the vs-variants cookie. Once you find a combination you like, copy the names back into sectionVariants so they ship as the default. An unknown name in the cookie is ignored and the config default is used.
Beyond sections, seven marketing pages each ship in three full-page layouts, driven by pagesConfig.variants and the vs-page-variants cookie. The mechanism mirrors section variants exactly:
// src/config/pages.ts
variants: {
about: "centered", // centered | roster | manifesto
customers: "grid", // grid | panels | filtered
careers: "list", // list | grid | sidebar
community: "grid", // grid | chat | forum
api: "stacked", // stacked | tabbed | sidebar
contact: "split", // split | grid | stacked
roadmap: "kanban", // kanban | timeline | list
}
If you've settled on one layout per section and want to slim the bundle, delete the unused variant components and replace the if (variant === "…") ladder with a direct import. tests/variants.test.ts goes with them. The config field can stay or go — nothing else depends on it.