⌘Rcommandrefresh

Type to search.

Build a fast Astro blog in 20 minutes

A no-nonsense walkthrough of standing up a content-first blog with Astro — content collections, layouts, and a production build that flies.

Benjamin2 min read

Astro has quietly become the default answer for content-heavy sites, and once you’ve shipped one it’s easy to see why: you write mostly HTML and Markdown, you ship almost no JavaScript, and the thing is fast without you fighting for it. Here’s the shortest path from empty folder to a working blog.

1. Scaffold the project

Start from the minimal template so nothing is in your way:

npm create astro@latest my-blog -- --template minimal --typescript strict
cd my-blog

You get a tiny project: a config file, a src/pages directory, and not much else. That emptiness is the point — you add only what you need.

2. Define a content collection

This is the piece that makes Astro click. Instead of loose Markdown files, you describe the shape of your content with a Zod schema and get type safety plus validation for free:

// src/content.config.ts
import { glob } from 'astro/loaders';
import { defineCollection, z } from 'astro:content';

const posts = defineCollection({
  loader: glob({ pattern: '**/*.md', base: './src/content/posts' }),
  schema: z.object({
    title: z.string(),
    pubDate: z.coerce.date(),
    draft: z.boolean().default(false),
  }),
});

export const collections = { posts };

Now every post is validated at build time. Forget a title? The build fails loudly instead of shipping a broken page.

3. Render a post

A dynamic route pulls an entry and renders it. The render() call hands you a Content component that outputs the Markdown body:

---
import { getCollection, render } from 'astro:content';

export async function getStaticPaths() {
  const posts = await getCollection('posts');
  return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
}

const { post } = Astro.props;
const { Content } = await render(post);
---
<article>
  <h1>{post.data.title}</h1>
  <Content />
</article>

4. Build and ship

npm run build

You get a dist/ folder of static HTML you can drop on any host — no server, no runtime, no cold starts. The whole site is pre-rendered.

Where to go next

From here the additions are small and composable: an RSS feed via @astrojs/rss, a sitemap integration, Tailwind through the Vite plugin, and pagination using Astro’s built-in paginate() helper. Each one is a few lines, and none of them slow the site down. That restraint — adding capability without adding weight — is the whole reason Astro is worth learning.

Share

XLinkedInHacker News

Hit refresh on your inbox

Occasional dispatches on Apple silicon, software, and the tools that keep your workflow reloading. No spam, unsubscribe anytime.