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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
A simple webapp for the family, regrouping tailor made tools (groceries,
chores).
## 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
## Notable choices
- **@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.
## Product
### Groceries
Two core concepts: the **catalog** (every item you've ever added) and the
**list** (unchecked items — what to buy next). Adding an item creates it (or
unchecks an existing one). Checking an item off simply marks it done; it
remains visible in the catalog with a strikethrough. Unchecked items persist
on the list for the next shopping trip — there is only one persistent list.
**Three modes of use:**
1. **Quick add** — during the week, you run out of milk or need an ingredient.
Open the app, type the name, tap to add. An autocomplete dropdown surfaces
existing catalog items as you type, so "citron" does not become "citrons".
Tapping a suggestion re-adds the existing item; typing a new name creates it.
2. **Planning** — before shopping, sit down with your partner and browse the
catalog. Tap unchecked items to add them back to the list. Multi-select
and bulk-update category for several items at once. The page does not
reload, so going through 20–30 items is not frustrating. Stale one-off
items can be deleted from the catalog.
3. **Shopping** — items are grouped by category (matching store aisles).
Check off as you grab them. Multiple devices can use the same list,
but live sync is not implemented yet — refresh to see your partner's
changes.
**Product references** — some items like "coffee" or "pasta" aren't generic.
For these you can record one or more reference brands, each with a name,
price per unit (€/kg or €/L), and a quality score (0–100). In the store, if
you're unsure which brand you usually buy or you spot an alternative, you
can compare against your references right from the item. If a new brand
wins, you can add it or switch the reference.
**Categories** — items are manually assigned to categories. Categories
correspond to physical store aisles for an efficient shopping walk. Drag
categories to reorder them so the list matches your actual store layout.
**PWA** — installed as a standalone app via `@vite-pwa/sveltekit`. Service
worker precaches assets; works offline after first visit.
### Projects & routines
**Projects** ("Household", "Personal growth", …) group recurring **routines**
— chores are just routines in the household project. Each routine has an
interval like `1d`, `2w`, `3m` or `1y`. The home page lists projects with a
health score (0–100); each project page shows its routines sorted most-urgent
first (À jour / À faire / En retard / Très en retard) with one-tap "Fait"
completion. Editing a routine creates a new immutable version, and every
completion records the exact version it was made against, so the past is
never rewritten. Each routine has its own page (the name links from the
project) with an editable description, a chart of its health score over time,
and its completion log. Archiving a routine stamps the date it was archived
and removes it from the active list: it stays reachable in a collapsible
"Archivées" section on its project page (with a fuzzy search) and opens as a
read-only page whose health chart runs from creation to the archive date.
## TODO
### Features
- [ ] Live updates from server
- [ ] Auto-categorize new items (LLM-assisted)
- [ ] https://automerge.org/docs/tutorial/
- [ ] Style like feed.kagamino.dev
- [ ] Shared > Modal actions
- [x] Routines > Archive on date - Routine that was tracked between d1 and d2
- [ ] Routine > Frequency = 5d/1w
## 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.
Authenticate both Docker clients once:
```bash
docker login container.registry.kagamino.dev
ssh ubuntu@feed.kagamino.dev "sudo docker login container.registry.kagamino.dev"
```
Build, push, and deploy the latest image with:
```bash
mise run deploy
```
The deploy script starts the registry, builds and pushes the image, then pulls
and restarts only the `home` service on the VPS.
|