Files
glance-todo/README.md
2026-03-09 08:19:51 +01:00

3.6 KiB

Todo-Glance

A server-backed CRUD todo widget for Glance. Stores tasks in SQLite instead of browser localStorage, so your todos persist across devices and sessions.

Integrates as a Glance Extension widget with native theming via Glance CSS variables.

Stack

  • Go — single main.go, no frameworks
  • SQLite via modernc.org/sqlite — pure Go, no CGO required
  • Vanilla JS — embedded in the Go binary, no build step

Quick Start

docker compose up --build
  • Glance dashboard: http://localhost:8080
  • Todo API: http://localhost:8081

The included glance.yml has the widget pre-configured. Edit it to add your other Glance widgets.

Standalone

go build -o todo-glance .
./todo-glance

Then add the widget to your existing Glance config:

- type: extension
  url: http://todo-glance:8081/
  allow-potentially-dangerous-html: true
  cache: 1s

Replace todo-glance with the hostname or IP where the server is reachable from Glance.

Environment Variables

Variable Default Description
TODO_PORT 8081 Server listen port
TODO_DB_PATH ./todos.db SQLite database file path
TODO_EXTERNAL_URL (from Host header) URL browsers use to reach the API. Required when the browser-facing URL differs from the internal one (e.g. behind a reverse proxy).

API

Method Path Description
GET / Extension widget HTML (returns Widget-Title and Widget-Content-Type headers)
GET /api/todos List all todos
POST /api/todos Create a todo — {"text": "...", "priority": 0-3, "tags": [...]}
PUT /api/todos/{id} Update a todo — {"text": "...", "done": true, "priority": 0-3, "tags": [...]}
DELETE /api/todos/{id} Delete a todo — returns 204

Priority levels: 0 = none, 1 = low, 2 = medium, 3 = high. Todos are sorted by: incomplete first, then highest priority, then newest.

Examples

# Create with priority and tags
curl -X POST -H 'Content-Type: application/json' \
  -d '{"text":"Fix login bug","priority":3,"tags":["work","urgent"]}' \
  http://localhost:8081/api/todos

# Create simple
curl -X POST -H 'Content-Type: application/json' \
  -d '{"text":"Buy milk"}' http://localhost:8081/api/todos

# List (sorted by priority)
curl http://localhost:8081/api/todos

# Mark done
curl -X PUT -H 'Content-Type: application/json' \
  -d '{"done":true}' http://localhost:8081/api/todos/1

# Change priority
curl -X PUT -H 'Content-Type: application/json' \
  -d '{"priority":2}' http://localhost:8081/api/todos/1

# Update tags
curl -X PUT -H 'Content-Type: application/json' \
  -d '{"tags":["work","reviewed"]}' http://localhost:8081/api/todos/1

# Delete
curl -X DELETE http://localhost:8081/api/todos/1

Architecture

Browser (Glance page)
  │
  │  GET /          Glance fetches widget HTML from todo-glance
  │  ─────────────► (internal Docker network)
  │
  │  API calls      JS in the widget calls /api/* endpoints
  │  ─────────────► (browser hits TODO_EXTERNAL_URL / localhost:8081)
  │
  ▼
todo-glance ──► SQLite file (/data/todos.db in Docker)

The HTML is served to Glance over the internal network. Once rendered in the browser, the embedded JS makes API calls directly to the todo-glance server using the external URL. CORS headers are set on all /api/ endpoints to allow this cross-origin access.