The vault workspace — one LiveView serving three routes, so moving between notes patches the note pane instead of remounting the sidebar:
:index— the vault with no note open:show— a note open (read or edit):new— the "this note doesn't exist yet" page an unresolved[[wiki-link]]points at
Editing
Obsidian's model, and only that: clicking a note puts you in the editor, the editor is already a rendered view, and there is no second "reading" surface to switch to. That editor is Leaf — the same one PhoenixKit uses elsewhere — in hybrid mode, its Obsidian-style live preview, where formatting renders inline while the source markers stay editable. Someone with read-only access gets the same surface, not a different one.
[[wiki-links]] render as link tokens in the editor itself. Leaf decorates
them and asks which targets exist — only this module knows that — and the
answer goes back through the same resolver and same-folder tie-break that
built the stored link index, so a link never renders as pointing somewhere
the backlinks panel disagrees with. An unresolved target is styled distinctly
and points at the create page.
Leaf never navigates on a click; it reports one and leaves the destination to us. The right-hand panel still lists outgoing links, which is the path for a reader who wants the whole set rather than the one under the cursor.
Visual and HTML modes are denied. Both round-trip the document through HTML,
and a note's YAML front matter is ----delimited — which survives that trip
as a horizontal rule and a paragraph, silently destroying every property on
the note. Hybrid and markdown modes edit the source directly and are safe.
Edits autosave: Leaf debounces, the save writes the file and reindexes it, and the status pill reports where that got to.
[[ and # autocomplete
Leaf's inline-suggestion triggers do the real thing — a caret-anchored popup, arrow keys to move, Enter or Tab to accept, Escape to dismiss, and it works mid-paragraph because the client knows where the caret is.
[[ completes note titles and # completes tags. Both allow creating what
does not exist yet, so you can link ahead of yourself exactly as in Obsidian.
A suggestion whose title several notes share is inserted path-qualified,
so the link says which note it meant rather than leaving it to the tie-break.
Summary
Functions
The Leaf component id for a note.
Whether a {:leaf_changed, …} payload should be written to disk.
Functions
The Leaf component id for a note.
Keyed to the note, and both halves of that matter.
Leaf's editing surfaces are phx-update="ignore", so LiveView never patches
them after mount and a changed content assign does nothing to the DOM.
Under a constant id, patching from note A to note B reused the same
component and the same hook, and the editor went on showing A's text while
the server believed it was showing B's — every note opened with whatever was
loaded first.
Keying the id to the note makes LiveView tear the old component down and
mount a fresh one, and it makes a stale message identifiable: Leaf
debounces, so a :leaf_changed for the note you just left can arrive after
you have switched, and saving it would write A's text into B's file.
Whether a {:leaf_changed, …} payload should be written to disk.
Pure, and public, because it is the whole of the fix for two bugs that were invisible from the server's point of view — a stale editor writing into the wrong note, and an untouched note being rewritten just for being opened.