Project Planner — turn the tasks already in your vault into a real plan

Qualify workflow Release workflow GitHub Release Downloads License

--- **Project Planner** turns the tasks you already have in your Obsidian vault into a plan you can actually run a project from — a dependency graph, a Gantt chart with a real critical path, a kanban board, and time-and-materials costing. Nothing lives in a proprietary database. Every task, date, dependency, person and cost is read from and written back to plain Markdown, in the same [Tasks](https://github.com/obsidian-tasks-group/obsidian-tasks) and Dataview syntax you were already using. Delete the plugin and your notes still read exactly the same.

The graph view

--- ## Contents - [Why this exists](#why-this-exists) - [Requirements](#requirements) - [Installation](#installation) - [Quick start](#quick-start) - [How tasks are read](#how-tasks-are-read) - [The graph view](#the-graph-view) - [The Gantt view](#the-gantt-view) - [The board view](#the-board-view) - [Finance](#finance) - [Embedding a graph in a note](#embedding-a-graph-in-a-note) - [Companion notes](#companion-notes) - [Undo](#undo) - [Metadata reference](#metadata-reference) - [Commands](#commands) - [Settings](#settings) - [Relationship to Tasks Map](#relationship-to-tasks-map) - [Development](#development) - [License](#license) --- ## Why this exists Most task plugins are good at *capture* and weak at *planning*. They will tell you what is due on Thursday. They will not tell you which of the eleven things due on Thursday is the one that, if it slips, moves your delivery date. Project Planner is built around dependencies rather than dates: - **Dependencies are the primary data.** A task that is blocked knows what it is waiting on, and every view is a different way of reading the same graph. - **Every task gets a bar, dated or not.** Undated tasks are placed by their dependencies rather than dropped, so a plan is useful before anybody has sat down to fill in dates. - **Suggestions are never silently written.** Inferred dates are drawn dashed and stay out of your notes until you accept them. - **Nothing is invented.** Shares that do not total 100% are reported, not scaled. People with no rate cost nothing and are listed as unpriced. Costs resting on guessed dates are counted separately from costs resting on real ones. --- ## Requirements | Plugin | Required? | Why | | --- | --- | --- | | [Dataview](https://github.com/blacksmithgu/obsidian-dataview) | **Yes** | Reads inline `- [ ]` checkbox tasks out of your vault. The views refuse to render without it. | | [Tasks](https://github.com/obsidian-tasks-group/obsidian-tasks) | Optional | Adds **Create task** and **Edit task** to the node context menu, using the Tasks plugin's own modal. | Obsidian **1.8.0** or newer. Works on desktop and mobile — no Node or Electron APIs are used. --- ## Installation ### From the community plugin browser **Settings → Community plugins → Browse**, search for **Project Planner**, install and enable. ### Manually 1. Download `main.js`, `manifest.json` and `styles.css` from the [latest release](https://github.com/HMIL1151/project-planner/releases). 2. Copy them into `/.obsidian/plugins/project-planner/`. 3. Reload Obsidian, then enable **Project Planner** under **Community plugins**. --- ## Quick start Write two ordinary tasks in any note, and give one an ID the other can point at: ```markdown - [ ] Draw up the frame 🆔 frame 🛫 2026-03-02 📅 2026-03-06 - [ ] Weld the frame ⛔ frame 📅 2026-03-11 - [ ] Paint it ⛔ weld - [ ] Ship it 🆔 ship ⛔ paint ``` Open the **graph** icon in the ribbon. You get four connected nodes. Open the **Gantt** icon and you get four bars — the two with dates drawn where you put them, the two without drawn dashed, placed the day after whatever blocks them. Turn on **Critical path** and the chain that decides the finish date lights up. --- ## How tasks are read Two kinds of task, both first-class, both read into the same model. ### Inline checkbox tasks Any `- [ ]` line anywhere in your vault, read via Dataview. ```markdown - [ ] Fit the sensor loom 🆔 loom ⛔ frame 🛫 2026-03-02 📅 2026-03-06 #electrical 🔼 ``` Statuses come from the checkbox itself: `[ ]` to do, `[/]` in progress, `[x]` done, `[-]` cancelled. ### Note tasks A whole note becomes one task when its frontmatter is tagged `task`. Use these when a task needs somewhere to put detail. ```yaml --- tags: - task start: 2026-03-02 due: 2026-03-06 blockedBy: [frame] progress: 40 --- ``` ### Both syntaxes, everywhere Dependencies and metadata can be written as Tasks-plugin emoji or as Dataview inline fields, and the two can be mixed freely across a vault. Project Planner reads whichever a line already uses and **writes back in the same style**, so it never reformats notes into a house style you did not choose. ```markdown - [ ] Emoji style 🆔 a1 ⛔ b2 📅 2026-03-06 - [ ] Dataview style [id:: a1] [dependsOn:: b2] [due:: 2026-03-06] ``` --- ## The graph view The dependency graph, on a pannable ReactFlow canvas with automatic [dagre](https://github.com/dagrejs/dagre) layout. ### Nodes Each task is a node showing its text, status, tags, priority and progress. Node controls: | Control | Action | | --- | --- | | Status circle | Cycle the task's completion status | | Star | Star or unstar the task (`⭐`) | | Arrow | Open the note the task lives in | | **⋮** | Context menu — create a child task, edit, set finance, delete | | Tag chips | Click **×** to remove a tag, **+ Add tag** to add one | Wiki-links in task text render as real links and open the note they point at. ### Edges Drag from a node handle to another node to create a dependency; the `⛔`/`🆔` metadata is written into both notes. Click an edge and press `Delete` to remove it, which strips the reference from the vault. **Chain healing:** deleting a task in the middle of `A → B → C` hands B's blockers to whatever was waiting on B, so `A → C` survives rather than the chain quietly falling apart. **Per-edge styling:** right-click an edge to override its line style individually, on top of the global Bezier / Straight / SmoothStep setting. ### Critical path Toggle **Critical path** to compute float across the whole plan — the gap between when each task finishes and the latest it could finish without moving the delivery date. Tasks with zero float are the critical path and are highlighted in both the graph and the Gantt. This is the set worth arguing about when a deadline is at risk; everything else has room to move. ### Search, filters and traversal The right-hand filter panel carries: | Filter | Description | | --- | --- | | Search | By task text, ID or tag, with a live suggestion list (`↑`/`↓`/`Enter`/`Escape`) | | Show dependencies / dependents | Pull the upstream and/or downstream chain of a search hit into view | | Status | Multi-select — to do, in progress, done, cancelled | | Include labels | Show only tasks carrying at least one selected tag | | Exclude labels | Hide tasks carrying any selected tag | | Files / folders | Restrict to selected notes or folders | | Only starred | Show only starred tasks | **Filter presets** save any combination by name, restore it in one click, and can be inserted straight into a note as an embed block. ### Unlinked tasks panel Tasks with no dependencies in either direction are moved to a left-hand panel rather than scattered across the canvas as noise. Search it, then drag any task onto the canvas to work with it. Connect it to something and it stays on the canvas for good. ### Project groups Tasks sharing a project are drawn inside a labelled group container, so a large vault reads as a handful of projects rather than one undifferentiated cloud. --- ## The Gantt view The same tasks on a timeline. ### Every task gets a bar A chart that only drew dated tasks would be nearly empty in a real vault, so every task is placed: | The task has | The bar is | | --- | --- | | Start (`🛫`, or `⏳` as fallback) and due (`📅`) | Drawn between them | | Start only | One day long | | Due only | Drawn from when its blockers finish up to the deadline — the window available | | Neither | Starts the day after its last blocker finishes, lasts one day | Because inference walks the dependency graph, a chain of undated tasks spreads out day by day in the order the graph says they must happen. ### Suggested dates stay suggestions Inferred bars are drawn as **dashed outlines** and nothing is written to your notes while they stay that way. Turn a proposal into a real date by dragging or resizing the bar, or use **Apply suggested dates** to write every dashed bar at once and get a count of what changed. ### Editing | Action | Result | | --- | --- | | Drag a bar sideways | Moves start and due together, keeping the length | | Drag either edge | Changes that date alone | | Click a task name | Selects the row and lights up its whole dependency chain | | Drag the grip | Reorders rows; the order is saved | | **+** on a row | Writes a new task directly below it, in the same note | | **Link** on a row | Starts a dependency — click the task it should block | Dragging snaps to whole days and a bar can never be shorter than one day. ### Scheduling controls - **Working days** — measure durations in working days and keep bars off weekends. The finance view follows the same setting, so money and schedule can never disagree. - **Sort by date** — a *mode*, not a one-off shuffle: rows are drawn flat and earliest first while it is on, and your manual order and nesting come back untouched when you turn it off. - **Group by** — tag, status, note or project. - **Collapse** — fold a parent's children away; parents roll their children's span up into one bar. - **Zoom** — days, weeks or months, with a **Today** button. ### Milestones Named days marked across the whole chart — "Design freeze", "Release 1.0" — drawn as a diamond in their own band with a dashed line down the timeline. Milestones are not tasks: no note, no duration, no dependencies, and nothing is ever written to your vault. Past milestones draw grey, today's orange, future ones purple. The timeline always stretches far enough to reach them. ### Schedule warnings Three ways a plan quietly goes wrong, flagged on the rows and counted under the chart: | Warning | Meaning | | --- | --- | | **Overdue** | Finished on paper before today, and not marked done | | **Stalled** | Should have started, and has not been touched | | **Backwards dependency** | A blocker finishes *after* the work waiting on it | Only dates you actually wrote are judged — flagging the chart's own guesses would be noise. ### PNG export Export the chart as a picture for a report or a slide. This is deliberately **not** a screenshot: it is a separate drawing of the same plan, laid out for paper. The whole timeline is fitted to the page width so nothing runs off the edge; it uses four print-safe colours; it drops weekend bands, day ticks and dependency arrows, which are the first things to become noise at page size; and it makes the parts that carry meaning bigger — title, span, group headings, milestone names, and a legend listing only what the chart actually uses. Today is marked only when today falls inside the plan. --- ## The board view Where the Gantt answers *when*, the board answers *what state is this in* — and dragging a card is what changes the answer. | Group by | Columns | Dragging writes | | --- | --- | --- | | Status | To do, In progress, Done, Cancelled | The checkbox | | Due date | Late, Today, Tomorrow, Rest of this week, Next week, Later, No date | The `📅` due date | | Person | One per name in `[people:: …]`, plus Unassigned | The task's people | | Tag | One per tag in use, plus No tag | The task's tags | | Project | One per project | *read only* | | Priority | 🔺 ⏫ 🔼 🔽 ⏬, plus No priority | *read only* | | Note | One per note holding tasks | *read only* | Dropping a card into a date column writes a real due date, so the card stays where you put it. Dropping one into a person's column makes it theirs alone; dropping it into **Unassigned** removes the people entirely. Read-only groupings show a padlock and refuse cards from other columns, but cards can still be reordered within them. Card order is one list for the whole board, so a card dragged to another column keeps the position you dropped it in, and changing the grouping does not throw your arrangement away. Columns can be folded away, remembered per grouping. The **+** in a column header adds a task already carrying whatever that column stands for. --- ## Finance Time-and-materials planning, **off by default** — enable it under **Settings → Project Planner → Finance**. A task consumes hours; those hours are worked by named people in some proportion; each person sits at a grade with a chargeout rate; and materials sit on top. ### The rates note Rates live in a note you own, not in plugin settings, so you can link to them and keep them in version control. Default path `Finance/People and rates.md`. ```markdown | Grade | Rate | | ---------- | ---- | | Principal | 145 | | Senior | 110 | | Person | Grade | Rate | | ----------- | --------- | ---- | | Alice Smith | Principal | | | Cara Diaz | Senior | 130 | ``` Tables are found by their **column headers**, not the headings above them, so you can retitle, reorder and write whatever prose you like around them. A person's own `Rate` overrides their grade's. Rows that cannot be read are dropped and reported with their line number. ### Putting finance on a task ```markdown - [ ] Fit the loom [hoursPerDay:: 6] [people:: Alice Smith 60%, Bob Jones 40%] [costs:: Loom kit 240, Travel 85] ``` | Field | Meaning | | --- | --- | | `hours` | Explicit total hours — wins over everything | | `hoursPerDay` | Per-task override of the global default | | `people` | Who is on it, and their share | | `costs` | Materials and expenses | Synonyms are accepted (`totalHours`/`estimatedHours` → `hours`, `allocations`/`who` → `people`, `expenses`/`materials` → `costs`), and shares may be written `60%`, `60` or `0.6`. The canonical spelling is written back. ### How the cost is worked out Hours come from an explicit total if there is one, otherwise from the length of the task's bar × its hours-per-day. Rates resolve person-first, then grade. Name matching is on meaning, not typing — `Alice Smith`, `alice smith` and `[[Alice Smith]]` are one person. **What it refuses to fake:** - Someone with no rate costs **nothing**, and their hours are reported as unpriced rather than counted as free. - Shares that do not total 100% are used **exactly as written** — scaling 60% + 30% up to 100% would hide a typo and inflate the plan. - Cost resting on *suggested* dates is counted separately, and **Include suggested dates** leaves it out. A vault full of undated tasks will never quietly read as a large invented cost. ### The dashboard Headline tiles (total, labour, materials, hours, tasks priced, tasks with no finance), the labour/materials split, a **breakdown** by person, grade, project, tag, status or note, **cost over time** by week or month, the **ten biggest costs** each clickable through to the Gantt, and a **Problems** section listing everything that could not be worked out. --- ## Embedding a graph in a note A fenced `project-planner` block renders a fully interactive graph inline. ````markdown ```project-planner { "filter": { "onlyStarred": true, "selectedStatuses": ["todo", "in_progress"] }, "config": { "height": 300, "showMinimap": false, "showFilterPanel": false } } ``` ```` An empty body (`{}`) shows the full graph with defaults. **Filter keys:** `selectedTags`, `excludedTags`, `selectedStatuses`, `selectedFiles`, `searchQuery`, `traversalMode` (`match`/`upstream`/`downstream`/`both`), `onlyStarred`. **Config keys:** `height`, `showMinimap`, `showFilterPanel`, `showPresetsPanel`, `showUnlinkedPanel`, `showStatusCounts`. Rather than writing these by hand, use **Insert current filter as embedded graph** from the command palette, or the insert button on a saved filter preset — both generate correct JSON. > Blocks tagged ` ```tasks-map ` from before the rename are still rendered, so > notes written against the old plugin keep working. --- ## Companion notes A checkbox line has nowhere to put detail. With companion notes enabled, creating a task also creates a note for it and turns the task's text into a link to that note. The note is deliberately **not** tagged `task` — that would make it a second task in its own right and draw a duplicate node. **Create notes for existing tasks** retrofits the whole vault at once, after asking for confirmation and telling you how many notes it will write. --- ## Undo One undo history, owned by the plugin and shared across every view — so the board can take back an edit the Gantt made, and vice versa. Row reorders, card moves, date drags, milestone changes, people reassignments and tag edits all step back through it. Vault writes are optimistic: the UI updates immediately and rolls back if the write fails. --- ## Metadata reference Everything Project Planner reads and writes. Every emoji field has a Dataview equivalent in `[field:: value]` or `(field:: value)` form. | Concept | Emoji | Dataview | Note-task frontmatter | | --- | --- | --- | --- | | Task ID | `🆔 abc` | `[id:: abc]` | — (the note is the identity) | | Blocked by | `⛔ abc` or `⛔ a,b,c` | `[dependsOn:: abc]` | `blockedBy:` / `dependsOn:` | | Due date | `📅 2026-03-06` | `[due:: 2026-03-06]` | `due:` | | Start date | `🛫 2026-03-02` | `[start:: 2026-03-02]` | `start:` | | Scheduled | `⏳ 2026-03-02` | `[scheduled:: …]` | `scheduled:` | | Created / done / cancelled | `➕` `✅` `❌` | — | — | | Priority | `🔺 ⏫ 🔼 🔽 ⏬` | — | — | | Starred | `⭐` | — | — | | Progress | — | `[progress:: 40]` or `40%` | `progress:` | | Parent | — | `[parent:: abc]` | `parent:` | | Tags | `#tag` | — | `tags:` | | Hours | — | `[hours:: 12]` | `hours:` | | Hours per day | — | `[hoursPerDay:: 6]` | `hoursPerDay:` | | People | — | `[people:: Alice 60%, Bob 40%]` | `people:` | | Costs | — | `[costs:: Loom kit 240]` | `costs:` | Out-of-range progress is clamped rather than rejected — someone who typed 120 meant "finished". Progress above zero displays as in-progress whatever the checkbox says, but 100% is never auto-promoted to done: finishing the work and declaring the task closed are different claims, and only the second is yours to make. --- ## Commands | Command | Description | | --- | --- | | Open graph view | The dependency graph | | Open Gantt view | The timeline | | Open board view | The kanban board | | Open task finance | The finance dashboard *(when finance is enabled)* | | Create the rates note | Creates and opens the rates note *(when finance is enabled)* | | Create notes for existing tasks | Retrofit companion notes across the vault | | Insert current filter as embedded graph | Write an embed block into a note | Ribbon icons are provided for the graph, Gantt, board and — when enabled — finance views. --- ## Settings | Group | Settings | | --- | --- | | **Display** | Show priorities, show tags, show status counts | | **Layout** | Direction (horizontal/vertical), edge style (Bezier/Straight/SmoothStep), SmoothStep corner radius | | **Tag appearance** | Palette (Rainbow, Ocean, Forest, Sunset, Mono) plus per-tag colour pinning, with **Reset all** | | **Task relations** | How dependencies are written: CSV, individual, or Dataview | | **Gantt** | Working days, critical path, schedule warnings, row order and collapsed rows | | **Board** | Group-by, card order, collapsed columns | | **Finance** | Enable, rates note path, default hours per day, currency, include suggested dates | | **Companion notes** | Enable, and the folder to write them to | | **Language** | English, Nederlands, 简体中文 | | **Advanced** | Debug visualisation overlays | --- ## Relationship to Tasks Map Project Planner began life as a fork of **[Tasks Map](https://github.com/NicoKNL/tasks-map)** by [Nico Klaassen](https://github.com/NicoKNL), and it owes that project its foundation: the graph canvas, the dual inline/note task model, the Dataview integration and the filtering core all started there. Credit where it is due — that groundwork is what made the rest possible, and it remains MIT licensed with the original copyright notice intact. It has since grown into a substantially different plugin. Tasks Map visualises tasks as a graph. Project Planner is a project-planning tool that happens to include that graph. Added since the fork: - **The Gantt view** in its entirety — date inference from the dependency graph, dashed suggestions that stay out of your notes, drag-to-schedule, working-day scheduling, grouping and collapsing, date-order mode, milestones, schedule-risk warnings, and print-oriented PNG export. - **Critical path analysis** — float computed across the whole plan, surfaced in both the graph and the Gantt. - **The kanban board** — seven groupings, each writing back the thing its columns stand for. - **The finance system** — rate books read from a note you own, per-task hours, people and materials, cost roll-ups by person, grade, project, tag, status and note, cost-over-time, and a problems report that refuses to invent numbers. - **Companion notes**, with vault-wide retrofit. - **Chain healing** on task deletion, so removing a task does not break the run of work through it. - **Plugin-wide shared undo** across every view. - **Progress tracking**, parent/child hierarchy, project grouping, per-edge style overrides and filter presets. The name changed because "Tasks Map" no longer described it. This is a planner that reads your tasks, not a map of them. --- ## Development ```bash npm install npm run dev ``` | Command | Purpose | | --- | --- | | `npm run dev` | esbuild watch build | | `npm run build` | Typecheck + production bundle | | `npm run build:deploy` | Build, then copy into a local vault | | `npm test` | Jest | | `npm run lint` | ESLint over `src/**/*.{ts,tsx}` | | `npm run lint:css` | Stylelint | | `npm run format` | Prettier check | `src/lib/` is pure, framework-free logic — scheduling, critical path, finance, costing, Gantt rows, filtering and graph traversal — and is where the unit tests point. React components stay presentational. Set a deploy target in `.obsidian-plugin-dir` or `$OBSIDIAN_PLUGIN_DIR`; `deploy.mjs` copies `main.js`, `manifest.json` and `styles.css` and never touches your vault's `data.json`. Contributions are welcome — please open an issue or PR. --- ## License [MIT](LICENSE). Copyright © 2025 Nico Klaassen (original Tasks Map plugin) and © 2025–2026 Harrison Milburn (Project Planner). The original copyright notice is retained as the MIT License requires.