97
README.md
Normal file
97
README.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# task-inventory
|
||||||
|
|
||||||
|
Personal task management. Organise tasks, thoughts, and ideas as a hierarchy. Designed to grow into project management over time.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Hierarchical tasks with unlimited nesting — create subtasks, reparent tasks, or promote subtasks to roots
|
||||||
|
- Tree view (roots only, expandable) and flat view (all tasks)
|
||||||
|
- Filters by status, priority, and tag; free-text search across title and body
|
||||||
|
- Markdown rendering via a local Gitea instance — preview tab in the editor, rendered inline in the task list
|
||||||
|
- Sequential integer IDs
|
||||||
|
- Flat NDJSON key-value store — single file, no database required
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
cp config.yaml.example config.yaml
|
||||||
|
# edit config.yaml — add your Gitea URL and token
|
||||||
|
node server.mjs
|
||||||
|
```
|
||||||
|
|
||||||
|
Server starts on `http://localhost:3025` by default.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
`config.yaml` (not committed):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
gitea:
|
||||||
|
url: https://gitea.example.com
|
||||||
|
token: your_token_here # needs read:misc scope minimum
|
||||||
|
```
|
||||||
|
|
||||||
|
If Gitea is not configured, task titles and bodies are shown as plain text.
|
||||||
|
|
||||||
|
Environment overrides:
|
||||||
|
|
||||||
|
| Variable | Default |
|
||||||
|
|---|---|
|
||||||
|
| `PORT` | `3025` |
|
||||||
|
| `BIND_ADDRESS` | `localhost` |
|
||||||
|
|
||||||
|
## Data model
|
||||||
|
|
||||||
|
Tasks are stored in `data/tasks.ndjson`. Sequential IDs are tracked in `data/ids.ndjson`.
|
||||||
|
|
||||||
|
```
|
||||||
|
Task {
|
||||||
|
id integer sequential, auto-assigned
|
||||||
|
title string markdown
|
||||||
|
body string markdown, optional
|
||||||
|
status open | deferred | done | cancelled
|
||||||
|
priority high | normal | low
|
||||||
|
tags string[]
|
||||||
|
parent_id integer | null null = root task
|
||||||
|
created_at ms timestamp
|
||||||
|
updated_at ms timestamp
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
All responses: `{ ok: true, ...data }` or `{ ok: false, error: string }`.
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/tasks
|
||||||
|
POST /api/tasks body: { title, body?, status?, priority?, tags?, parent_id? }
|
||||||
|
GET /api/tasks/:id
|
||||||
|
PUT /api/tasks/:id body: any subset of task fields
|
||||||
|
DELETE /api/tasks/:id blocked if task has subtasks
|
||||||
|
|
||||||
|
POST /api/render-markdown body: { text, mode? } → { html }
|
||||||
|
```
|
||||||
|
|
||||||
|
## File map
|
||||||
|
|
||||||
|
```
|
||||||
|
server.mjs Entry point — Express 5, all routes
|
||||||
|
lib/
|
||||||
|
config.mjs Loads config.yaml (ENOENT-safe)
|
||||||
|
ids.mjs Sequential integer ID generator per namespace
|
||||||
|
kv-store.mjs Flat NDJSON key-value store (auto-load, debounced flush)
|
||||||
|
storage.mjs Task CRUD wrappers
|
||||||
|
public/
|
||||||
|
app.mjs SPA — state, rendering, dialogs
|
||||||
|
index.html Shell
|
||||||
|
style.css All styles
|
||||||
|
templates.html HTML templates (injected at init)
|
||||||
|
gitea-markup.css Vendored Gitea markup + chroma CSS for markdown rendering
|
||||||
|
lib/
|
||||||
|
api.mjs fetch wrappers for all API endpoints
|
||||||
|
dom.mjs qs(), clone(), set_text(), show(), hide()
|
||||||
|
data/ Created at runtime, not committed
|
||||||
|
tasks.ndjson All task records
|
||||||
|
ids.ndjson Sequence counters
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user