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