1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
A simple webapp for the family, regrouping tailor made tools (groceries,
chores).
## Features
- **Refocus refresh** — returning to the app after 10 seconds away refetches
the current page's data; edit pages are left untouched.
- **Groceries** — two concepts: the **catalog** (every item ever added) and
the **list** (unchecked items — what to buy next). Quick add with
autocomplete, bulk category updates while planning, aisle-grouped view
while shopping. Shared across devices, but live sync is not implemented —
refresh to see your partner's changes.
- **Product references** — for items like "coffee" or "pasta": one or more
reference brands with a price per unit (€/kg or €/L) and a quality score
(0–100), comparable from the item while in the store.
- **Categories** — items assigned to store aisles, drag to reorder the list
to match the physical layout.
- **Projects & routines** — projects ("Household", "Personal growth", …)
group recurring routines with a frequency: an interval like `2w`, or a
quota like `5/2w` (5 completions per 2-week window anchored on creation —
a closed window left unmet makes the routine En retard). Project pages
sort routines most-urgent first (À jour / À faire / En retard / Très en
retard) with one-tap "Fait", live search, and a health score (0–100) per
project and per routine, charted over time. Routines show the age of the
last completion ("fait hier", "fait il y a 5 jours") or the lateness ("3
jours de retard"); completions can be backdated to the day they actually
happened. Editing creates immutable versions and each completion records
its version — the past is never rewritten. Archiving keeps a read-only
page whose chart runs to the archive date.
- **PWA** — standalone install via `@vite-pwa/sveltekit`; works offline
after the first visit.
## Architecture
- SvelteKit (Svelte 5 runes) + adapter-node, no separate front/back. Mobile-first CSS
- SQLite via **@libsql/client** + Drizzle ORM
- Plain CSS (no framework), Vitest for tests, Prettier + ESLint flat config
- `npm run dcd` scans source code for duplicate blocks (skips generated JSON)
- Multi-stage Docker image
- **@libsql/client over better-sqlite3** — Node 26 removed V8 API surface
(`GetPrototype`, `This` on PropertyCallbackInfo) that better-sqlite3's
native addon depends on; @libsql/client is pure JS and works out of the box.
- **Plain CSS over Tailwind** — smaller dependency footprint, no build step
for styles.
## Usage
Seed routines from the paper sheet (one-off, idempotent):
```bash
docker compose exec home node --experimental-strip-types scripts/seed-sheet1-routines.ts
```
Pull a copy of the remote database into `data.db` for local testing:
```bash
mise run db:backup
```
## Release / Deploy
Images are published to the private registry at
`container.registry.kagamino.dev`. The app password is supplied at runtime as
`AUTH_PASSWORD` in the VPS Docker Compose deployment.
```bash
# authenticate both Docker clients (once)
docker login container.registry.kagamino.dev
ssh ubuntu@feed.kagamino.dev "sudo docker login container.registry.kagamino.dev"
# start the registry, build and push the image, restart `home` on the VPS
mise run deploy
```
## TODO
- Live updates from server
- Auto-categorize new items (LLM-assisted)
- https://automerge.org/docs/tutorial/
- Style like feed.kagamino.dev?
- Shared > Modal actions
|