Publisher
unlistedby Mark Ayers
Publish notes to GitHub for Hugo processing. Automatically converts wikilinks, images, and filenames to Hugo-compatible formats.
Obsidian Publisher
Publish Obsidian notes to GitHub for Hugo processing. Tailored for philoserf.com.
You probably shouldn't install this
This is personal tooling, not a general-purpose plugin. It is opinionated in ways that only make sense for one person's workflow:
- Single user. The only known installation is the maintainer's. Breaking changes ship without migration paths (see
CHANGELOG.md— 1.4.0 renamed the publish sentinel, 1.5.0 retiredremovePublishFlagand the{{< ref >}}wikilinks, 1.6.0 retired the direct-commit publish mode entirely). - One target shape. The Hugo destination is expected to use
content/posts/,static/images/, and the shippedhugo-shortcodes/(callout + mermaid) installed in the site's theme. Other layouts will see broken links or missing renderers. - PR workflow only, mandatory. Every publish creates a timestamped feature branch and opens a PR against
baseBranch. There is no direct-commit escape hatch. - Required frontmatter. Notes must carry
status: publish, plus a non-emptytitleanddate. Missing or empty required fields fail the publish per-note. - No issue triage for feature requests. Bugs are welcome; feature requests from other users will almost always be closed as out-of-scope.
If you want something similar, the code is MIT-licensed — fork it and adapt. Don't expect upstream to accommodate your workflow.
Content Transformations
The plugin converts Obsidian-specific syntax to Hugo-compatible markdown during publish:
| Obsidian | Hugo |
|---|---|
[[Page Name]] | [Page Name](/posts/page-name/) (if in publish set) |
[[Page Name#Heading]] | [Page Name#Heading](/posts/page-name/#heading) |
[[Page|Display]] | [Display](/posts/page-name/) |
![[image.png]] |  |
![[image.png|alt]] |  |
![[image.png|300]] |  (sizing stripped) |
![[Note Name]] (embed) | [Note Name](/posts/note-name/) (if in publish set) |
%%comment%% | Removed |
==highlight== | <mark>highlight</mark> |
> [!note] Title | {{< callout note "Title" >}} … {{< /callout >}} |
```mermaid | {{< mermaid >}} … {{< /mermaid >}} |
Wikilinks and note embeds only resolve to URLs for notes in the current publish set (the notes being published in this operation). Out-of-set references degrade to plain text — so you can't publish a link to a note that isn't also being published.
Callout types pass through from Obsidian verbatim (no collapse to a fixed set). The destination Hugo site must define callout and mermaid shortcodes in layouts/shortcodes/. Reference implementations ship in hugo-shortcodes/ — copy them into your theme. The shortcode names are configurable in the plugin settings (default callout and mermaid).
Heading anchors ([[Page#Heading]]) assume the destination Hugo site uses the default autoIDType: "github", which preserves Unicode letters. Sites configured with the opt-in autoIDType: "github-ascii" will see mismatched #fragment links — pages load, but in-page jumps to non-ASCII headings won't resolve.
Security
This plugin requires a GitHub Personal Access Token (PAT) to publish content.
- Use a fine-grained token scoped to your target repository with
contents:writeandpull_requests:writepermissions. Avoid classic tokens with broadreposcope. - Token storage: The token is stored in Obsidian's plugin data file (
data.json) as plaintext. This is an Obsidian platform constraint — there is no encrypted storage API. Anyone with file system access to your vault can read the token. - Recommendations: Use a token scoped to a single repository. On shared devices, be aware that the token is accessible on disk.
Alternatives
- Enveloppe — publish Obsidian notes to GitHub with broader CMS support (Jekyll, Hugo, etc.).
- Digital Garden — publish notes to a static site with its own theme and hosting.
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.