Quarto to Obsidian publish workflow


I of­ten write tech­ni­cal notes as Quarto .qmd files in pro­ject fold­ers, but I archive and read long-form notes in Obsidian. This post doc­u­ments a work­flow that keeps those two worlds con­nected:

  1. Write and pre­view in Quarto.
  2. Publish into Obsidian as clean Markdown.
  3. Copy all ref­er­enced fig­ures into a sta­ble vault at­tach­ment lo­ca­tion.
  4. Rewrite im­age links so Obsidian ren­ders every­thing cor­rectly.

The goal is sim­ple: keep source notes where the code lives, while main­tain­ing a pol­ished Obsidian knowl­edge base.


What the work­flow does #

Given a source file:

/path/to/project/notes/my_note.qmd

Publishing pro­duces:

  • Rendered note: .../Obsidian Vault/Research/Notes/<TITLE FROM QMD>.md
  • Attachments: .../Obsidian Vault/Attachements & Files/quarto/<qmd-stem>/...

Image ref­er­ences are rewrit­ten from stan­dard Markdown paths to Obsidian wiki em­beds:

  • from: ![](my_note_files/figure-commonmark/fig1.png)
  • to: ![[Attachements & Files/quarto/my_note/figure-commonmark/fig1.png]]

This is im­por­tant be­cause the at­tach­ment folder in­cludes spaces (Attachements & Files), and wiki em­beds are much more ro­bust in Obsidian.


One-time setup #

Confirm vault paths #

  • Vault root: /path/to/Obsidian Vault
  • Attachments folder: Attachements & Files

Create Quarto at­tach­ments sub­folder #

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 ac­cord­ing to your path sit­u­a­tion. Save script to: ~/bin/publish_quarto_to_obsidian.sh. Make it ex­e­cutable:

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 any­where, for ex­am­ple:

/path/to/project/notebooks/this_is_a_note.qmd

Use front mat­ter with a hu­man-read­able ti­tle:

---
title: My note title
format:
  gfm: default
jupyter: python3
---

Important:

  • title: is used as the lit­eral Obsidian file­name (My Nice Title.md).
  • Do not in­clude / or \ in the ti­tle.

Then write con­tent nor­mally, in­clud­ing ex­e­cutable 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 as­sets un­der <qmd-stem>_files/figure-commonmark/.... The pub­lish script re­solves ref­er­enced im­ages and copies them into your vault at­tach­ments au­to­mat­i­cally.


Publish into Obsidian #

Choose a des­ti­na­tion path in­side the vault, for ex­am­ple:

  • Research/Notes
  • Research
  • Personal/Journal

Then run:

publish_quarto_to_obsidian.sh "/path/to/this_is_a_note.qmd" "Research/Notes"

What hap­pens dur­ing pub­lish #

  1. Render .qmd to GFM Markdown (--to gfm) in a tem­po­rary folder.
  2. Read title: from front mat­ter and use it as the out­put file­name.
  3. Parse ren­dered Markdown for im­age refs (![](...) and <img src="...">).
  4. Resolve im­ages rel­a­tive to .qmd folder first, ren­dered out­put folder sec­ond.
  5. Copy as­sets to Attachements & Files/quarto/<qmd-stem>/....
  6. Rewrite im­age links to Obsidian em­beds (![[...]]).
  7. Write fi­nal note to .../Obsidian Vault/<DEST>/<TITLE>.md.
  8. Add source marker: <!-- source-qmd: /abs/path/to/this_is_a_note.qmd -->
  9. Remove older gen­er­ated notes in the same des­ti­na­tion that share the same source marker.

Updating an ex­ist­ing note #

After edit­ing the .qmd, re­run the same pub­lish com­mand:

publish_quarto_to_obsidian.sh "/path/to/this_is_a_note.qmd" "Research/Notes"

Effects:

  • The des­ti­na­tion Markdown note is re­freshed.
  • Attachments for that note are recre­ated.
  • If title: changed, old gen­er­ated note is deleted via source marker match­ing.