How to Add a Blog to Your Astro Site
Add a blog to your Astro site with content collections. Write posts in Markdown and let Astro build the pages for you.
Tested on Astro 7.4

In this guide
An Astro blog is a folder of Markdown files. Each file becomes a post, and you don’t need a database. This tutorial assumes you already have a project with a layout. If you don’t, start with how to make a website with Astro.
Step 1: Write a post
Create src/content/posts/hello-world.md:
---
title: Hello, world
date: 2026-11-06
---
This is my **first** blog post, written in Markdown.
Step 2: Define the collection
Create src/content.config.ts, directly inside src:
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const posts = defineCollection({
loader: glob({ base: './src/content/posts', pattern: '**/*.md' }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
}),
});
export const collections = { posts };
The loader tells Astro where your posts are. The schema lists what each post needs.
Step 3: Create the blog index
Create src/pages/blog/index.astro:
---
import { getCollection } from 'astro:content';
import Layout from '../../layouts/Layout.astro';
const posts = (await getCollection('posts')).sort(
(a, b) => b.data.date.valueOf() - a.data.date.valueOf(),
);
---
<Layout title="Blog">
<h1>Blog</h1>
<ul>
{posts.map((post) => (
<li><a href={`/blog/${post.id}/`}>{post.data.title}</a></li>
))}
</ul>
</Layout>
The sort matters here, because Astro doesn’t return posts in any particular order.
Step 4: Create a page for each post
Create src/pages/blog/[id].astro, with the square brackets in the name:
---
import { getCollection, render } from 'astro:content';
import Layout from '../../layouts/Layout.astro';
export async function getStaticPaths() {
const posts = await getCollection('posts');
return posts.map((post) => ({
params: { id: post.id },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
<Layout title={post.data.title}>
<h1>{post.data.title}</h1>
<p>{post.data.date.toDateString()}</p>
<Content />
</Layout>
Step 5: Check it works
Restart your dev server and visit /blog/. You should see your post in the list. Click it to read it.
To publish another post, add another .md file to the same folder.
Frequently asked questions
Is there a faster way to start a blog?
Yes. Create a new project with the official blog template, which already includes posts, an RSS feed and a sitemap. Run npm create astro@latest with the template option set to blog.
Can I use images in my posts?
Yes. Put images in a folder near your post and link to them with normal Markdown image syntax.
Stuck on a step?
Check the common errors guide, look up a word in the glossary, or ask in the official Astro Discord, where the support channels are friendly to beginners.