Skip to content

Pages & layouts

varsha uses Astro’s file-based routing and provides a MarketingLayout component that gives every marketing page a consistent header, navigation, footer, theme system, and attribution.

Every .astro file in src/pages/ automatically becomes a route. The file path determines the URL:

FileURL
src/pages/index.astro/
src/pages/about.astro/about
src/pages/pricing.astro/pricing
src/pages/blog/index.astro/blog
src/pages/blog/[slug].astro/blog/:slug (dynamic)

Every marketing page should use MarketingLayout:

src/pages/about.astro
---
import MarketingLayout from '../components/MarketingLayout.astro';
---
<MarketingLayout
title="About Us"
description="Learn about our company and mission."
canonicalPath="/about/"
>
<main class="page">
<section class="hero">
<h1>About Us</h1>
<p>Your hero subtitle goes here.</p>
</section>
<section class="section">
<div class="container">
<h2>Section heading</h2>
<p>Section content goes here.</p>
</div>
</section>
</main>
</MarketingLayout>

The MarketingLayout component accepts the following props:

PropTypeRequiredDescription
titlestringYesPage title (used in <title> and OG tags)
descriptionstringYesMeta description for SEO and social sharing
canonicalPathstringYesCanonical URL path (e.g., /about/)
ogType'website' | 'article'NoOpen Graph type (default: 'website')
ogImagestringNoCustom OG image path (default: /assets/og-card-v8.png)
ogImageAltstringNoAlt text for OG image (default: 'varsha')

For article-type pages, use ogType: 'article':

src/pages/blog/[slug].astro
<MarketingLayout
title={post.data.title}
description={post.data.description}
canonicalPath={`/blog/${post.slug}/`}
ogType="article"
>
<!-- article content -->
</MarketingLayout>

varsha’s global CSS (public/css/style.css) provides utility classes for common page patterns:

<section class="hero">
<h1>Your headline here</h1>
<p>A compelling subtitle that explains your value proposition.</p>
<div class="hero-actions">
<a href="/docs/install/" class="button button--primary">Get started</a>
<a href="/docs/" class="button button--secondary">Read docs</a>
</div>
</section>
<section class="section">
<div class="container">
<h2>Features</h2>
<div class="feature-grid">
<div class="feature-card">
<h3>Fast by default</h3>
<p>Astro ships zero JavaScript by default for static pages.</p>
</div>
<div class="feature-card">
<h3>Beautiful themes</h3>
<p>18+ built-in color themes with one-click switching.</p>
</div>
<div class="feature-card">
<h3>Content first</h3>
<p>Markdown and MDX with full content collections support.</p>
</div>
</div>
</div>
</section>

When you create a new page, add it to the navigation in src/components/MarketingLayout.astro. There are two navigation areas to update:

  1. Desktop nav: .nav-links div
  2. Mobile nav: .nav-menu-panel div (inside the <details> element)
src/components/MarketingLayout.astro
<div class="nav-links">
<a href="/">Home</a>
<a href="/about/">About</a>
<a href="/pricing/">Pricing</a>
<a href="/blog/">Blog</a>
<a href="/docs/">Docs</a>
</div>

Keep the mobile and desktop navigation links in sync to ensure a consistent experience across devices.

The BuiltWith component renders the required attribution link. It is automatically included at the bottom of MarketingLayout and Starlight’s custom Footer. You do not need to add it manually to pages.

If you create a completely custom layout without MarketingLayout, include the attribution:

---
import BuiltWith from '../components/BuiltWith.astro';
---
<!-- Your layout content -->
<BuiltWith variant="corner" />

Available variants:

VariantAppearance
footerInline footer credit (used in Starlight footer)
cornerFloating corner badge (default on marketing pages)
docsDocumentation-specific styling

Create a 404.astro page in src/pages/ for a custom 404 experience:

src/pages/404.astro
---
import MarketingLayout from '../components/MarketingLayout.astro';
---
<MarketingLayout title="Page not found" description="The page you are looking for does not exist." canonicalPath="/404/">
<main class="page">
<section class="hero">
<h1>404</h1>
<p>Page not found.</p>
<a href="/" class="button button--primary">Go home</a>
</section>
</main>
</MarketingLayout>

For pages generated from data (like blog posts), use Astro’s dynamic routes with getStaticPaths():

src/pages/blog/[slug].astro
---
import { getCollection } from 'astro:content';
import MarketingLayout from '../../components/MarketingLayout.astro';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<MarketingLayout
title={post.data.title}
description={post.data.description}
canonicalPath={`/blog/${post.slug}/`}
ogType="article"
>
<main class="page">
<article class="section">
<div class="container">
<h1>{post.data.title}</h1>
<time datetime={post.data.pubDate.toISOString()}>
{post.data.pubDate.toLocaleDateString()}
</time>
<Content />
</div>
</article>
</main>
</MarketingLayout>

Customization

Brand your site with colors, fonts, metadata, and configuration options.

Customization →

Design system

Understand the design tokens and component philosophy.

Design system →

Components reference

See all available components and their props.

Components →