Using Obsidian with Astro Content Collections
How to write blog posts in Obsidian and publish them with Astro's content collections, including wikilinks, image embeds, and frontmatter validation.
Why Obsidian for Astro?
Obsidian is a markdown editor that treats notes as an interconnected graph. Astro’s content collections validate and build those markdown files into static pages. The combination gives you a local-first writing experience with type-safe content.
Content Structure
src/content/blog/
images/
my-post-cover.jpeg
my-post.md
Images live alongside their posts in src/content/blog/images/. The image() schema helper resolves paths relative to the content file:
---
title: "My Post"
image: ./images/my-post-cover.jpeg
---
Frontmatter Schema
Astro validates frontmatter against a Zod schema in src/content.config.ts:
const blog = defineCollection({
schema: ({ image }) =>
z.object({
title: z.string(),
description: z.string(),
date: z.coerce.date(),
draft: z.boolean().default(false),
tags: z.array(z.string()).default([]),
category: z.string().optional(),
image: image().optional(),
series: z
.object({
name: z.string(),
order: z.number(),
})
.optional(),
}),
});
Obsidian Syntax Transformation
Obsidian uses ![[image.png]] for image embeds. A normalization script converts these to standard Markdown:
pnpm normalize:obsidian
Transforms:
![[photo.png]]→![[photo.png|Alt text]]→
Code blocks are preserved — ![[example.png]] inside backticks stays as-is.
Tags and Categories
Tags are arrays in frontmatter, rendered as clickable links:
tags:
- astro
- markdown
- tutorial
Categories link to /categories/{name}, tags link to /tags/{name}.
Series
Group related posts with a series object:
series:
name: Content Management Series
order: 1
Writing Workflow
- Write in Obsidian with wikilinks and image embeds
- Run
pnpm normalize:obsidianto convert syntax - Set
draft: truewhile iterating - Set
draft: falsewhen ready to publish