6.0 KiB
6.0 KiB
Templates
Templates are complete website starting points. Props for content, default values for demo content, inline sections for freedom.
Quick Setup Flow
1. Define Sections
List the sections for the template:
NavbarFloating, HeroBillboardBrand, AboutTextSplit, ProductMediaCards,
FeaturesBento, TestimonialTrustCard, FaqSplitMedia, ContactCenter, FooterSimpleCard
2. Create Files
src/templates/[name]/
├── page.tsx
└── theme.css
3. Build page.tsx
Imports - UI components only, never sections:
import Button from "@/components/ui/Button";
import TextAnimation from "@/components/ui/TextAnimation";
import ImageOrVideo from "@/components/ui/ImageOrVideo";
import ScrollReveal from "@/components/ui/ScrollReveal";
import AutoFillText from "@/components/ui/AutoFillText";
import { Star, ArrowUpRight } from "lucide-react";
import "./theme.css";
Types - One type per section:
type TemplateProps = {
hero: { brand: string; description: string; /* ... */ };
about: { title: string; description: string; /* ... */ };
};
Default Props - Demo content:
const defaultProps: TemplateProps = {
hero: { brand: "Brand", description: "Description text" },
about: { title: "About Us", description: "..." },
};
Sections - Copy code from base section, add marker:
{/* === HERO (base: HeroBillboardBrand) === */}
<section>
{/* Inline code from HeroBillboardBrand.tsx */}
</section>
4. Build theme.css
Copy full structure from existing template, change only:
- Color values in
:root - Card style (
.card) - Button styles (
.primary-button,.secondary-button)
Required structure:
/* [Name] - [Theme Description] */
@import "tailwindcss";
@import "../../styles/masks.css";
@import "../../styles/animations.css";
:root {
/* @colorThemes/[lightTheme|darkTheme]/[themeName] */
--background: #...;
--card: #...;
--foreground: #...;
--primary-cta: #...;
--primary-cta-text: #...;
--secondary-cta: #...;
--secondary-cta-text: #...;
--accent: #...;
--background-accent: #...;
/* @layout/border-radius/rounded */
--radius: 1.5rem;
/* @layout/content-width/medium */
--width-content-width: clamp(40rem, 72.5vw, 100rem);
/* ... carousel, typography variables ... */
}
/* Mobile typography */
@media (max-width: 768px) { :root { /* ... */ } }
@theme inline { /* Tailwind mappings */ }
/* Base styles: *, html, body, h1-h6 */
/* WEBILD_CARD_STYLE */
/* @cards/[style-name] */
.card { /* ... */ }
/* WEBILD_PRIMARY_BUTTON */
/* @buttons/primary-button-styles/[style-name] */
.primary-button { /* ... */ }
/* WEBILD_SECONDARY_BUTTON */
/* @buttons/secondary-button-styles/[style-name] */
.secondary-button { /* ... */ }
5. Add Route
In src/pages/components/templates/:
- Create
[Name]TemplatePage.tsx - Add to
TemplateListPage.tsx
Structure
src/templates/
├── saas/
│ ├── page.tsx # Props + defaults + inline sections
│ └── theme.css # Colors, buttons, cards
└── restaurant/
├── page.tsx
└── theme.css
Template Pattern
// UI components (always imported)
import Button from "@/components/ui/Button";
import TextAnimation from "@/components/ui/TextAnimation";
import ImageOrVideo from "@/components/ui/ImageOrVideo";
import ScrollReveal from "@/components/ui/ScrollReveal";
import "./theme.css";
// Types
type SaasTemplateProps = {
hero: {
tag: string;
title: string;
description: string;
primaryButton: { text: string; href: string };
secondaryButton: { text: string; href: string };
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
features: { /* ... */ };
};
// Default content (demo data)
const defaultProps: SaasTemplateProps = {
hero: {
tag: "SaaS Platform",
title: "Build Modern Web Experiences",
description: "Create stunning websites...",
primaryButton: { text: "Get Started", href: "#contact" },
secondaryButton: { text: "Learn More", href: "#features" },
imageSrc: "https://...",
},
features: { /* ... */ },
};
// Template component
const SaasTemplate = ({
hero = defaultProps.hero,
features = defaultProps.features,
}: Partial<SaasTemplateProps>) => {
return (
<>
{/* === HERO (base: HeroSplit) === */}
<section aria-label="Hero section" className="...">
<TextAnimation text={hero.title} /* ... */ />
<Button text={hero.primaryButton.text} href={hero.primaryButton.href} />
<ImageOrVideo imageSrc={hero.imageSrc} videoSrc={hero.videoSrc} />
</section>
{/* === FEATURES (base: FeaturesMediaCards) === */}
<section aria-label="Features section">
{/* Inline code using features prop */}
</section>
</>
);
};
export default SaasTemplate;
Base Markers
Each section has a comment marking its base section:
{/* === HERO (base: HeroSplit) === */}
Find all templates using a section: grep -r "base: HeroSplit" src/templates/
theme.css
/* Colors from colorThemes.json */
:root {
--background: #050012;
--card: #040121;
--foreground: #f0e6ff;
--primary-cta: #c89bff;
--primary-cta-text: #050012;
--secondary-cta: #1d123b;
--secondary-cta-text: #f0e6ff;
--accent: #684f7b;
--background-accent: #65417c;
}
/* Buttons from theme-options/buttons/ */
.primary-button { /* ... */ }
.secondary-button { /* ... */ }
/* Cards from theme-options/cards/ */
.card { /* ... */ }
Creating a Template
- Create
src/templates/[name]/page.tsxandtheme.css - Define types matching your chosen sections
- Create defaultProps with demo content
- Copy section code inline (don't import sections)
- Add base markers to each section
- Build theme.css from colorThemes.json + theme-options/
Updating Templates
When a base section changes, find affected templates with grep and apply the fix to each inline section.
Not Included
- Not in registry.json (standalone files)
- No ThemeProvider
- No imported sections (inline code only)