Skip to content

Documentation

This template is built AI-first. Every task below is shown two ways — tell your AI assistant what you want, or do it manually. Pick the approach that works for you.

Getting Started

Download the template, install dependencies, and start the dev server.

With AI

Download and unzip the template. Open the folder in your AI coding tool (Claude Code, Cursor, Windsurf, etc.) and say:

Install all dependencies and start the dev server. Open the browser at localhost:4321 when ready.

Manual

Unzip the download, open a terminal in the project folder, and run:

npm install
npm run dev

Then open http://localhost:4321 in your browser.

Building Blocks

The template uses a three-tier architecture. Everything you build with falls into one of these tiers.

TierWhatCountLocation
ComponentsSmall UI primitives (Button, Dialog, Tabs...)11src/components/ui/
SectionsFull page sections (Hero, Pricing, FAQ...)28src/components/sections/
PagesComplete page templates (SaaS, Portfolio...)15+src/pages/

Tier 1: Component

Small, reusable React UI primitives from shadcn/ui + Radix UI. Use with client:load for interactivity.

---
import { Button } from "@/components/ui/button";
---
<Button client:load variant="outline" size="lg">Click me</Button>

Tier 2: Section

Full-width page blocks that combine layout, typography, and content. Drop them into any page and pass content as props.

---
import FAQ from "@/components/sections/FAQ.astro";
---
<FAQ
  title="Frequently Asked Questions"
  faqs={[
    { question: "How does it work?", answer: "Sign up and start building." }
  ]}
/>

Tier 3: Page

Complete pages that assemble multiple sections with a layout. Copy a template and customize the props.

---
import BaseLayout from "@/layouts/BaseLayout.astro";
import Hero from "@/components/sections/Hero.astro";
import Features from "@/components/sections/Features.astro";
import CTA from "@/components/sections/CTA.astro";
---
<BaseLayout title="My Page">
  <Hero title="Welcome" subtitle="..." />
  <Features title="Features" features={[...]}  />
  <CTA title="Get Started" description="..."
    cta={{ href: "/signup", label: "Sign Up" }}  />
</BaseLayout>

Replace Content

This template ships with fictional "Apex AI" content. Replace it with your real product, company name, and copy.

With AI

The fastest way: describe your product and let the AI rewrite all content at once.

My product is [YOUR PRODUCT] — [one sentence what it does]. Replace all fictional "Apex AI" content across the site with content for my product. Update the homepage hero, all page titles, meta descriptions, Header brand name, and Footer tagline. Keep the same section structure.

For more control, go page by page:

Rewrite the homepage (src/pages/index.astro) for [YOUR PRODUCT]. Keep all sections but replace headlines, descriptions, feature lists, and CTA labels with content that matches my product.

Manual

Content lives in the page files (not in section components). Edit these files:

Homepage

src/pages/index.astro

Hero title, subtitle, CTA labels, section props

Header

src/components/Header.astro

Brand name (line 29: "Apex AI"), nav labels

Footer

src/components/Footer.astro

Brand name, tagline, link labels

Other pages

src/pages/*.astro

Features, Pricing, About, etc. — each page has its own section props

Key rule: Change content in page files where sections are used, not in the section component definitions.

Change Font

The template uses Geist (variable weight) by default. Swap it for any web font.

With AI

Switch the font from Geist to Inter. Download the Inter variable font woff2 file, place it in public/fonts/, update the @font-face declaration in src/styles/globals.css, and update the --font-sans variable in the @theme block.

Manual

Three steps in src/styles/globals.css:

/* 1. Replace @font-face */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2')
    format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

/* 2. Update @theme */
@theme {
  --font-sans: 'Inter', system-ui, sans-serif;
}

/* 3. Place your .woff2 file in: */
/* public/fonts/Inter-Variable.woff2 */

Use variable fonts (single .woff2) for best performance. Download from Google Fonts or Fontsource.

Customize Theme & Colors

All colors are CSS custom properties in one file. Change them and the entire site updates.

With AI

