Guide

Guide

Your site is configured and ready - now for the everyday work. Expand any topic below to see how content flows through Stardrive and which options unlock the more powerful features.

Writing blog postsMarkdown files with a powerful frontmatter

Each blog post is a Markdown file in ./src/content/articles/ (organised per language). The frontmatter unlocks the special functionality:

Frontmatter options

titlestringrequired
The article title.
publishDatedaterequired
The publication date, used for ordering and display.
updateDatedate
An optional "last updated" date.
excerptstring
A short teaser used in lists and previews.
draftbooleanspecial
Keeps the post out of production builds while you work on it.
featuredbooleanspecial
Highlights the post wherever featured articles are surfaced.
llmsTxtbooleanspecial
Includes the post in the generated llms.txt (when addArticles is set to selected in the theme config).
externalCanonicalstringSEO
Points the canonical URL elsewhere - ideal for cross-posted content.
slugstring
A cleaner custom slug. Include the language code, e.g. en/my-post.
i18nSlugobject
Only needed when the filename differs per language. Map each locale to its slug, e.g. { de: "de/mein-post", en: "en/my-post" }.
image.filepathlocal
A local, build-optimized hero image. Reference it via the @images/… alias, e.g. @images/content/articles/webmcp.jpg (recommended).
image.urlstringexternal
An external hero image URL as an alternative to a local file.
image.altstring
Alt text for the hero image.
tagsstring[]
Tags for filtering and related content.
categoriesstring[]
Categories the article belongs to.
authorobject
Author name and optional url.
tocDepthnumber
How many heading levels the table of contents includes.
src/content/articles/en/webmcp-changes-the-game.md
---
title: "How WebMCP changes the game"
publishDate: 2026-01-15
excerpt: "A short teaser for lists and previews."
draft: false
featured: true
slug: "en/webmcp-changes-the-game"
externalCanonical: "https://example.com/original-post"
image:
file: "@images/content/articles/webmcp.jpg" # local, optimized (recommended)
# url: "https://cdn.example.com/webmcp.jpg" # external alternative
alt: "Illustration of an AI agent using tools"
tags: ["ai", "webmcp"]
categories: ["engineering"]
---
Your Markdown body goes here.

Commit from anywhere

Because posts are just files, another system can commit Markdown into your repository - every push triggers a fresh build.

Headless CMS option

You can pull posts dynamically from a headless CMS like Directus or Strapi, but that requires bigger adjustments to the content layer.

Embedding YouTube videos

Paste a YouTube URL on its own line in the Markdown body and Stardrive converts it into a privacy-friendly (no-cookie) responsive embed. Both youtube.com/watch?v=… and youtu.be/… links are supported, and optional t, list, and title query params are passed through. The visitor's locale is automatically used for the captions language (cc_lang_pref).

Write the URL without the https://www prefix - a full URL (e.g. https://www.youtube.com/watch?v=…) is treated as a regular external link instead of an embed.

Adding FAQ entriesJust like blog posts, only shorter

FAQ answers live in ./src/content/faq-answers/ as Markdown files - the same idea as blog posts, but with a lightweight schema. The question becomes the headline and the Markdown body is the answer.

Frontmatter options

questionstringrequired
The question text shown in the accordion.
categorystring
Groups the entry so it can be filtered on the FAQ page.
publishDatedate
An optional publication date.
updateDatedate
An optional "last updated" date.
draftbooleanspecial
Hides the entry from production builds.
llmsTxtbooleanspecial
Includes the entry in the generated llms.txt.
src/content/faq-answers/en/self-hosting.md
---
question: "Can I self-host Stardrive?"
category: "general"
draft: false
---
Absolutely. Stardrive outputs a static site by default and runs on any host.
Adding integrationsShow how your product connects to other services

When to use it

Use the integrations section when your product can be used or combined with other services - think automations, data sync, or native connectors. It gives visitors a browsable catalogue.

Structure

Content lives in ./src/content/integration-options/. Think category first, then services: the type field is the category - it both groups the entries and drives the routing (e.g. native, zapier, make, n8n). Each service is then its own Markdown file inside that category.

Frontmatter options

