Skip to content

Repository files navigation

Astro Publish

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

Live demo MIT license Built with Astro Hosting cost


Why this exists

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.


Highlights

⌘K search palette

⌘K full-text search

Pagefind-powered, indexed at build time, runs entirely in the browser. Press K anywhere to fuzzy-search every note — no server, no API key.

Wikilink hover previews

Hover any [[link]] to see the target's title, tags, and a snippet of body text — the same affordance Obsidian Publish ships with, rendered statically.

Wikilink hover preview
Local force-directed graph

Local graph

Force-directed view of every note and its connections, colored by type frontmatter (or top-level folder). Drag to rearrange, scroll to zoom.

Mobile-first

Sticky topbar with directory and contents slide-outs at narrow widths, with a unified backdrop tap-to-close. Reads as well on a phone as on desktop.

Mobile view with slide-out nav
Rendered dataview table

Dataview tables

Drive automatic tables off frontmatter with a useful subset of Obsidian's Dataview syntax — TABLE … FROM … WHERE … SORT …, with contains(), link(), and identifier paths. Rendered at build, no client-side runtime.


Quick start

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 index

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

Already have a site from an earlier version?

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 build

content/ 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.


What's supported

  • 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 subsetTABLE [WITHOUT ID] … WHERE … SORT …, with contains(), 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.

Customizing

The single customization surface is src/config/site.ts. Edit it to:

  • Order the navigationnavOrder pins folders and notes to the front of their level in the order you list them, instead of the default A→Z. Or set order: <number> in a note's frontmatter. See Authoring → Navigation order.
  • Add meta-bar fields — show frontmatter values like author, status, or read time in the page header.
  • Color the graph — map type frontmatter values (or top-level folder names) to specific node colors.
  • Configure folder-collapse filenames — defaults to index.md and welcome.md.

Defaults work out-of-the-box; you only edit the config if you want richer behavior.


Documentation

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

Repository layout

/
├── 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.


License

MIT.

This template is an independent project; Obsidian and Obsidian Publish are trademarks of Dynalist Inc., used here only for descriptive comparison.

About

An Obsidian looking Astro theme similar to Obsidian Publish

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages