github ZenNotes/zennotes v2.50.4
ZenNotes v2.50.4

4 hours ago

ZenNotes 2.50.4: asset links that follow renames and moves, live modified dates, and two editor fixes

Released on September 15, 2026 as v2.50.4, at 850cf5f8. The release branch v2.50.4 was fast-forwarded into main through PR #787. All four reports came from @uNyanda; each is closed with a commit-linked comment. Channel and validation details are in the sections at the end.

✨ Features

  • Asset links follow renames and moves (#785). Renaming or moving an asset (sidebar menu, drag onto a folder, Assets view, or a rendered image's menu, on local vaults and through the Go server on remote ones) rewrites every note that referenced it, the way renaming a note already updated its wikilinks. References are resolved the way the renderer resolves them (relative to the note, then the vault root, then a unique file name) and re-targeted in the style each was written: a note-relative ../assets/x.png stays relative, a vault-root assets/x.png becomes media/x.png, a bare x.png stays bare while it still names one file and otherwise becomes the full path, and a wikilink never gains ... Aliases, |300 size hints, #page=2 fragments, percent-encoding, angle brackets, and link titles survive; anything inside code stays literal. Only notes that referenced the file are rewritten, and open buffers are flushed first so the rewrite cannot race a pending save.
  • Live last-modified template variables (#784). {{modified_date}}, {{modified_time}} and {{modified_datetime}} (with the same :FORMAT tokens as {{date:FORMAT}}) stay in the note instead of being substituted when it is created. The editor's live preview renders them as the file's last-saved time, revealing the raw token under the caret and leaving code literal; the reading view renders the same values. An Updated: {{modified_date}} line in frontmatter keeps itself current. The template editor offers the three after {{. The raw file keeps the token, so other tools show the braces.

🐛 Fixes

  • Forwarded tasks showed once per note on Kanban (#786). A task forwarded across notes leaves a [>] record in each one. The Status board and custom field boards already left those out, but the Priority and Folder boards only skipped done cards, so the same task appeared once per hop, and cancelled [-] tasks leaked onto those boards the same way. Every board now shows open work only. The [>] trail is a closed state by design, like [x]; the copy in the destination note is the one card. The Tasks list keeps its Forwarded group.
  • Wikilink picker stuck open after [[ inside inline code (#783). With Auto-close Markdown on, typing [[ inside backticks and deleting the auto-inserted ]] left an open [[ in the code span, and every keystroke after the closing backtick re-opened the note picker. The [[, [[Note# and [[Note^ pickers now stand down when the brackets sit in inline code or a code block.
  • Reading view: right-click on an image opens the asset menu. PDF, audio and video embeds and attachment chips had the menu (Open, Rename…, Move…, Duplicate, Copy as Embed, Copy Path, Open as Reference, Reveal in File Manager, Delete Asset…) since 1.1.0; image figures were never tagged for it. They are now.

🧰 For contributors

  • #783: ea12d3cb. Closure comment.
  • #786: e167302d. Closure comment.
  • #785: 99f42040. The renderer's asset resolver moved to packages/shared-domain/src/asset-path-resolution.ts (re-exported from app-core) and now reports the reading that resolved a reference; the rewriter is packages/shared-domain/src/asset-link-rename.ts with a Go port in apps/server/internal/vault/asset_link_rename.go. Desktop renameAsset/moveAsset and Go RenameAsset/MoveAsset snapshot assets and notes before the file operation; the store gained renameAsset/moveAsset actions used by all callers. Closure comment.
  • #784: 6b565e40. packages/app-core/src/lib/live-template-tokens.ts (pure) and cm-live-template-tokens.ts (editor plugin, part of the live-preview bundle); Preview.tsx substitutes before rendering. Closure comment.
  • Reading-view image menu: e73e4a4b.
  • Version bump: 850cf5f8.

In-app help (help.ts) documents the three live tokens and the rename/move rewriting; the website docs mirror both (docs.blade.php template-variable table and prose, docs-sections.json :template entry).

Demos

All four clips are 1920 × 1080 at 30 fps with burned-in captions and a .vtt sidecar, recorded from the built app over CDP on a clean demo vault.

  • 786-kanban-forwarded-once.mp4: 21 s. A task forwarded Monday → Tuesday → Wednesday, then the Status, Priority and Folder boards each showing it once.
  • 783-wikilink-picker-code.mp4: 18 s. Typing [[ inside backticks, deleting the auto-closed ]], writing on with the picker closed, then a real [[ in prose opening it.
  • 784-live-modified-date.mp4: 20 s. The Evergreen note's Updated: line and body tokens rendered, the raw token under the caret, an edit moving the time, and the reading view.
  • 785-asset-rename-move.mp4: 30 s. Rename from the Assets view, the note following, the new image menu in the reading view, a move to media/lisbon/, and the daily note's relative path still resolving.

Verification

  • Unit: shared-domain 15 rewriter tests (rename and move styles, collisions, encoding, code), app-core tests for the pickers, Kanban boards, live tokens (pure and editor plugin) and image-figure tagging, desktop vault.test.ts end-to-end rename and move, Go pure and end-to-end rename and move tests. apps/desktop && npm run build:prod passed (typecheck node + web, 768 tests, build, packaged CLI isolation). Go vet and internal/... tests pass.
  • Live, in the built desktop app over CDP: picker closed after a code-span [[ and open for a prose [[; one card per board for the forwarded chain; live tokens rendered in editor and reading view; rename from the Assets view and from the image menu rewrote both referencing notes on disk, refreshed the open buffer and re-rendered the images; a move from the sidebar menu produced a relative href, a bare wikilink and a re-rooted wikilink, with the daily note's relative path still resolving.
  • Not exercised live: the Go server path (covered by its tests only) and drag-onto-folder moves (same store action as the sidebar menu).

Distribution channels

  • Release workflow: 35036589163. Linux x64 and arm64 finished about 13 and 15 minutes after the tag with all five installer formats each plus both updater manifests; Windows (installer, portable ZIP, blockmap, manifest) at about 40 minutes; macOS (Apple silicon and Intel DMGs, ZIPs, blockmaps, manifest) at about 50 minutes, with Developer ID signing and notarization. 29 assets in total, including the four demo clips.
  • Docker: adibhanna/zennotes:2.50.4 published by workflow 35036589166 (amd64 and arm64).
  • AUR: 64853a3 in the separate zennotes-bin clone (zennotes-bin 2.50.4-1), mirrored on desktop main as ec8c0c60. Downloaded tarball SHA-256 428bdec0f436f4671c34e04a73d38a0f9345fb7119924e7938add50094703527 matched GitHub's asset digest. The Arch build check (aur-check.yml) passed on the branch and on main; the AUR RPC served 2.50.4-1 within minutes.
  • Nix: nix-update.yml run 35037488414 computed the hashes and opened bot PR #788, lifted exactly onto main as b28f1eb8 and closed. nix-build.yml 35037780379 then failed with the intermittent fetchFromGitHub source-hash disagreement (specified e6Yww…, got E3Kpar…); the fetched value was pinned in 6c3d95ec and nix-build.yml 35037936143 passed.
  • nixpkgs: PR #561418 restacked onto current master as zennotes-desktop: 2.45.0 -> 2.50.4 (fork commit 82bd8c0f, body in nixpkgs-pr-body.md).
  • Homebrew: ae257ff in the tap (zennotes 2.50.4), mirrored on desktop main as 9a2e5e1a. The cask pins both DMG digests from the GitHub API (arm64 0a56f41c65aeb1adc06751f277053b88d30e638aca70842493561b7c09921534).
  • Website: docs mirror and the 2.50.4 releases entry with all four clips pushed as 76a2e20 on website main; the full suite passed locally (791 tests, 6,236 assertions) and in website CI (tests and linter). The live release page lists 2.50.4 and serves the clips (HTTP 200).
  • npm run verify:channels -- 2.50.4 passed: Homebrew tap, AUR, Nix, and all seven website download redirects serve 2.50.4.

Release validation

Release PR #787's CI passed on macOS, Ubuntu, Ubuntu arm64 and Windows, plus CodeQL and the production dependency audit, before the fast-forward. The release workflow passed every platform job. aur-check.yml built the AUR package in a real Arch container on the branch and on main; nix-build.yml 35037936143 rebuilt the desktop and server Nix packages from the pinned hashes on main.

Local gates before the tag: apps/desktop && npm run build:prod (typecheck node + web, 768 tests, build, packaged CLI isolation) and Go vet + internal/... tests. The mac app packaged from a clean npm ci of the release branch (npm run pack) reported 2.50.4 and exposed a CDP page target 0.4 s after launch with both stores isolated and ZEN_PERF=1. That local package was unsigned; release CI signed and notarized both architectures.

The release was cut from a Claude worktree beside the main checkout. Two environment lessons are recorded in the project memory: npm version inside a worktree with symlinked node_modules reifies through the links into the main checkout (repaired by hand this time), and ffmpeg 9 rejects -r together with variable frame timing.

Don't miss a new zennotes release

NewReleases is sending notifications on new releases.