Quarto to Obsidian publish workflow
I often write technical notes as Quarto .qmd files in project folders, but I archive and read long-form notes in Obsidian. This post documents a workflow that keeps those two worlds connected:
- Write and preview in Quarto.
- Publish into Obsidian as clean Markdown.
- Copy all referenced figures into a stable vault attachment location.
- Rewrite image links so Obsidian renders everything correctly.
The goal is simple: keep source notes where the code lives, while maintaining a polished Obsidian knowledge base.
What the workflow does #
Given a source file:
/path/to/project/notes/my_note.qmd
Publishing produces:
- Rendered note:
.../Obsidian Vault/Research/Notes/<TITLE FROM QMD>.md - Attachments:
.../Obsidian Vault/Attachements & Files/quarto/<qmd-stem>/...
Image references are rewritten from standard Markdown paths to Obsidian wiki embeds:
- from:
 - to:
![[Attachements & Files/quarto/my_note/figure-commonmark/fig1.png]]
This is important because the attachment folder includes spaces (Attachements & Files), and wiki embeds are much more robust in Obsidian.
One-time setup #
Confirm vault paths #
- Vault root:
/path/to/Obsidian Vault - Attachments folder:
Attachements & Files
Create Quarto attachments subfolder #
VAULT="/path/to/Obsidian Vault"
mkdir -p "$VAULT/Attachements & Files/quarto"
Script #
The script is (written by GPT Codex 5.3):
Modify the line 19 – 20 according to your path situation. Save script to: ~/bin/publish_quarto_to_obsidian.sh. Make it executable:
chmod +x ~/bin/publish_quarto_to_obsidian.sh
If ~/bin is not on your PATH:
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Writing the .qmd note #
Create the note anywhere, for example:
/path/to/project/notebooks/this_is_a_note.qmd
Use front matter with a human-readable title:
---
title: My note title
format:
gfm: default
jupyter: python3
---
Important:
title:is used as the literal Obsidian filename (My Nice Title.md).- Do not include
/or\in the title.
Then write content normally, including executable code chunks:
## Main point
Some text.
```{python}
import matplotlib.pyplot as plt
plt.plot([1,2,3],[1,4,9])
plt.show()
```
Quarto may emit assets under <qmd-stem>_files/figure-commonmark/.... The publish script resolves referenced images and copies them into your vault attachments automatically.
Publish into Obsidian #
Choose a destination path inside the vault, for example:
Research/NotesResearchPersonal/Journal
Then run:
publish_quarto_to_obsidian.sh "/path/to/this_is_a_note.qmd" "Research/Notes"
What happens during publish #
- Render
.qmdto GFM Markdown (--to gfm) in a temporary folder. - Read
title:from front matter and use it as the output filename. - Parse rendered Markdown for image refs (
and<img src="...">). - Resolve images relative to
.qmdfolder first, rendered output folder second. - Copy assets to
Attachements & Files/quarto/<qmd-stem>/.... - Rewrite image links to Obsidian embeds (
![[...]]). - Write final note to
.../Obsidian Vault/<DEST>/<TITLE>.md. - Add source marker:
<!-- source-qmd: /abs/path/to/this_is_a_note.qmd --> - Remove older generated notes in the same destination that share the same source marker.
Updating an existing note #
After editing the .qmd, rerun the same publish command:
publish_quarto_to_obsidian.sh "/path/to/this_is_a_note.qmd" "Research/Notes"
Effects:
- The destination Markdown note is refreshed.
- Attachments for that note are recreated.
- If
title:changed, old generated note is deleted via source marker matching.