ZenNotes 2.81.0 brings recurring tasks and reminders, gives every folder a Kanban board of its own, lets a Kanban column take a color, and turns every Settings field that names a folder into a picker of your vault's folders. Enter in a list keeps its bullets together, and New Drawing opens its drawing in a Vault root vault whose drawings folder sits under assets/.
Features
- Recurring tasks and reminders (#1036, asked for by williamcheuk03). Add
@repeat:weeklyto a task line (alsodaily,weekdays,monthly,yearly,2d,3w,mon/thu, orafter-3dto count from the day you finish).- Checking it off writes the next occurrence right above it with the next
due:, and keeps the finished line below as the record. - Its subtasks come back unticked, and the record cancels (
[-]) the ones left open, so they show only once. - A task done late comes back on the next date after today, never as a pile of overdue copies.
@remind:9amor@remind:1dgives a desktop notification on the due date or the day before. It works with the window closed to the tray, and after a restart the app tells you what came due while it was quit.randRin the Tasks list, board and calendar set Repeat and Remind (also in the right-click menu, as:repeat/:remindin a note, and in the palette); Skip this time schedules the next one.- Settings → Tasks → Reminders turns them off or sets the default time. Reminders fire from the desktop app, so the phones and the web app leave that section out; a
@remind:written anywhere still fires on the desktop. - Not yet on whole-note tasks (tasks written in a note's frontmatter), the phones or
zn.
- Checking it off writes the next occurrence right above it with the next
- New Kanban for a folder (#1038, asked for by williamcheuk03). Right-click a folder and choose New Kanban: the folder gets a board of its own, one per class, project or client.
- The board is a database,
Untitled Kanban.base, with a Status of To do, Doing and Done, and it opens on its Board. - Also in the command palette, on
Space kin Vim mode, and as:kanban [folder]on the ex line. - The database Board now has a keyboard:
h/j/k/lmove,H/Lcarry a card a column,aadds a card,oopens its page andmits menu. With Vim off, the arrows, Enter and Shift+F10 do the work. - Each column ends in Add card, which stays open for the next one. The No status column shows only while a card sits in it.
- It is plain files, so the phones, a self-hosted server, the web app and
zn baseread it like any database.
- The board is a database,
- Colors for Kanban columns (#1037, asked for by williamcheuk03). Give any column Gray, Red, Yellow, Green, Teal, Blue or Purple.
- Set it from Color… in the column header's menu, with
Cin Vim mode (type to narrow, Enter), or with:color blueon the Tasks ex line. A bare:colorclears it. - Each color comes from the theme's own hue, so Blue is your theme's blue, light and dark.
- A column shows its color as a dot before its title and a thin top edge, and on a field board that value's chips on the cards take the same color.
- Colors are saved in config.toml under
[kanban_column_colors]. Database Board views don't get colors yet.
- Set it from Color… in the column header's menu, with
- Folder fields you pick from (#1033, asked for by williamcheuk03). Task folders, and every other Settings field that names a folder, lists your vault's folders when you focus it.
- That covers excluded folders, the Specific folder for drawings, databases, tasks and shares, the Kanban folder root, the template folder and the Typst preamble folder.
- Typing narrows the list, and Enter or a click picks. A path that matches nothing is kept as typed, so you can name a folder before it exists.
- Keys: the arrows or Ctrl+N / Ctrl+P, Enter, and Escape. The New note form in Search notes uses the same picker.
Fixes
- Settings only zn uses survive the app's saves. The desktop app rebuilt
config.tomlfrom the settings it knows at every launch and every settings change, so zn's[terminal]table (mouse, preview style, math, and since zn 0.14.0 view-mode rules) and keys like[vim] motionswere gone after the first save.- Tables and keys the app does not use now stay in the file as written, comments included, and the app re-reads the file before each write, so a
zn config setmade meanwhile is kept. - A typo in a table the app does not use no longer costs the app its own settings.
- Tables and keys the app does not use now stay in the file as written, comments included, and the app re-reads the file before each write, so a
- Enter in a list keeps the bullets together (reported by SLP on Discord). A blank line between a list's first two bullets (one Shift+Enter is enough) made every bullet typed after it land under a blank line of its own.
- Enter now opens the next item right below, as Vim's
oalready did, and a blank line you typed stays where it is. - Enter on an empty second bullet now ends the list, as it does on any other empty bullet.
- Ending a list leaves a blank line after it, so what you type next is a paragraph of its own. Before, Read mode showed a line typed right under a list as part of its last bullet.
- Enter now opens the next item right below, as Vim's
- New Drawing opens the drawing in a Vault root vault (reported by charles on Discord). With the drawings location set to a folder under
assets/(the old Settings example,assets/drawings), the drawing was written into the attachments folder and nothing opened.- Such a folder now creates in the vault root, and the Settings field says why. Databases and task files get the same fix.
- The field's example now reads
Drawings.
- A database opened in the same pane starts at its own first column. Open a Kanban, scroll its Board right, then make or open another database in that pane: the new board opened scrolled just as far, its first column and Add card off screen. It also kept the previous database's Raw CSV toggle and open menus. Each database now starts fresh.
- A narrow pane keeps the database's name. In a pane around 560 px wide the header's tools squeezed the title to a sliver and pushed the … menu off the edge. The tools now drop to a second line whole, as the Gallery's header does; a wide pane still draws one line.
- Phones leave out what only a keyboard uses. Menus showed hints like "Open page · Enter" on the phones; they now show only what is not a key there (the dot beside the current choice, due dates, a code language's tag, a sort arrow). Lists, boards and grids drew the keyboard's cursor too: the Tasks list's first row tinted with key hints, a ringed card on the boards, the database Table's first cell ringed, the calendar's first task, the Tags and Timeline rows. A phone now draws none of them, and its menus open with no row lit; the desktop is unchanged.
- A tap no longer leaves a tint behind on phones and tablets. A tap counted as hovering, so whatever slid under the finger stayed highlighted until the next tap. Hover styles now apply only where a pointer can hover, and the controls that appear on hover (a row's actions, the Table's select boxes, a tab's close) show all the time on a touch screen instead.
- Back from a note opened from Tasks returns to Tasks. Opening a task from the Tasks list, calendar or board recorded no jump, so
Ctrl+O(and Back on the phones) skipped Tasks and landed on the note before it. The shipped apps did the same. - A database that cannot open says so once. A board whose folder was deleted outside the app stacked an error toast on every redraw (over a thousand on a phone). Now the error toasts once and the view says "Could not open this database." with Try again; a database deleted from another device simply closes its tab, on the web app too.
- The title bar moves the window again after a cancelled drag. A drag something cancels before it starts (grabbing an image's resize handle does) left the window-drag strips switched off until some later drag ended.
- Default Locations. Settings → Vault → Notes titles its location rows Default Locations; it said "New Drawings, Databases & Tasks", which left out shares and named a row the phones hide. Default databases location now says what it does ("Where new databases and Kanban boards are created."), in the row and in Settings search.
- Opening a drawing no longer logs 230 font errors to the developer console. Excalidraw's fallback font addresses now point at the fonts bundled with the app, so the security policy has nothing to block. The fonts themselves were never missing.
For contributors
- config.toml carry-through (
429defec, merge6f978958):serializeConfigwrites the known prefs, then carries through unknown tables and keys as text from a scan of the file's layout (headers, key/value lines, multi-line strings and arrays). A layout the scan cannot split falls back to data, and the result must read back with every carried value or nothing is carried. Once 2.81.0 ships, zn's README caveat (tuidefbdd1) can go. - Recurring tasks and reminders (
8b57ef07, subtasks777e39da, mergef3e60078):@repeatand@remindride the existing@key:valuefield grammar, so the four synced task parsers did not change.planRecurringCompletionis the one shared edit behind every check-off path. Reminders are scheduled in main bytask-reminders.ts, with a ledger of fired keys in userData.task_remindersandtask_reminder_timeare portable prefs under[view]. Remaining slices:docs/ideas/recurring-tasks.md. A board conflict with #1037 was resolved by keeping both: the chip filter and the column color. - List Enter (
afa7839a):lib/cm-tight-list-enter.tsruns upstream'sinsertNewlineContinueMarkupCommand({ nonTightLists: false })and takes the loose-list blank line back out of the finished transaction, so ordered-list renumbering stays upstream's. Vimo's quoted-line prefix reads the same command. - Create locations (
c6b96892):reservedCreateFolderTopinlib/vault-layout.ts, andresolveCreateLocationfalls back to the primary location. The Settings rows explain the redirect throughspecificFolderOutcome. - Folder picker (
79b768f9, merge30ba76c0):lib/folder-picker.tsandlib/use-folder-picker.ts, shared byFolderPickerInputand the New note form. - Column colors (
3e565680, merge1f70c3e6):lib/kanban-column-colors.tsmaps palette names to theme hue tokens, with a test holding every theme block to all seven.[kanban_column_colors]is a portable pref. - New Kanban (
9f824b44, merge65913790): an optionalboardin the database seed, written byinitialDatabaseContentsfor desktop main anddatabase-opsalike. There is no new bridge method, Go route or file format. The keyboard lives inDatabaseBoardView. - Excalidraw fonts (
51159308, merge5f9a17b4): a build-time rewrite inelectron.vite.config.tsplusrenderer/excalidraw-asset-path.ts. - Found by the phone walks of the candidate core and fixed before the cut:
- Reminders settings (
d9e7c36a): shown only wherewindow.zen.setTaskRemindersexists, the same checktask-reminders-runtimemakes; the search index follows. - Database scroll (
08e46c85):DatabaseViewis keyed by its tab, asGalleryViewis. - Narrow header (
c79731f0): the database header wraps likeGalleryView's. - Menus (
507f117d):ContextMenuItem.hintis a key and is left out on a touch-first device; a newmarkcarries side text that is not a key. - Phones (
dc7f3eec):createBrowseKanban(host, directory?)in@zennotes/app-core/browsegives the phones' folder sheet New Kanban. - Task jumps (
99553fcb):openTaskAtrecords the jump withnoteHistoryAfterJump, asopenNoteAtOffset(#484) does. - Drag strips (
ec836bcc): a dragstart cancelled later in its dispatch clearszn-app-draggingonce the dispatch is over. - List exit (
8e78c8a6):cm-tight-list-enter.tsadds a blank line when Enter on an empty, unquoted item ends the list. - Failed database loads (
3824860a, web32c20a66):databasesLoadErrorkeeps the view from retrying; the web bridge answers null for a missing database, as desktop main does. - Touch hover (
bfab9fdc):hoverOnlyWhenSupportedinbuild/tailwind-preset.cjs(and the root config);zn-hover-revealmarks the hover-only controls that index.css shows where nothing can hover. Tooltips and key hints carry no class. - Keyboard cursor (
0628c9e2,16734463,bcce61e1, menus2ba2a9ed):useKeyboardCursor()inlib/keyboard-cursor.tssays whether to draw it; a touch-first device draws none, and only the drawing depends on it. - Copy (
2dc9388c,52500183,bc248281,046aaa92): the location section is Default Locations, and its rows say what they do in one line.
- Reminders settings (
Demos
Captioned 1080p clips recorded on the v2.81.0 build. The fix clips play the released 2.80.1 first, then 2.81.0.
Recurring tasks: x on a weekly checklist brings next week's back with its subtasks open; r makes Pay rent monthly and R adds a reminder the day before; the note shows next week's copy above and this week's record below, the open items cancelled. Watch the clip (23 seconds, captioned).
New Kanban: right-click Biology, New Kanban; three cards from Add card, one dragged to Doing, one carried to Done with L; Chemistry gets its own board. Watch the clip (33 seconds, captioned).
Column colors: C on In progress, "blu", Enter; :color teal on Upcoming; Color…, Red on Today from the header's menu. Watch the clip (24 seconds, captioned).
Folder picker: Task folders lists the vault's folders, "bio" and Enter adds Courses/Biology, ↓ ↓ Enter adds Projects/Website, and the Drawings folder field picks the same way. Watch the clip (24 seconds, captioned).
Lists, before and after: SLP's keys. Shift+Enter after the first bullet, then Enter for two more. On 2.80.1 every new bullet gets a blank line; on 2.81.0 they go right below. Watch the clip (22 seconds, captioned).
New Drawing, before and after: a Vault root vault with drawings set to assets/drawings. On 2.80.1 New Drawing opens nothing; on 2.81.0 the drawing opens at the vault root and Settings says why. Watch the clip (24 seconds, captioned).
Verification
How to test locally. Build once with npm run build --workspace @zennotes/desktop and launch with isolated stores: ZENNOTES_USER_DATA_PATH=$(mktemp -d) ZENNOTES_CONFIG_DIR=$(mktemp -d) npx electron apps/desktop/out/main/index.js. Turn Vim mode on in Settings for the letter keys.
- Recurring tasks. Write
- [ ] Weekly review @repeat:weekly due:<today>with two indented- [ ]lines, one ticked. Check off the parent: next week's copy appears above with both subtasks open, and the record below reads- [x]with the open one as- [-]. In Tasks, pressRon a task and pick1d: the line gains@remind:1d. - New Kanban. Make a folder
Biology. Right-click it, New Kanban: a board with To do, Doing and Done opens. Click Add card, type two titles with Enter after each. Drag one to Doing. Click the other and pressLtwice: it lands in Done.Biology/Untitled Kanban.base/data.csvlists both with their status. - Column colors. Open Tasks, Kanban. Right-click Today's header, Color…, Red: a red dot and top edge. Move to another column, press
C, typeblu, Enter: blue.:colorclears it. config.toml now has a[kanban_column_colors]table. - Folder picker. Settings, Tasks, Task folders: click the field, and your folders are listed. Type part of one, Enter: it is added. In Settings, Vault, set Default drawings location to Specific folder and pick a folder the same way.
- Lists. Type
- one, Enter,two. Go to the end ofone, press Shift+Enter, then go to the end oftwoand press Enter twice. Before the fix every new bullet got a blank line; now they go right below. Then press Enter on an empty bullet: the list ends with a blank line after it, so what you type next is a paragraph of its own. - New Drawing. In a vault set to Vault root, set Default drawings location to Specific folder
assets/drawings. Run New Drawing: it opens, saved at the vault root, and the Drawings folder row reads "assets/holds attachments, so new drawings go to the vault root." - zn's settings in config.toml. Add
[terminal]withmouse = falseto~/.config/zennotes/config.toml(or runzn config set), then change any setting in the app: the[terminal]table is still in the file afterwards. - Drawing fonts. Open a drawing with the developer tools open: no "violates the following Content Security Policy directive" font errors.
- Database scroll. Make a window about 900 px wide and run
:kanban. Scroll the board right, then run New Kanban from the palette: the second board opens at To do, and its header keeps the name "Untitled Kanban 2" with the tools on a second line.
Distribution channels
- GitHub release: installers for macOS (Apple silicon and Intel DMG and zip), Windows (x64 and ARM64 installer and zip) and Linux (x64 and arm64 AppImage, deb, rpm, pacman, tar.gz), with five update manifests;
promote-latestmarked it latest once the last feed was up (release run 41373958454). - AUR:
zennotes-bin2.81.0-1 (AUR clonefd2d0fd, repo12f8c938), pinned toZenNotes-2.81.0-linux-x64.tar.gzSHA-2565e9f7861…4385after the bump script checked the bundled CLI folder. - Nix:
packaging/nix/release-data.jsonfrom the update workflow (run 41375333733, bot PR #1041 closed) as05c04202;nix-buildpassed on main (run 41375626162). - nixpkgs: NixOS/nixpkgs#579420, now 2.74.0 → 2.81.0 and still waiting for review; the source hash is the tag tarball's, by the same prefetch that reproduces master's 2.74.0 hash.
- Homebrew:
zennotes2.81.0 in the tap (0a871e3), mirrored in235f4f8d; DMG SHA-256 arm64afd4d675…, x6469264b7d…. - Website: ZenNotes/website#104 merged at
7dd72cf1(docs, the release entry with six clips, zn 0.14.0, server 2.81.0, Android 1.1.51 and 1.1.52, iPhone 1.35.0, the 2.81.0 share viewer); deployed by its owndeployjob on Laravel Cloud, and the live check passed (clips byte-identical, range requests, docs, every app tab). - zn CLI: 0.14.0 (ZenNotes/tui#31, tag
v0.14.0, Homebrew formula0eadcc6, tap43a479f) is bundled (27953503, signed manifest verified againstzn-release-1). - Server: ZenNotes/znserver v2.81.0 (#62, README #63) pins
web-2.81.0-web.h7628547a4b0d2d18; Dockeradibhanna/zennotes:2.81.0,2.81,latestatsha256:19412592…(amd64, arm64). - Boundary packages:
core-2.81.0-core.h4e6a38a3361b4748,web-2.81.0-web.h7628547a4b0d2d18andviewer-2.81.0-viewer.hfe81ba39327b44ba, built from the tag's commit and published as pre-releases. - Phones: iPhone 1.36.0 (build 55) Waiting for Review, with the App Store's new product-page header, search-results art and iPhone Duo screenshots; Android 1.1.52 (versionCode 55) live on Google Play at full rollout, with its GitHub release carrying Play's universal APK.
Release validation
- Local gates on the release commit
bfab9fdc, in a cleannpm cicheckout: typecheck, every test suite uncached (shared-domain 2341, app-core 4694, desktop 1376, Quick Look 18),build:prod, the three smoke suites,npm run packand the packaged launch check (page target, rendered, 2.81.0), hazard scan and dash lint. - #1039: all ten checks green. Its first push failed CodeQL alert #145 on a test helper (
replace('|', '')marking the caret), fixed in8bc2209c. CI onmainpassed on the release commit before the tag (run 41372505185, CodeQL 41372505142). verify-installers.py: every file the five feeds name is present at its size; both DMGs are Notarized Developer ID and stapled, reporting 2.81.0;npm run verify:channels -- 2.81.0reported every channel serving 2.81.0.- The phones walked six candidate cores before the cut, and each fix they found is in this release (the Fixes above from "A database opened in the same pane" down).
- The tag moved once. It was first pushed on
bcce61e1; the Android release-build walk then found three core bugs older than 2.81 (the list exit, the database error loop, the menus' lit row), and the iPhone walk found the tint a tap leaves behind. Those were fixed (8e78c8a6,3824860a,32c20a66,2ba2a9ed,bfab9fdc), the first release run (41370044827) was cancelled, and the tag moved tobfab9fdcbefore AUR, Nix or Homebrew pinned anything. - Known issue, shipping in 2.81.1: the tap fix shows hover-only controls all the time on a touch screen, and in the database Table the row's Open button then covers a long page name. The phone apps carry their own fix for it. The web app from server 2.81.0, used on a tablet or phone browser, still shows it; the desktop app is not affected. The core fix is ready on
fix/table-open-touch(24a5831b,c80e9e5b).- The list replay comes out tight.