Summary
Make Emanote's task index (/-/tasks) a date-aware, filterable dashboard by understanding Obsidian Tasks emoji syntax. Tasks stay authored inline in their notes (- [ ] …); only the rendering gets smarter. Emanote stays read-only — completing/rolling tasks is the editor's job; Emanote displays.
Motivating use case: a calm, pull-not-push daily task dashboard (GTD "open loops" style) — a view you open, never a nag.
Authoring syntax (target)
Standard Obsidian Tasks emoji, appended to any - [ ] line:
- [ ] Draft the release notes 📅 2026-07-03 #active
- [ ] Follow up with the vendor ⏳ 2026-12-01 🔼 #waiting
- [ ] Send the monthly report 📅 2026-07-21 🔁 every month #active
| Emoji |
Meaning |
Phase |
📅 due · ⏳ scheduled · 🛫 start |
dates |
1 |
➕ created · ✅ done · ❌ cancelled |
dates |
1 |
🔺⏫🔼🔽⏬ |
priority |
3 |
🔁 |
recurrence rule |
3 |
🆔 / ⛔ |
id / depends-on |
later |
Task "state" (e.g. active/waiting/held/someday for a loop workflow) is just a #tag — already supported, no new syntax. Hierarchical tags (#loop/active, #loop/held, …) are recommended so related states share a namespace and filter as a group (loop/*).
Current behaviour (baseline)
/-/tasks (View/TaskIndex.hs) lists unchecked tasks, grouped by note, in path order; no dates, no filtering. Emoji/dates render as literal text. Tasks can't be filtered by tag (a task's inline #tag tags the note, not the task). This proposal changes that.
Phase 1 — Show task dates (PR 1)
You get: every task on /-/tasks shows its due/scheduled date as a badge, with overdue in red and due-today highlighted (computed live from the browser clock, so it never goes stale on the static site).
- Parse the date emoji from each task's inlines into the task model (
_taskDueDate, _taskScheduled, …); strip the recognised tokens from the rendered text and emit badges instead.
- Parse in Emanote's task layer (
Model/Task.hs) — no change to the heist-extra parser needed.
- Template emits
data-due etc.; a tiny vanilla loops.js adds the overdue/today classes. JS-off still shows the plain list.
Phase 2 — Filter & sort dashboard (PR 2)
You get: /-/tasks becomes a real dashboard — filter by tag (hierarchical, so namespaced states filter individually or as foo/*) and by due window (overdue · next 3 days · all), sort by due, and toggle group-by-note ⇄ a flat agenda. Default view = "what needs me soon."
- Emit
data-tags per task; client-side controls do the filtering/sorting (no rebuild).
- A small load count ("12 open · 3 due") for at-a-glance load.
Phase 3 — Priority & recurrence (PR 3)
You get: priority badges (⏫/🔼/🔽) that sort, and recurring tasks (🔁) shown with their rule and a computed next due.
- Parse priority + recurrence; extend sort to (overdue, priority, due).
- Recurrence is display only — Emanote doesn't mutate files.
Phase 4 — Embedded task queries (PR 4)
You get: drop a query into any note to embed a filtered task list — e.g. a hand-made dashboard page showing "all #active due this week." Composability beyond the global /-/tasks.
- Extend the query mechanism (
Model/Query.hs, currently note-only) with a tasks source + a render template, reusing the Phase 1–3 parsing.
Non-goals
- Reminders / push. Pull-not-push — a view you open, not a nag. No notifications, no server.
- Editing/completing tasks. Emanote renders; an editor (or external tooling) mutates the Markdown.
Key files
heist-extra:TaskList.hs (low-level parse) · Model/Task.hs (indexed task + new metadata) · View/TaskIndex.hs + templates/special/tasks.tpl (the view) · Model/Query.hs (Phase 4) · new default/js/loops.js.
Summary
Make Emanote's task index (
/-/tasks) a date-aware, filterable dashboard by understanding Obsidian Tasks emoji syntax. Tasks stay authored inline in their notes (- [ ] …); only the rendering gets smarter. Emanote stays read-only — completing/rolling tasks is the editor's job; Emanote displays.Motivating use case: a calm, pull-not-push daily task dashboard (GTD "open loops" style) — a view you open, never a nag.
Authoring syntax (target)
Standard Obsidian Tasks emoji, appended to any
- [ ]line:📅due ·⏳scheduled ·🛫start➕created ·✅done ·❌cancelled🔺⏫🔼🔽⏬🔁🆔/⛔Task "state" (e.g. active/waiting/held/someday for a loop workflow) is just a
#tag— already supported, no new syntax. Hierarchical tags (#loop/active,#loop/held, …) are recommended so related states share a namespace and filter as a group (loop/*).Current behaviour (baseline)
/-/tasks(View/TaskIndex.hs) lists unchecked tasks, grouped by note, in path order; no dates, no filtering. Emoji/dates render as literal text. Tasks can't be filtered by tag (a task's inline#tagtags the note, not the task). This proposal changes that.Phase 1 — Show task dates (PR 1)
You get: every task on
/-/tasksshows its due/scheduled date as a badge, with overdue in red and due-today highlighted (computed live from the browser clock, so it never goes stale on the static site)._taskDueDate,_taskScheduled, …); strip the recognised tokens from the rendered text and emit badges instead.Model/Task.hs) — no change to theheist-extraparser needed.data-dueetc.; a tiny vanillaloops.jsadds the overdue/today classes. JS-off still shows the plain list.Phase 2 — Filter & sort dashboard (PR 2)
You get:
/-/tasksbecomes a real dashboard — filter by tag (hierarchical, so namespaced states filter individually or asfoo/*) and by due window (overdue · next 3 days · all), sort by due, and toggle group-by-note ⇄ a flat agenda. Default view = "what needs me soon."data-tagsper task; client-side controls do the filtering/sorting (no rebuild).Phase 3 — Priority & recurrence (PR 3)
You get: priority badges (
⏫/🔼/🔽) that sort, and recurring tasks (🔁) shown with their rule and a computed next due.Phase 4 — Embedded task queries (PR 4)
You get: drop a query into any note to embed a filtered task list — e.g. a hand-made dashboard page showing "all
#activedue this week." Composability beyond the global/-/tasks.Model/Query.hs, currently note-only) with ataskssource + a render template, reusing the Phase 1–3 parsing.Non-goals
Key files
heist-extra:TaskList.hs(low-level parse) ·Model/Task.hs(indexed task + new metadata) ·View/TaskIndex.hs+templates/special/tasks.tpl(the view) ·Model/Query.hs(Phase 4) · newdefault/js/loops.js.