Obsidian to Astro
ยฉ 2021-2026 Guillaume Excoffier. All rights reserved.
A powerful sync tool that transforms your Obsidian notes into a beautiful Astro blog with automated image processing and link conversion.
โจ Features
- ๐ Automated Sync - One-command sync from Obsidian vault to Astro project
- ๐ผ๏ธ Smart Image Handling - Automatic hero image and content image processing
- ๐ Link Transformation - Convert Obsidian wiki links to proper URLs
- ๐ท๏ธ Tag Extraction - Auto-extract hashtags from content
- ๐จ Image Optimization - Built-in Astro image optimization
- ๐๏ธ Safe Purge - Clean old content while preserving important assets
- ๐ฆ Content Collections - Type-safe frontmatter with Astro content collections
- ๐ญ View Transitions - Smooth page transitions for better UX
๐ Quick Start
Prerequisites
- Node.js 18+ installed
- An Obsidian vault with markdown notes
- Git (optional, for deployment)
Installation
- Clone the repository
git clone https://github.com/GoyoStach/Obsidian-to-Astro.git cd Obsidian-to-Astro - Install dependencies
npm install - Configure environment variables
Copy the example environment file:
Editcp .env.local.example .env.local.env.localwith your paths:# Absolute path to your Obsidian vault OBSIDIAN_PATH=/home/goyo/Documents/Obsidian # Relative path to blog posts (from project root) PROJECT_PATH=src/content/blogPost # Relative path to images (from project root) IMAGE_PATH=src/Images - Run the development server
Open http://localhost:4321 in your browser.npm run dev
๐งพ About
This project transforms Obsidian notes into a production-ready blog. Inspired by Takuya Matsuyama โs workflow:
Current Version: Astro 5.x with latest features:
- Content Collections for type-safe frontmatter
- Native image optimization
- View transitions for smooth navigation
๐ Tech Stack
- ๐ Astro 5.x - All-in-one web framework for fast, content-focused websites
- โ๏ธ React 18 - UI component library for interactive elements
- ๐จ Tailwind CSS - Utility-first CSS framework
- ๐ Gray Matter - Frontmatter parser
- ๐ผ๏ธ Sharp - High-performance image processing
๐ Project Structure
Obsidian-to-Astro/
โโโ scripts/
โ โโโ obsidian-sync/ # Sync CLI tool
โ โโโ src/
โ โโโ cli/ # Command-line interface
โ โโโ lib/ # Core processing logic
โ โ โโโ file-system.ts
โ โ โโโ frontmatter.ts
โ โ โโโ image-processor.ts
โ โ โโโ processor.ts
โ โ โโโ transformer.ts
โ โโโ utils/ # Helper functions
โโโ src/
โ โโโ Images/ # Processed images from Obsidian
โ โ โโโ preserved/ # Protected from purge
โ โ โ โโโ astro_banner.png
โ โ โโโ hero.png
โ โ โโโ image1.png
โ โ โโโ .gitkeep
โ โโโ components/ # React/Astro components
โ โโโ layouts/ # Page layouts
โ โโโ pages/ # Route pages
โ โ โโโ index.astro
โ โ โโโ [...slug].astro
โ โโโ content/
โ โโโ blogPost/ # Synced markdown files
โ โโโ advanced-git.md
โ โโโ .gitkeep
โโโ .env.local # Environment configuration
โโโ astro.config.mjs # Astro configuration
โโโ package.json
Key Directories
src/content/blogPost/- Contains all synced blog posts from Obsidiansrc/Images/- Stores all images with automatic optimizationsrc/Images/preserved/- Protected folder for permanent assets (not deleted on purge)scripts/obsidian-sync/- Automated sync tool for Obsidian โ Astro
๐ง Commands
All commands are run from the root of the project:
| Command | Action |
|---|---|
npm install | Install dependencies |
npm run dev | Start dev server at localhost:4321 |
npm run build | Build production site to ./dist/ |
npm run preview | Preview built site locally |
npm run sync | Sync Obsidian notes to Astro |
npm run sync:clean | Clean all synced content (with confirmation) |
npm run lint | Run ESLint |
npm run lint:fix | Fix ESLint errors automatically |
npm run format | Format code with Prettier |
๐ Deployment
Production Build
Build the site for production:
npm run build
This generates a static site in ./dist/ that can be deployed anywhere.
Automated Deployment
This blog uses automated deployment with Coolify on a VPS:
- Sync your Obsidian notes:
npm run sync - Commit the changes:
git add . git commit -m "Add new blog post" git push origin main - Deploy - The CI/CD pipeline automatically builds and deploys
Live Site: https://blog.goyostash.com/
Manual Deployment
You can deploy to any static hosting service:
- Vercel:
vercel deploy - Netlify:
netlify deploy --prod - GitHub Pages: Push to
gh-pagesbranch - Any VPS: Copy
./dist/to your web server
๐ ๏ธ How It Works
Sync Process
When you run npm run sync, the tool:
- Discovers markdown files in your Obsidian vault
- Filters for files with
isExposed: truein frontmatter - Purges old content from
src/content/blogPost/andsrc/Images/(exceptpreserved/) - Processes each file:
- Transforms wiki links:
[[Note]]โ[Note](/note)- Extracts hashtags:
#codeโ added to tags array - Resolves hero images from vault
- Copies hero images to
src/Images/ - Processes content images
- Updates image references
- Generates missing frontmatter fields
- Extracts hashtags:
- Transforms wiki links:
- Writes processed files to
src/content/blogPost/ - Reports statistics (files processed, images copied, links converted)
Path Resolution
The tool intelligently resolves image paths:
Obsidian: 9999 Images/Advanced_Git/hero.jpg
โ
Astro: src/Images/Advanced_Git_hero.jpg
โ
Frontmatter: ../../Images/Advanced_Git_hero.jpg
It handles:
- Numbered folders (e.g.,
9999 Images/) - Nested folder structures
- Common attachment folders (
attachments/,Images/, etc.) - Relative and absolute paths
- URL encoding (spaces, special characters)
๐ Best Practices
Obsidian Organization
- โ
Use
isExposed: trueonly for finished posts - โ Keep images in dedicated folders per topic
- โ Use descriptive filenames (becomes the URL slug)
- โ Add meaningful tags and descriptions
- โ Use wiki links for internal references
Image Management
- โ
Store permanent assets in
src/Images/preserved/ - โ Use hero images for better visual appeal
- โ Optimize large images before adding to vault
- โ ๏ธ Avoid special characters in filenames (
&,\, etc.) - โ ๏ธ Use underscores
_instead of spaces in folder names
Content Writing
- โ
Use H1 (
#) for the main title - โ Add hashtags for automatic tag extraction
- โ Link related posts with wiki links
- โ
Test locally with
npm run devbefore deploying
๐ Troubleshooting
Images not showing up
- Check that the image path in Obsidian is correct
- Verify the image exists in your vault
- Look for warnings in the sync output
- Check
src/Images/for copied files
Links not working
- Ensure wiki links use the note filename:
[[Filename]] - Avoid using full paths in wiki links
- The tool extracts only the filename for the URL
Sync not finding notes
- Verify
OBSIDIAN_PATHin.env.localis correct - Check that notes have
isExposed: truein frontmatter - Run sync with verbose output to see discovered files
Build errors
- Run
npm run lintto check for code issues - Verify all image paths in frontmatter are valid
- Check that content collections schema is satisfied
๐ License
ยฉ 2021-2026 Guillaume Excoffier. All rights reserved.
๐ Credits
- Inspired by Takuya Matsuyama โs workflow
- Built with Astro
- Styled with Tailwind CSS
๐ Obsidian Setup
Vault Structure
Your Obsidian vault can have any structure. The sync tool will automatically discover and process marked files:
MyObsidianVault/
โโโ .obsidian/
โโโ 200 Informatique/
โ โโโ 210 Web Dev/
โ โโโ Advanced Git.md # Your blog post
โ โโโ Multiple git account.md
โโโ 9999 Images/ # Optional: centralized images
โ โโโ Advanced_Git/
โ โ โโโ Advanced_Git_hero.jpg
โ โโโ Multiple_git_account/
โ โโโ hero.png
โโโ 800 Miscellaneous/
โโโ Another post.md
Frontmatter Configuration
To expose a note as a blog post, add frontmatter with isExposed: true:
---
title: My Awesome Post
description: A brief description of the post
isExposed: true
date: '2026-02-14'
tags:
- code
- tutorial
categories:
- "[[gh]]"
heroImage: 9999 Images/My_Post/hero.jpg
---
# My Awesome Post
Your content here...
Frontmatter Fields
| Field | Required | Description | Example |
|---|---|---|---|
isExposed | โ Yes | Must be true to sync this note | isExposed: true |
title | โ No | Post title (auto-generated from H1 or filename if not provided) | title: Advanced Git |
description | โ No | Post description (auto-generated if not provided) | description: Learn advanced git |
date | โ No | Publication date (uses file modification date if not provided) | date: '2026-02-14' |
tags | โ No | Array of tags (hashtags from content are auto-extracted) | tags: [code, git] |
heroImage | โ No | Path to hero image in Obsidian vault (uses default if omitted) | heroImage: 9999 Images/Post/hero.jpg |
Hero Image Paths
The sync tool supports multiple hero image path formats:
# Obsidian centralized images folder
heroImage: 9999 Images/Advanced_Git/Advanced_Git_hero.jpg
# Relative to note location
heroImage: attachments/hero.png
# Subfolder structure
heroImage: Images/My_Topic/banner.jpg
The tool will:
- Resolve the image path from your Obsidian vault
- Copy it to
src/Images/in the Astro project - Update the frontmatter with the correct relative path:
../../Images/hero.jpg
Image References in Content
Use standard Obsidian syntax for images:
# Obsidian wiki links (recommended)
![[image.png]]
![[folder/image.png]]
# Standard markdown

The sync tool automatically:
- Resolves image paths from your vault
- Copies images to
src/Images/ - Updates image references to work with Astro
Internal Links
Link to other notes using Obsidian wiki links:
# Simple link
[[Other Note]]
# Link with custom text
[[200 Informatique/210 Web Dev/Advanced Git|Git Tutorial]]
# Folder paths are automatically handled
[[Folder/Subfolder/My Note]]
The sync tool converts these to proper URLs:
[[Advanced Git]]โ[Advanced Git](/advanced-git)[[Folder/My Note|Custom Text]]โ[Custom Text](/my-note)
Creating a New Post
- Create a markdown file anywhere in your Obsidian vault
- Add frontmatter with
isExposed: true:--- isExposed: true title: My New Post description: This is my new blog post tags: [tutorial, code] heroImage: 9999 Images/My_New_Post/hero.jpg --- - Write your content using Obsidian features:
- Wiki links for internal references
![[image]]for images#hashtagsfor additional tags- Standard markdown formatting
- Wiki links for internal references
- Run the sync command:
npm run sync
The tool will:
- โ
Copy your markdown file to
src/content/blogPost/ - โ Process and copy all images
- โ Convert wiki links to web-compatible URLs
- โ Extract hashtags and merge with frontmatter tags
- โ Generate missing frontmatter fields
Sync Workflow
# 1. Sync from Obsidian to Astro
npm run sync
# 2. Preview changes locally
npm run dev
# 3. Build for production
npm run build
# 4. (Optional) Clean all synced content
npm run sync:clean
Protected Images
Images in src/Images/preserved/ are never deleted during sync cleanup. Use this folder for:
- Default hero images
- Site logos
- Reusable assets
Example:
heroImage: ../../Images/preserved/astro_banner.png