typestringrequired
The category the service belongs to - also used for routing, e.g. native, zapier, make.
servicestringrequired
The service name, e.g. Google Sheets.
titlestringrequired
The integration title.
descriptionstring
A short description of the integration.
urlstring
Link to the integration details or setup page.
publishDatedate
An optional publication date.
updateDatedate
An optional "last updated" date.
draftbooleanspecial
Hides the entry from production builds.
slugstring
A cleaner custom slug. Include the language code, e.g. en/google-sheets.
i18nSlugobject
Only needed when the filename differs per language, e.g. { de: "de/…", en: "en/…" }.
logo.filepath
The service logo via the @images/… alias (use an SVG as a component-friendly file).
logo.urlstring
An external logo URL as an alternative to a local file.
logo.altstring
Alt text for the logo.
src/content/integration-options/en/google-sheets.md
---
type: "native"
service: "Google Sheets"
title: "Sync data to Google Sheets"
description: "Push records into a spreadsheet in real time."
url: "https://example.com/integrations/google-sheets"
logo:
file: "@images/content/integration-options/google-sheets.svg"
alt: "Google Sheets logo"
---

Same service in multiple categories

A service can appear under more than one type (category) - just create one Markdown file per category. In that case the files must have different filenames, otherwise the entries collide. Give each a distinct name (or use a hashed filename plus a custom slug).

Pricing tablesFlexible tiers, taxes and billing periods

Not wired up yet

The pricing table is on the roadmap. This section explains the intended model so you can plan ahead.

You will be able to define different prices per tier - monthly, annually andlifetime - and show them with or without taxes. The presentation is fully configurable, so you decide what customers see.

Monthly

Annually

Lifetime

Pull pricing dynamically

We recommend sourcing this data from a backend that talks to a provider like Stripe or Paddle. That way taxes can be shown dynamically based on the visitor's location.

EventsMarkdown events, or mirror them from Add to Calendar PRO

Events work like blog posts: Markdown files in ./src/content/events/, i18n-ready, with one-click "Add to Calendar" buttons, time zones and rich detail pages.

Frontmatter options

titlestringrequired
The event title.
publishDatedaterequired
The publication date, used for ordering and display.
startDatedaterequired
When the event begins.
endDatedaterequired
When the event ends.
updateDatedate
An optional "last updated" date.
descriptionstring
Short description used for the shareable event (use the Markdown body for richer detail).
allDayboolean
Marks the event as all-day.
timeZonestring
A valid IANA time zone, e.g. Europe/Berlin.
locationstring
Where the event takes place.
organizerobject
Organizer name and email.
rrulestring
A recurrence rule, e.g. FREQ=WEEKLY;BYDAY=MO,WE,FR.
icsFilestring
Point to a static .ics file instead of generating one dynamically.
slugstring
A cleaner custom slug. Include the language code, e.g. en/my-event.
i18nSlugobject
Only needed when the filename differs per language, e.g. { de: "de/…", en: "en/…" }.
draftbooleanspecial
Keeps the event out of production builds while you work on it.
llmsTxtbooleanspecial
Includes the event in the generated llms.txt.
image.filepathlocal
A local, build-optimized image via the @images/… alias.
image.urlstringexternal
An external image URL as an alternative to a local file.
image.altstring
Alt text for the image.
src/content/events/en/ai-webinar.md
---
title: "Live webinar: Building for the AI age"
publishDate: 2026-02-01
startDate: 2026-02-20T17:00:00
endDate: 2026-02-20T18:00:00
timeZone: "Europe/Berlin"
location: "Online"
description: "Join our product team for a hands-on session."
organizer:
name: "Stardrive Team"
email: "events@example.com"
# rrule: "FREQ=WEEKLY;BYDAY=WE" # optional recurrence
image:
file: ./webinar.jpg
alt: "Webinar cover"
---
A rich, Markdown description of the event.

Mirror from Add to Calendar PRO

Alternatively, connect Add to Calendar PROwith a filter on a specific event group. Events are then mirrored into the page dynamically - marketing can make changes in the web app with no re-deployment needed.

Great for webinars, corporate events, and investor-relations calendars.

Header optionsSticky bar, overlay, close button, or none at all

The header is one of the most flexible parts of Stardrive. It can be a sticky bar, an overlay that morphs on scroll, a minimal close button, or disappear entirely. Options flow through three layers, from the page down to the component that renders the bar:

1. Page

Pass a header prop

Each page hands a header object to the Layout. This is where you override behaviour per route.

2. Layout

default.astro / article.astro

The Layout reads the page's header prop, merges it with its own hardcoded defaults, and forwards the result to the Header component.

3. Component

header.astro

The component receives the final props and renders one of four variants based on the combination.

Two levels of defaults

There is no header key in theme.config.ts. Defaults are coded in two places - both are plain code, so you edit them directly.

Layout default

In ./src/layouts/default.astro (and article.astro), some values are hardcoded and passed to every page that uses the Layout. These are the things you almost never want to change per page:

  • github - the GitHub link shown on the right (currently points at the Stardrive repo).
  • ctaButton - the call-to-action button (defaults to the "Sign up" label and the signup route).
  • isHome - forwarded from the Layout so the logo is not linked on the homepage.

Edit these directly in the Layout file to change them globally.

Component default

In ./src/components/layout/header.astro, the variant is chosen from the combination of fixed, overlay, and closeIcon. When none of those are set, the component falls back to the CSS-fixed variant - a header that sticks to the top while scrolling and hides once the footer covers most of the viewport. That fallback lives in the component's own logic, not in a config file.

Change a default once, apply everywhere

Because the defaults live in code, a single edit in the Layout (for github / ctaButton) or the component (for the fallback variant) propagates to every page. You only need the per-page header prop when a route should behave differently.

Overriding on the page

Pass a header object to the Layout to override the defaults for a single page. Only the keys you set are applied - everything else falls back to the Layout and component defaults.

src/pages/my-page.astro
---
import Layout from "@layouts/default.astro";
<Layout
title="My page"
header={{
overlay: true, // start as an overlay over the hero
scrollDownThreshold: 600, // switch to the fixed bar after 600px
showTopBanner: false, // hide the top promo banner on this page
}}
>
<section class="hero"></section>
<section class="content"></section>
</Layout>
---

Back button instead of logo

Set button to replace the logo with a "back" link - ideal for detail pages.

Hide the header entirely

Set hidden: true when a page should not show a header at all (e.g. a landing page).

Back-button header
---
<Layout
title="Article"
header={{
button: { text: "Back to blog", href: "/blog" },
fixed: true,
}}
>
</Layout>
---
No header
---
<Layout title="Landing page" header={{ hidden: true }}>
</Layout>
---

All header options

These are the props accepted by the header object on the Layout. The Layout forwards the relevant subset to the Header component; a few additional props (github, ctaButton, overlayTheme) are only set at the Layout or component level.

PropTypeDefaultWhat it does
hiddenbooleanundefinedWhen true, the header is not rendered at all. Use for full-bleed landing pages.
fixedbooleanundefinedRenders a full-width bar pinned to the very top that does not move on scroll. Mutually exclusive with overlay and closeIcon.
overlaybooleanundefinedStarts the header as an absolute overlay (typically over a hero), then transitions to a fixed bar once scrollDownThreshold is passed. Mutually exclusive with fixed.
scrollDownThresholdnumberheader out of viewportOnly used with overlay. Pixels scrolled before the overlay morphs into the fixed bar. Should be larger than the header height for a clean transition.
closeIconbooleanundefinedReplaces the logo/button with a close icon that links back to the home page. Used on the 404 page. Mutually exclusive with fixed and overlay.
button{ text, href }logoShows a "back" button (with an arrow icon) instead of the site logo. Common on list and detail pages (e.g. "Back to blog").
showTopBannerbooleanfrom theme.config.tsForce-hides (false) or force-shows (true) the top promo banner for this page, overriding the global topBanner setting.

Layout-only props

A few props are not exposed on the page-level header object because they are project-wide: github (the repo link), ctaButton (the right-hand CTA), and overlayTheme (force light/dark for overlay headers). Edit them directly in ./src/layouts/default.astro or ./src/components/layout/header.astro.

Common combinations

The variant is picked from the combination of fixed, overlay, and closeIcon. These three are mutually exclusive - set at most one.

CombinationResultTypical use
(none set)CSS-fixed header that sticks to the top and hides when the footer covers the viewport.Most content pages.
fixed: trueFull-width bar pinned to the very top, never moves.List pages with a back button (blog categories, tags).
overlay: true + scrollDownThresholdOverlay over the hero, then morphs into a fixed bar after the threshold.Homepage and hero-driven pages.
closeIcon: trueJust a close icon linking home.Error pages (e.g. 404).
button + fixed: truePinned bar with a back button instead of the logo.Sub-listings where the user came from an overview.
hidden: trueNo header at all.Standalone landing or splash pages.
showTopBanner: falseAny variant, but the top promo banner is hidden.Legal/privacy pages where you want a calmer chrome.

Mutually exclusive variants

fixed, overlay, and closeIcon select different rendering branches in the component. Setting more than one produces undefined behaviour - the component checks closeIcon first, then fixed, then overlay, so only one ever applies. Pick the one that matches your intent.