Preface
Nested Set Org Chart is a full-stack explorer for company hierarchies. Instead of adjacency lists or recursive CTEs for every query, the tree lives as a Nested Set in PostgreSQL: each node stores level, iLeft, and iRight, so an entire subtree is one range filter away.
The stack is a Django REST API (JWT, Swagger) plus a React/Vite SPA with a folder tree, force-directed graph, and EN/IT labels for org units — departments like Marketing, Sales, and Helpdesk under a generic company root.
The problem
Org charts are trees. The usual options each have a cost:
- Adjacency list (
parent_id) — simple writes, painful deep reads (recursive queries) - Materialized path — string prefixes, awkward rebalancing
- Nested Set — denser writes when inserting, but O(1)-style subtree reads with two integers
This project leans into Nested Set end to end: seed a sample company tree, expose range queries over the API, then rebuild parent/child edges in the UI for graph and tree views — without a parent_id column.
Nested Set model
Each node is a closed interval on a depth-first traversal:
| Field | Meaning |
|---|---|
| level | Depth in the tree (root = 0) |
| iLeft / iRight | Contiguous visit bounds |
Invariants used everywhere:
- Descendants of N →
iLeft > N.iLeft AND iRight < N.iRight - Parent of N → unique node with
level == N.level - 1whose bounds enclose N - Direct children → same range filter plus
level == N.level + 1
Localized names live in a related table (language, nodeName) → node, so the same tree serves English and Italian labels.
Product preview
Tree browser on one side, force-directed org graph on the other — both driven by the same Nested Set payload.

Folder structure
Monorepo-style layout: Django API at the root, React SPA in org-view-flow/, Docker for Postgres + services.
Architecture
Backend
- Django 5 + DRF list/detail/search endpoints under
/api/nodes/ - JWT signup/login; docs at
/api/docs/ - Nested Set seed data for a sample company hierarchy
- Custom 0-based pagination (
page_num/page_size)
Frontend
- React 18 + Vite + Tailwind + shadcn/ui
- Folder tree + custom canvas force layout (concentric levels)
- Client-side parent recovery from
(level, iLeft, iRight) - EN/IT via react-i18next
Under the hood
Three of the geekier bits — range queries, parent reconstruction, and a Nested Set–aware force layout. Code blocks use the same titled CodeBlock UI as the rest of the site.
Subtree count & search with two inequalities
Classic Nested Set: no recursion. Descendants of a node are everything strictly inside its [iLeft, iRight] interval; keyword search reuses the same bounds.
Rebuild parents without a parent_id column
The API returns flat Nested Set rows. The SPA recovers the tree graph with the enclosure rule: parent is the unique node one level up whose interval contains the child.
Force layout from Nested Set edges
Nodes seed on concentric rings (radius ≈ level). Links come from the reconstructed parentId, then a light spring simulation keeps the org chart readable.
Features
Subtree reads with iLeft/iRight range filters — no recursive CTEs on every request.
Concentric levels and spring edges inferred from Nested Set parent recovery.
Folder-style browser and canvas graph share the same API payload.
Search names inside a parent interval, with EN/IT language selection.
Signup/login with SimpleJWT and OpenAPI docs via drf-spectacular.
Compose stack for API, DB, and frontend preview — one Makefile to bring it up.
Tech stack
Open source & links
Source, Makefile targets (make up, make test, make frontend), and Swagger live in the repo.
If you care about tree algebra in SQL as much as pretty org charts, this is the project where Nested Set stops being a textbook footnote and becomes the API contract.


