A lightweight Kanban board single-page application built with vanilla JavaScript
(ES modules), HTML and CSS. No build step, no framework, and zero runtime
dependencies — just open index.html in a modern browser and start organizing.
- Boards, columns and cards — create, rename and delete each of them.
- Drag and drop — move cards between columns and reorder within a column using the native HTML5 drag-and-drop API.
- Labels and priority — tag cards with free-form labels and a low / medium / high priority badge.
- Search & filter — instantly filter cards by title, description or label.
- Undo / redo — every mutation is reversible (
Ctrl+Z/Ctrl+Y). - Persistence — the entire state is saved to
localStorageautomatically. - Import / export — save any board to a JSON file and load it back later.
- Light & dark themes — follows your system preference via
prefers-color-scheme. - Keyboard accessible — focusable cards, shortcut keys, and ARIA roles.
TaskFlow [ search / ] New Delete Undo Redo Export Import
┌ To Do ───────┐ ┌ In Progress ─┐ ┌ Done ────────┐
│ Ship release │ │ Write docs │ │ Set up CI │
│ [high] │ │ [medium] │ │ [low] │
│ #urgent │ │ │ │ │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ + Add card │ │ + Add card │ │ + Add card │
└──────────────┘ └──────────────┘ └──────────────┘ + Add column
No installation or build is required.
# Option 1 — just open the file
open index.html # macOS
xdg-open index.html # Linux
# Option 2 — serve it (recommended, so ES modules load over http)
python3 -m http.server 8000
# then visit http://localhost:8000ES modules are subject to the browser's CORS rules, so serving over a local HTTP server is the most reliable way to run the app.
| Shortcut | Action |
|---|---|
/ |
Focus the search box |
Ctrl/Cmd + Z |
Undo |
Ctrl/Cmd + Y |
Redo (also Ctrl+Shift+Z) |
Enter / E |
Edit the focused card |
Delete |
Delete the focused card |
The application is split into small, single-responsibility ES modules under
js/:
| Module | Responsibility |
|---|---|
app.js |
Entry point — wires the store, toolbar, shortcuts and render loop. |
state.js |
Pure in-memory state model, mutations, selectors, undo/redo, filter. |
storage.js |
localStorage load/save/clear. |
board.js |
Renders boards, columns and cards to the DOM and binds interactions. |
dragdrop.js |
HTML5 drag-and-drop wiring and drop-index calculation. |
The design follows a simple unidirectional data flow: UI events call methods
on the Store, the store mutates state (snapshotting for undo) and notifies
subscribers, and app.js re-renders the board from the new state. Because
state.js never touches the DOM, its logic is fully unit-testable under Node.
The state module ships with a unit-test suite using Node's built-in test runner
(node:test) and assert — no dependencies to install.
node tests/state.test.mjs
# or, to use the test runner's reporter:
node --test
# or via the npm script:
npm testThe included
package.jsononly sets"type": "module"(so Node reads the.jsfiles as ES modules) and a test script — there are no installable dependencies.
You can also syntax-check every module (DOM modules can be checked but not executed under Node):
node --check js/state.js
node --check js/storage.js
node --check js/dragdrop.js
node --check js/board.js
node --check js/app.jstaskflow-kanban/
├── index.html
├── css/
│ └── styles.css
├── js/
│ ├── app.js
│ ├── board.js
│ ├── dragdrop.js
│ ├── state.js
│ └── storage.js
├── tests/
│ └── state.test.mjs
├── package.json
├── LICENSE
└── README.md
Released under the MIT License.