Help Center

Astro / Getting started

Make an Astro site

Create a new Astro project with pnpm, give it the Viralistic structure, and run the dev server, checks and build on your own machine.

Intermediate 30 min Updated

This guide is for developers, or anyone working alongside Claude Code, who wants to start a new website the way Viralistic builds them. You go from an empty folder to an Astro project where every page is a markdown file, schemas are strict and one route renders everything. You also learn the four commands you will use every day.

What you need

  • Node.js, an even-numbered LTS release. Viralistic projects pin the exact version in a .nvmrc file (currently Node 24).
  • pnpm, the package manager we use for every project. Install it with the instructions on pnpm.io.
  • Git and a GitHub account, so the site can be deployed later.
  • A code editor, for example VS Code with the official Astro extension.

Create the project

  1. Open a terminal in the folder where you keep your projects.
  2. Run the Astro setup wizard:
pnpm create astro@latest
  1. Give the project a folder name.
  2. Choose the smallest starter the wizard offers (minimal or empty). You will replace most of it.
  3. Say yes to installing dependencies and to creating a git repository.
  4. Move into the new folder with cd your-folder-name.

Tip: The wizard’s questions change between Astro versions. If an option looks different from this guide, pick the option that gives you the least starter code.

Add the Viralistic structure

A fresh Astro project has a src/pages/index.astro file with markup inside it. Viralistic sites never put content in routes. Instead, content lives in src/content, and a type field in each page decides which layout renders it. The fastest way to get there is to copy the foundation files from an existing Viralistic project. Here is what they add and why.

One content route

Delete src/pages/index.astro and create src/pages/[...page].astro. This is the only route on the site. It turns every file in the pages collection into a URL:

---
import { getCollection } from "astro:content"

import LayoutRenderer from "@/components/layout-renderer.astro"

export async function getStaticPaths() {
  const pages = await getCollection("pages")

  return pages.map((page) => ({
    params: { page: page.id === "index" ? undefined : page.id },
    props: page,
  }))
}
---

<LayoutRenderer {...Astro.props} />

Collections and schemas

src/content.config.ts defines two collections: pages (markdown files) and globals (one YAML file per language with the site name, navigation, call to action and footer). Each collection is validated by a schema in src/schemas/:

  • layouts/base.ts holds the fields every page has: title, description, an optional image and an optional seo block.
  • layouts/<type>.ts holds one schema per page type, always ending in .strict() so unknown fields fail the build.
  • page.ts combines them into one union keyed on type.

Layouts, blocks and UI

src/components/layout-renderer.astro reads the page’s type and loads src/layouts/<type>.astro. Layouts only pick blocks (src/components/blocks/hero-1.astro, features-1.astro and so on) and pass data to them. Small building blocks such as buttons come from the Fulldev UI registry:

pnpm dlx shadcn@latest add @fulldev/button

Your first content

Create a globals file named after the default locale in astro.config.ts (Viralistic’s own site uses src/content/globals/nl.yaml), and a home page at src/content/pages/index.md:

---
type: home
title: We build calm, fast websites
description: A short description for search engines and social previews.
eyebrow: Welcome
buttons:
  - label: Get in touch
    href: /contact
---

Body text in markdown goes here.

Every field must match the home schema. Add a field to the schema first, then to the page.

Site URL, name, favicon and languages go into fulldevIntegration() in astro.config.ts. That one integration also wires Tailwind, the sitemap, robots.txt and favicons, so you do not configure them anywhere else.

Run the site

Add these scripts to package.json if they are not there yet:

{
  "scripts": {
    "dev": "astro dev --host 127.0.0.1",
    "build": "astro build",
    "preview": "astro preview",
    "typecheck": "astro check",
    "check": "pnpm format:check && pnpm typecheck",
    "format:write": "prettier --write .",
    "format:check": "prettier --check ."
  }
}

Then use them:

CommandWhat it does
pnpm devStarts a local server at http://127.0.0.1:4321 that reloads as you edit
pnpm checkChecks formatting with Prettier and types with astro check
pnpm buildBuilds the static site into the dist folder
pnpm previewServes the dist folder locally, exactly as it will go live

Note: If pnpm build fails with a message about an unexpected key, that is the strict schema doing its job. A page has a field its layout does not know. Fix the field or add it to the schema.

Commit your work

  1. Run pnpm format:write so the code follows the shared Prettier settings.
  2. Run pnpm check and pnpm build. Both must pass.
  3. Commit with a conventional prefix, for example chore: initialize Astro project foundation.
  4. Create an empty repository on GitHub and push to it.

Next steps

Still stuck?

Send us what you tried and a screenshot, and we will help you further. For new projects, book a strategic call.