How this works#
Three directories, one direction of travel:

The vault#
vault/ is the Obsidian vault and the only place you type. It knows nothing
about Hugo beyond one front matter key, publish.
The sync script#
bin/vault-sync.py is where the actual translation happens, because Hugo does
not understand Obsidian’s markdown. Hugo’s maintainers closed the wikilink
feature request as not planned, so [[Note]] reaches Goldmark as literal
text and renders as literal text. The script rewrites it into a relref
shortcode, which Hugo resolves at build time and fails loudly on if the target
disappears.
It also copies each note’s attachments into the page’s own directory, so every
published note is a self-contained page bundle
and image paths stay correct whatever baseURL you set.
The site#
site/ is a normal Hugo site using the hugo-book theme. content/docs/ is
generated output — it is in .gitignore, and make sync deletes and rebuilds
it every time. Anything you want to keep by hand goes in content/ outside
docs/, in layouts/, or in assets/.
Running it#
make sync # vault -> site/content/docs
make serve # sync, then hugo server on :1313
make build # sync, then a production build into site/publicThe word [[wikilink]] inside that code fence is left alone — the converter
skips fenced blocks and inline code such as ![[not an embed]].
See also: Syntax cheatsheet and the front page.