Frontmatter

Starter project

The FM Solo Starter is a reference Astro project built to the Solo contract. If you start from it, solo:validate passes on the first run.

What it includes

The starter is a minimal but realistic Astro project with:

  • A Base.astro layout with global stylesheet loading
  • A set of Solo-friendly components such as Hero, Section, CTA, Footer, GalleryItem, ImageGallery, ContactDetails, and ContactForm
  • SEO components (SEOPage, SEOWebsite, SEOOrganisation, SEOLocalBusiness, SEOArticle) on the blessed support list
  • Multiple example pages — including index.astro, contact.astro, showcase.astro, styling.astro, and 404.astro
  • A structured styling layer with src/styles/styles.scss and partials under src/styles/partials/
  • A small JS entrypoint under src/scripts/ for progressive enhancement
  • Static images served from public/images/

Getting the starter

git clone https://github.com/withfrontmatter/fm-solo-starter
cd frontmatter-solo-starter
npm install

The starter is also included in the Solo CLI package download, so you can use the same reference project whether you start from GitHub or from the purchased archive.

Running solo-check on the starter

The starter should pass validation out of the box:

npx @withfrontmatter/solo-check --root .
# Expected: exit 0, no errors

Styling and frontend workflow

The starter ships with SCSS by default, but it is not locked to SCSS.

  • Source styling lives in src/styles/styles.scss
  • Design structure is split into partials under src/styles/partials/
  • In development, Astro serves the source stylesheet directly for native hot reload
  • In build, the starter emits stable assets under public/assets/ for backend handoff
  • JavaScript source lives under src/scripts/ with main.js as the entrypoint

If your team prefers plain CSS, you can switch the starter to plain CSS and keep the same Solo component contract. The styling system is a default authoring choice, not a hard requirement.

Component structure

Every component in the starter follows the same pattern — typed literal props, global CSS only, no dynamic expressions:

---
export interface Props {
  headline: string;    // required — literal string only
  sub?: string;        // optional
  ctaLabel?: string;   // optional
  ctaHref?: string;    // optional
}
const { headline, sub, ctaLabel, ctaHref } = Astro.props;
---
<section class="hero">
  <h1>{headline}</h1>
  {sub && <p>{sub}</p>}
</section>
Props must be literal. <Hero headline={page.title} /> fails with E201. The starter only uses string literals like <Hero headline="Hello Solo" />. See the Solo contract for the full rules.

Using the starter as a reference

If you're adapting an existing Astro project to the Solo contract, the starter is useful as a reference for:

  • How to structure Props interfaces
  • How to use SEO components correctly
  • How to organize global styling and stable frontend assets
  • How pages compose components without dynamic logic
  • How to keep a frontend workflow comfortable while staying backend-friendly

What the starter does not include

The starter is intentionally minimal. It does not include:

  • Framework components (React, Vue, Svelte) — these are skipped with placeholders
  • Markdown pages — not supported in Solo v1
  • Dynamic data fetching — by design
  • CMS integration — that's the backend developer's responsibility

On this page