Init work
This commit is contained in:
110
README.md
110
README.md
@@ -0,0 +1,110 @@
|
||||
# Todo-Glance
|
||||
|
||||
A server-backed CRUD todo widget for [Glance](https://github.com/glanceapp/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](https://pkg.go.dev/modernc.org/sqlite) — pure Go, no CGO required
|
||||
- **Vanilla JS** — embedded in the Go binary, no build step
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Docker Compose (recommended)
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
go build -o todo-glance .
|
||||
./todo-glance
|
||||
```
|
||||
|
||||
Then add the widget to your existing Glance config:
|
||||
|
||||
```yaml
|
||||
- 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
|
||||
|
||||
```bash
|
||||
# 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.
|
||||
|
||||
Reference in New Issue
Block a user