A self-hosted, $0 alternative to Obsidian Publish.
Publish any Obsidian vault as a fast static site that looks and feels like Obsidian Publish — for free.
Live demo → · Get started · Update · Deploy · Author · How it works
Obsidian Publish is $10/month per vault, hosted on Obsidian's infrastructure. This template gives you the same UI — collapsible folder tree, wikilinks with hover previews, scroll-spy TOC, force-directed graph, ⌘K full-text search, dark/light theme — as a static site you fully control.
The vault lives as plain markdown in content/. A custom Astro publishing layer reads it at build time and emits a static site that runs anywhere — Cloudflare Pages, Netlify, GitHub Pages, S3, your own box. No server, no database, no recurring fees.
Want it private? Optional email-based access control via Cloudflare Access gates the whole site (or specific paths) behind one-time-code login — also free for 50 users.
Total infrastructure cost on Cloudflare Pages + Cloudflare Access: $0.
Want to see it first? Browse the live demo — it's this repo, deployed to Cloudflare Pages, with the sample vault.
Click Use this template → Create a new repository, then:
git clone https://github.com/<you>/<your-repo>.git
cd <your-repo>
npm install # required on every fresh clone — node_modules/ is gitignored
npm run dev # preview at http://localhost:4321/
npm run build # static build into dist/, plus Pagefind search indexReplace content/ with your own Obsidian vault (or set OBSIDIAN_VAULT_DIR to point at one outside the repo) and the renderer picks it up automatically.
Full walkthrough — Node versions, template vs. fork, configuration, troubleshooting — in Getting started.
Pull the latest engine fixes without touching a single note:
git remote add upstream https://github.com/treverehrfurth/astro-publish.git # once, ever
git fetch upstream --tags
git switch -c update-engine
git rm -r --quiet --ignore-unmatch src/components src/layouts src/lib src/pages src/styles docs
git checkout upstream/main -- src/components src/layouts src/lib src/pages src/styles \
src/content.config.ts docs astro.config.ts tsconfig.json package.json package-lock.json .env.schema
npm install && npm run buildcontent/ and src/config/site.ts are never named, so your vault and your customizations are untouched. See Updating for the full procedure, the fork/merge alternative, and what to check afterwards.
- CommonMark + GFM — tables, footnotes, strikethrough, task lists.
- Obsidian wikilinks —
[[Note]],[[Note|alias]],[[Note#heading]],![[image.png]],![[document.pdf]]. - Embedded images and PDFs — copied to
public/_evidence/at build, served alongside the site. - Tags — frontmatter
tags:plus inline#hashtags, indexed at/tags/<tag>. - Callouts —
> [!note],> [!tip],> [!warning], etc. - Backlinks — automatic, rendered at the bottom of every note.
- Dataview subset —
TABLE [WITHOUT ID] … WHERE … SORT …, withcontains(),link(), identifier paths (type,this.slug,file.path), and the boolean ops. draft: true/publish: false— exclude a note from the published site.- Frontmatter
aliases— alternate names a wikilink can resolve to.
The single customization surface is src/config/site.ts. Edit it to:
- Order the navigation —
navOrderpins folders and notes to the front of their level in the order you list them, instead of the default A→Z. Or setorder: <number>in a note's frontmatter. See Authoring → Navigation order. - Add meta-bar fields — show frontmatter values like
author,status, orread timein the page header. - Color the graph — map
typefrontmatter values (or top-level folder names) to specific node colors. - Configure folder-collapse filenames — defaults to
index.mdandwelcome.md.
Defaults work out-of-the-box; you only edit the config if you want richer behavior.
| Topic | What's in it |
|---|---|
| Getting started | Prerequisites, "Use this template" vs. fork, installing dependencies, the npm scripts, pointing it at your vault, troubleshooting |
| Updating | Pulling engine fixes into a site you already built, without touching your notes |
| Architecture | The build pipeline (loader passes, remark plugins, dataview), why this exists vs. Obsidian Publish |
| Authoring | Frontmatter schema, file naming, wikilinks, embeds, Dataview subset, draft/publish |
| Deployment | Cloudflare Pages settings, Cloudflare Access (email OTP), custom domain, env vars |
/
├── content/ Your vault — drop in any Obsidian vault here
├── src/
│ ├── config/ site.ts — the customization surface
│ ├── layouts/ Page shells (Layout.astro, NoteLayout.astro)
│ ├── components/ LeftNav, RightRail, GraphView, SearchPalette, etc.
│ ├── lib/ Vault loader, wikilink resolver, dataview engine
│ ├── pages/ Astro routes
│ ├── styles/ CSS tokens + per-component stylesheets
│ └── content.config.ts
├── _templates/ Obsidian-side templates for new notes (not published)
├── public/ Static assets + build-time generated JSON
├── docs/ This documentation
├── astro.config.ts Site config (canonical URL, integrations)
└── package.json
The content/ folder is the entire authoring surface. Open it as an Obsidian vault, edit normally, run npm run build, deploy.
MIT.
This template is an independent project; Obsidian and Obsidian Publish are trademarks of Dynalist Inc., used here only for descriptive comparison.




