pedroilidio1 downloadsSerialize a Bases view into static Markdown, wrapped in sentinel comments so it can be refreshed in place.
Freeze an Obsidian Bases view into real, static Markdown — wrapped in sentinel comments so you can refresh it in place.
Bases views are dynamic: they live inside a .base and don't exist as text, so
their results are invisible to the Graph, Search, Publish, exports, and other
tools. Bases Serializer writes the current result as ordinary Markdown, so:
Re-run it any time to update the block in place.
![]() |
![]() |
| Before — a live base embed | After — frozen Markdown, groups and all |
BRAT (recommended while unreleased)
pedroilidio/obsidian-bases-serializer.Manual
main.js, manifest.json, and styles.css from the latest release.<vault>/.obsidian/plugins/bases-serializer/.Requires Obsidian 1.10.0+ with Bases enabled.
![[tasks.base#Today]].Keeping the snapshot next to the query it came from means the base is the source of truth: change the base, re-serialize, the note updates.

| Control | What it does |
|---|---|
| ❄ Serialize now / Serialize here | Writes the block. The label reflects the mode (standalone vs. embedded). |
| ▾ | One-off actions: Keep live view, Freeze · replace embed with text (embedded only), Copy Markdown, Open target note, Remove serialized block. |
| Format | The format picker (icon + label). Opens a menu with Default (…) plus List, Checklist, Numbered, Table. |


List, Checklist, Numbered, or Table (the fallback for the in-view picker).Wikilink [[Note]] (default), Markdown [title](path), or Plain text.## Tasks).Hide (default), Inline (same line), or Sub-items (nested bullets).Inline (default ·; verbatim, include your own spaces).Due: 2026-10-13 instead of bare values (default off). — value.{group} and {count} (default ### {group}).(no rows)).50vh).![[base#view]] for plain Markdown (no embed, no sentinels).{link}, {title}, {path}, {index}, {group}, and any property by id
({note.due}) or display name ({Due}) — case-insensitive.
- {link} — {note.due} ({note.status})
Everything is wrapped in HTML-comment sentinels:
%% bases-serializer key="Today" format="checklist" %%
- [ ] [[Notes/Foo]] — 2026-10-13
- [ ] [[Notes/Bar]]
%% /bases-serializer %%
Only the block whose sentinel key= matches is replaced on re-serialize;
everything else in the note is left untouched, and multiple blocks per note are
supported. Set a custom Sentinel key to keep several independent snapshots.
Freeze takes it further: instead of a sentinel block it drops the plain
Markdown in place of the embed line itself — no %% markers, no ![[…]] left.
That's ideal for a final, "baked" note.
npm install
npm run dev # esbuild watch -> main.js
npm run build # typecheck + bundle
npm test # unit tests (sentinels, rendering)
Pure logic lives in src/sentinels.ts (block upsert/strip/freeze) and
src/render.ts (formats, templates, groups) with no Obsidian imports, so it
is unit-tested without the app. The Bases view wrapper lives in src/main.ts.
See ARCHITECTURE.md for a guided tour — the file map, the data flow, how to add a format or an option, and the traps worth knowing about.
QueryController is
opaque, so this must be a view type — it can't serialize the built-in
Table/Cards view directly.List renders bare bullets; use Checklist for - [ ] tasks.If Bases Serializer saves you time, you can buy me a coffee — it keeps the ❄️ in shape.
The code was written in pair-programming sessions with an AI assistant —
OpenCode driving DeepSeek V4.1 Flash — under my direction. The design, scope,
trade-offs and every product decision are mine; the implementation was largely the
assistant's. ARCHITECTURE.md is the map I use to maintain it, and changes authored
by the assistant carry an Assisted-by: trailer in git.