⌘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.