Skip to content

Dependency-aware task graph

A card can’t tell you what it’s waiting on.A node can.

NodeKanban trades Kanban columns for an infinite canvas. Tasks are nodes, edges carry the dependency logic, and blocked is worked out from the graph instead of typed into a field that goes stale by Thursday.

3 boards · 150 nodes per board · no card required

nodekanban / mvp — 7 nodes, 7 edges
A NodeKanban board with seven tasks and seven dependenciesPostgres schema and Auth are done. Board canvas is in progress, Stripe checkout is to do, Realtime presence is in the backlog. Seat billing webhook is blocked, waiting on Stripe checkout. Public beta is blocked, waiting on Board canvas and Realtime presence.NB-04Postgres schema + RLSDONENB-07Auth + org bootstrapDONENB-12Board canvasIN PROGRESSNB-19Stripe checkoutTODONB-23Realtime presenceBACKLOGNB-26Seat billing webhookBLOCKEDWAITING ON: STRIPE CHECKOUTNB-31Public betaBLOCKEDWAITING ON 2: BOARD CANVAS +1BLOCKS — SATISFIEDBLOCKS — UNSATISFIEDRELATES
Nothing here was set to “blocked” by hand. Both ember cards derive it from their incoming edges.

The rule

Blocked isn’t a status. It’s a consequence.

Every other tool asks a person to notice that work is stuck and then remember to say so. NodeKanban reads the edges instead. One definition, evaluated the same way in Postgres and in the browser.

-- public.node_states
is_blocked := exists (
  select 1
    from edges e
    join nodes src on src.id = e.source_id
   where e.target_id = node.id
     and e.kind      = 'blocks'
     and src.status <> 'done'
)

Postgres view · client mirror · one shared test suite

Upstream unfinished

Nobody touched “Deploy staging”. Its incoming blocks edge is unsatisfied, so the board reports it as blocked.

Upstream marked done

One status change upstream. “Deploy staging” clears on its own — no second edit, no stale label.

Built for projects where the order of the work is the hard part.

  • An infinite canvas, not five columns

    Place work where it makes sense — by system, by milestone, by whatever shape the project actually has. Nothing is forced into a lane it does not belong in.

  • Two edge kinds, one meaning each

    A blocks edge says this cannot start until that finishes. A relates edge says these two are worth reading together. Neither is decorative.

  • Blocked is computed, not claimed

    The board reads the incoming edges and works it out. Finish the upstream task and everything downstream clears in the same breath.

  • Nest up to three levels deep

    Open a node to reveal the network inside it. Sub-work stays attached to its parent instead of leaking into a checklist nobody reads.

  • Everyone sees the same graph

    Live cursors, presence and node changes stream to every open board. Row-level security decides who receives them, so a non-member gets nothing.

  • Cycles are rejected at the database

    If A blocks B and B blocks A, there is no valid order to do the work. Postgres refuses the edge before it lands, rather than drawing you an impossible board.

Six states. Five priorities. Nothing to interpret.

Status is a colour and a word. Priority is a gauge, so it never gets confused with status at a glance. The same palette runs from the marketing page to the canvas.

  • BacklogCaptured, not committed to
  • To doReady to be picked up
  • In progressSomeone is on it right now
  • BlockedDerived — never stored
  • DoneClears everything downstream
  • ArchivedOff the board, still in history
  • None
  • Low
  • Medium
  • High
  • Urgent

Map one real project. You’ll see the shape of it in ten minutes.

The free plan is deliberately big enough to hold a genuine dependency graph — three boards, 150 nodes each, realtime included.