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
.nvmrcfile (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
- Open a terminal in the folder where you keep your projects.
- Run the Astro setup wizard:
pnpm create astro@latest
- Give the project a folder name.
- Choose the smallest starter the wizard offers (minimal or empty). You will replace most of it.
- Say yes to installing dependencies and to creating a git repository.
- 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.tsholds the fields every page has:title,description, an optionalimageand an optionalseoblock.layouts/<type>.tsholds one schema per page type, always ending in.strict()so unknown fields fail the build.page.tscombines them into one union keyed ontype.
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:
| Command | What it does |
|---|---|
pnpm dev | Starts a local server at http://127.0.0.1:4321 that reloads as you edit |
pnpm check | Checks formatting with Prettier and types with astro check |
pnpm build | Builds the static site into the dist folder |
pnpm preview | Serves the dist folder locally, exactly as it will go live |
Note: If
pnpm buildfails 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
- Run
pnpm format:writeso the code follows the shared Prettier settings. - Run
pnpm checkandpnpm build. Both must pass. - Commit with a conventional prefix, for example
chore: initialize Astro project foundation. - 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.
Strategic call