A powerful, hierarchical outliner application designed for creating and managing nested lists with ease. Inspired by Dynalist and Workflowy.
Nodepad is a keyboard-first, deeply hierarchical outliner application designed for creating and managing nested lists with ease. It allows developers and productivity enthusiasts to structure complex ideas, logs, and checklists in a simple, responsive outline interface.
[TBD] Some app ux-paths need to be reworked, next steps is to stabilize and deploy on nodepad.lex1001.cc.
- Sentry logging
- NodeLine buttons when editing - ok, cancel, drag&drop tip
- Screenshots aren’t relevant, change here.
- DemoUsers Isolation to prevent spam and abuse
- Test prod usecases
- Keymode luminate and hide/show
Screenshots
Technical Architecture
Nodepad is built with separation of concerns at its core, combining a robust relational schema with high-performance tree traversal.
1. Hierarchical Data Model (ltree)
To support deeply nested trees without suffering from the N+1 query problem or slow recursive CTE queries, Nodepad uses PostgreSQL’s native ltree extension.
- Hierarchy Representation: Each node maintains both a
parent_idforeign key and a materialized path (e.g.,root.child1.child2). - Path Calculation: Handled cleanly in the backend service layer (
backend/app/services/nodes.py) without polluting the raw model classes.
2. Custom Reordering (Fractional Indexing)
Nodes can be dragged, indented, or outdented dynamically.
- Ordering: Handled via fractional indexing (decimal numbers, saved as
Numeric(30, 15)in PostgreSQL to prevent precision loss). - Subtree Stability: During complex subtree movements, the backend uses a Longest Increasing Subsequence (LIS) algorithm (
backend/app/services/lists.py). This minimizes database write operations by identifying the minimum number of nodes that actually need to have their positions updated. - Maintenance: A custom background indexer utility periodically resets positions to integers (multiples of 1000) to keep precision boundaries stable.
3. Frontend & State Boundary
- Client State: Built on React 19 and TypeScript, powered by Zustand for state management and TanStack Router for routing.
- Optimistic UI Updates: The frontend predicts reordering success and updates the client state immediately for an instantaneous, zero-lag feel.
- Design System: Decoupled atomic UI components built with Tailwind CSS 4 and accessible Radix UI primitives.
Keyboard-First Outlining
Nodepad is built for keyboard navigation. Below is the list of shortcuts available on the outline editing screen:
| Shortcut | Action |
|---|---|
| Enter | Save current node and finish editing |
| Shift + Enter | Create a new child node under current |
| Tab | Indent node (move right in hierarchy) |
| Shift + Tab | Outdent node (move left in hierarchy) |
| ↑ / ↓ Arrows | Navigate seamlessly between nodes |
| Backspace | Delete node (when empty) |
| Ctrl + Z | Undo last node edit or delete |
| Escape | Cancel editing |
Development Log & Next Milestones
Upcoming Features & Research Items
- Keymode / Edit Mode: Introducing a physical keyboard mode indicator on the sidebar and configuring navigation via Shift + Arrows to allow quick keyboard actions without triggering input fields.
- Tab Behavior: Improving indent/outdent UX so pressing
Tabin edit mode begins moving the unsaved node without forcing the user to finish text input. - Encryption: Investigating server-side encryption for secure cloud list storage.
- Performance: Setting up mock load-testing scripts for scale validation.
graph TD
User([User Keyboard/UI Input]) -->|Optimistic Update| Store[Zustand Store]
Store -->|API Request| API[FastAPI API Boundary]
API -->|Domain Logic| Service[Service Layer - Path/LIS]
Service -->|Database Operation| DB[(PostgreSQL ltree / Decimal Index)]