Change the color scheme to match my brand: primary color is electric blue (#0066FF), background should be pure white, and cards should have a very light blue tint. Update both light and dark mode in globals.css. Make sure contrast ratios meet WCAG AA (4.5:1 for text).

The AI updates all tokens in both modes and verifies contrast compliance.

Manual

Edit src/styles/globals.css:

@theme {
  --color-primary:
    oklch(55% 0.25 260);
  --color-primary-foreground:
    oklch(98% 0 0);
}

.dark {
  --color-primary:
    oklch(70% 0.2 260);
  --color-primary-foreground:
    oklch(10% 0 0);
}

OKLCH format: oklch(lightness% chroma hue). Use oklch.com to pick colors.

Design Tokens

The full design system is controlled through CSS custom properties. Here's every token and what it does.

TokenUsed forTailwind class
--color-backgroundPage backgroundbg-background
--color-foregroundMain texttext-foreground
--color-primaryButtons, links, accentsbg-primary, text-primary
--color-primary-foregroundText on primary buttonstext-primary-foreground
--color-cardCard backgroundsbg-card
--color-mutedSubtle backgrounds, code blocksbg-muted
--color-muted-foregroundSecondary text, descriptionstext-muted-foreground
--color-borderAll bordersborder-border
--color-accent-orangeHighlights, badgesbg-accent-orange, text-accent-orange
--color-destructiveError states, delete buttonsbg-destructive
--radiusGlobal border radiusrounded-md

Update Navigation

Add, remove, or rename menu items in the header and footer.

With AI

Add a "Resources" dropdown to the header navigation with links to /docs (Documentation), /changelog (Changelog), and /blog (Blog). Also add these links to the footer.

To remove items:

Remove the "Careers" link from both the header navigation and the footer. I don't need a careers page.

Manual

Header — edit the dropdowns object in src/components/Header.astro:

const dropdowns = {
  Product: [
    { href: '/features', label: 'Features' },
    { href: '/pricing', label: 'Pricing' },
  ],
  Resources: [
    { href: '/docs', label: 'Docs' },
    { href: '/changelog', label: 'Changelog' },
  ],
};

Footer — edit footerLinks in src/components/Footer.astro:

const footerLinks = {
  pages: [
    { href: '/features', label: 'Features' },
    { href: '/pricing', label: 'Pricing' },
  ],
  system: [
    { href: '/contact', label: 'Contact' },
    { href: '/privacy', label: 'Privacy' },
  ],
};

Create a New Page

The template uses file-based routing. Every .astro file in src/pages/ becomes a route.

With AI

Create a new "About Us" page at /about with a hero section, a team grid showing 4 team members, and a values section. Add it to the header navigation under Company and to the footer.

The AI creates the page, imports sections, adds SEO meta tags, and updates navigation.

Manual

Create src/pages/about.astro:

---
import BaseLayout from "@/layouts/BaseLayout.astro";
import Team from
  "@/components/sections/Team.astro";
---

<BaseLayout
  title="About Us"
  description="Meet the team behind..."
>
  <section class="pt-36 pb-12 px-6">
    <div class="mx-auto max-w-3xl">
      <h1 class="text-4xl font-semibold mb-6">
        About Us
      </h1>
    </div>
  </section>
  <Team />
</BaseLayout>

The file name is the URL: about.astro/about. Don't forget to add the link to Header and Footer.

Layout Reference

LayoutUse Case
BaseLayoutContent pages, standard pages (boxed, max-w-5xl)
FullWidthLayoutShowcase, gallery, docs (full viewport width)
MinimalLayout404, maintenance, standalone landing pages (no nav)
AuthLayoutLogin, signup, password reset (split screen)
ArticleLayoutLong-form content (reading-optimized typography)

Add a Section to a Page

The template ships with 28 pre-built sections. Import them into any page and pass your content as props.

With AI

Add a pricing section to the homepage with 3 tiers: Free ($0, for personal projects, 1 project + community support), Pro ($19/month, for teams, unlimited projects + priority support), and Enterprise ($49/month, for organizations, everything in Pro + SSO + dedicated account manager). Place it after the features section.

The AI imports the Pricing component, configures the tiers array, and places it at the right position.

Manual

Import the component and pass your data as props:

---
import Pricing from
  "@/components/sections/Pricing.astro";

const tiers = [
  {
    name: "Free",
    price: "$0",
    description: "For personal projects",
    features: ["1 project", "Support"],
    cta: { href: "/signup", label: "Start" },
  },
  // ... more tiers
];
---

<Pricing title="Pricing" tiers={tiers} />

See all available sections at /sections.

Replace or Remove a Section

Swap out sections on a page or remove ones you don't need.

With AI

To replace:

On the homepage, replace the ProblemStatement section with a Testimonials section showing 3 customer quotes.

To remove:

Remove the LogoCloud section from the homepage. I don't have partner logos yet. Also remove the import if it's no longer used anywhere.

Manual

Sections are imported and placed in page files. To swap or remove, edit the page:

---
// src/pages/index.astro
import Hero from "...";
// Remove: import LogoCloud from "...";
import Testimonials from
  "@/components/sections/Testimonials.astro";
---

<BaseLayout title="Home">
  <Hero ... />
  <!-- Removed: <LogoCloud /> -->
  <Testimonials
    testimonials={[
      { quote: "...", name: "...",
        role: "..." },
    ]}
  />
</BaseLayout>

Remove both the import statement and the component tag in the template.

Create a Custom Component

Build your own section components following the existing patterns and conventions.

With AI

Create a new "How It Works" section component with 3 numbered steps. Each step has a title and description. Follow the existing project patterns (TypeScript props, Tailwind classes, semantic HTML). Place it on the homepage after the Hero.

The AI reads AGENTS.md to understand conventions and creates a component with typed props, proper imports, and consistent styling.

Manual

Create src/components/sections/HowItWorks.astro:

---
interface Props {
  title?: string;
  steps: {
    title: string;
    description: string;
  }[];
}

const { title = "How It Works", steps } =
  Astro.props;
---

<section class="py-20 px-6">
  <div class="max-w-7xl mx-auto">
    <h2 class="text-3xl font-semibold mb-12">
      {title}
    </h2>
    <div class="grid md:grid-cols-3 gap-8">
      {steps.map((step, i) => (
        <div>
          <span class="text-4xl font-bold
            text-muted-foreground/30">
            {String(i + 1).padStart(2, '0')}
          </span>
          <h3 class="text-xl font-semibold
            mt-4 mb-2">
            {step.title}
          </h3>
          <p class="text-muted-foreground">
            {step.description}
          </p>
        </div>
      ))}
    </div>
  </div>
</section>

Add Images

Astro auto-optimizes images (resize, format conversion, lazy loading). Use the <Image /> component for best performance.

With AI

Add a full-width hero image to the about page. I've placed it at src/assets/images/team-photo.jpg. Use Astro's Image component with responsive widths (400, 800, 1200), lazy loading, and a descriptive alt text. The image should span the full width with a max height of 50vh.

Manual

Place images in src/assets/images/ (optimized) or public/ (served as-is):

---
import { Image } from 'astro:assets';
import teamPhoto from
  '@/assets/images/team-photo.jpg';
---

<!-- Optimized (recommended) -->
<Image
  src={teamPhoto}
  alt="Team at the annual retreat"
  widths={[400, 800, 1200]}
  sizes="calc(100vw - 3rem)"
  loading="lazy"
  class="w-full h-[50vh] object-cover"
/>

<!-- From public/ (no optimization) -->
<img
  src="/images/logo-partner.png"
  alt="Partner company logo"
  loading="lazy"
/>

Rule: Always add descriptive alt text. Use alt="" only for purely decorative images.

SEO Setup

Set meta tags, Open Graph images, and structured data for every page.

With AI

Review and update the SEO for all pages. For each page, set a unique title (under 60 chars), meta description (150-160 chars), and appropriate Open Graph type. Update the site URL in astro.config.mjs to my production domain. Make sure auth pages (login) have noindex set.

For OG image generation:

Create a 1200x630px Open Graph image for the homepage. Replace public/cover.png with a branded version showing our product name and tagline.

Manual

Each page sets SEO via layout props:

<BaseLayout
  title="Features - Your Product"
  description="Discover how Your Product
    helps teams ship faster."
  image="/og-features.png"
  type="website"
/>

Checklist:

  • 1.Set site in astro.config.mjs to your domain
  • 2.Unique title + description per page
  • 3.OG image at public/cover.png (1200x630)
  • 4.Update robots.txt sitemap URL
  • 5.Auth pages: add noindex={true}

Build & Deploy

Build a production-optimized version of your site and deploy it to any static hosting provider.

With AI

Build the project for production and check if there are any errors or warnings. Fix anything that comes up.

For deployment:

Deploy this project to Vercel. Make sure the site URL in astro.config.mjs matches my production domain first.

Manual

Build and preview locally:

npm run build
npm run preview

Deploy the dist/ folder to any static host:

  • Vercel: Push to GitHub, import in dashboard
  • Netlify: Connect repo, auto-detects Astro
  • Cloudflare:npx wrangler pages deploy dist

Connect Your Forms

The contact form ships without a backend. Connect it to a form service in minutes.

Formspree

  1. Create a free account at formspree.io
  2. Create a new form and copy the endpoint URL
  3. In src/pages/contact.astro, replace the form action:
<form action="https://formspree.io/f/YOUR_ID" method="POST">

Netlify Forms

  1. Deploy to Netlify (forms are auto-detected)
  2. Add the netlify attribute to the form tag:
<form name="contact" netlify method="POST">

Submissions appear in your Netlify dashboard under Forms.

Configure Your AI with PROJECT.md

Tell your AI assistant about your project — brand voice, domain rules, preferences. This file overrides all defaults.

With AI

Set up PROJECT.md for my project. My product is [YOUR PRODUCT], a [what it does] for [target audience]. Brand voice: [professional/casual/playful]. Primary color: [your hex]. Language: [English/German/etc]. Any text you generate should match this tone and use these rules.

Once set up, every AI assistant (Claude Code, Cursor, Copilot, Windsurf) will read PROJECT.md automatically and follow your rules.

Manual

Open PROJECT.md in the project root and add your rules:

## Brand
Product: Acme Analytics
Tagline: "Insights that move teams"
Audience: B2B SaaS, product managers

## Voice
Professional, clear, no jargon.
US English only.

## Design
Primary color: #2563EB
Keep the warm off-white background.
Use rounded-full on all buttons.

## Rules
- All forms must validate with Zod
- Never use "Sign Up" — use "Get Started"
- Footer must link to status.acme.com

Priority: PROJECT.md > AGENTS.md > README.md. Your rules always win.

AI Architecture

This template includes a hybrid AI system that works across all coding assistants.

How It Works

When you open this template in an AI coding tool, the tool reads AGENTS.md to understand the project. This file contains all conventions, patterns, and rules — so the AI knows how to write code that fits.

FileRead byPurpose
AGENTS.mdAll AI toolsConventions, patterns, architecture
PROJECT.mdAll AI toolsYour project overrides (highest priority)
system/globals/All AI tools8 design knowledge files (colors, typography, spacing...)
system/prompts/All AI tools (copy-paste)7 portable self-audit quality checks
.claude/Claude Code onlyAgents, commands, skill chains (optional power features)

Self-Audit Prompts

Copy-paste quality checks in system/prompts/ that work in any AI tool — ChatGPT, Gemini, Cursor Chat, Claude.

  • Tokens — hardcoded colors, inline styles, OKLCH compliance
  • Accessibility — WCAG 2.1 AA, contrast, keyboard nav
  • Performance — Lighthouse, Core Web Vitals, images
  • SEO — meta tags, structured data, heading hierarchy
  • Dark Mode — token parity, contrast in both modes
  • Responsive — breakpoints, overflow, touch targets
  • Cascade — design token consistency across tiers

Quality Gates

Run quality checks before launch — with AI or by following the skill chains manually.

With AI

Run a pre-launch review on my project. Check design token consistency, accessibility (WCAG AA), performance, SEO meta tags, dark mode, and responsive layout. Report issues grouped by severity.

In Claude Code, /plenum triggers parallel review agents. In other tools, the AI uses the self-audit prompts from system/prompts/.

Manual

Each task type follows a skill chain — a sequence of domain checks:

TaskSkill Chain
New Sectionui-design → tailwind → a11y → qa
New Pageastro → ui-design → seo → a11y → qa
Theme Changetailwind → ui-design → a11y
Pre-Launchall 7 self-audit prompts

Project Structure

A quick reference of key directories and what they contain.

apex-template/
├── src/
│   ├── components/
│   │   ├── sections/      28 pre-built page sections (3 Hero variants + 25 more)
│   │   └── ui/            11 shadcn/ui components (Button, Card, Dialog, Accordion...)
│   ├── layouts/           Page templates (Base, FullWidth, Auth, Minimal, Article)
│   ├── pages/             File-based routing — each .astro file = one route
│   ├── styles/globals.css Design tokens, colors, Tailwind @theme config
│   ├── assets/images/     Source images (auto-optimized by Astro)
│   ├── registry.json      Machine-readable component catalog
│   └── lib/utils.ts       Utility functions (cn helper)
├── public/                Static assets (fonts, logos, favicons)
├── system/
│   ├── globals/           8 design knowledge files (canonical reference)
│   └── prompts/           7 portable self-audit prompts
├── AGENTS.md              AI assistant instructions (all tools)
├── PROJECT.md             Your project-specific AI overrides
├── astro.config.mjs       Astro + Vite + integrations config
└── package.json           Dependencies and npm scripts

Want to dive deeper? Check out the source code and full README on GitHub.

View on GitHub