- Python 53.4%
- HTML 38.8%
- JavaScript 7.4%
- Dockerfile 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Push Docker Image / push (push) Successful in -40s
SESSION_COOKIE_AGE is applied at login time and only re-applied when the session is saved, so an active user was still logged out 14 days after logging in. Saving the session on every request makes the cookie age a sliding window that refreshes on use. |
||
| .forgejo/workflows | ||
| .impeccable | ||
| core | ||
| docker | ||
| hearth | ||
| locale/pl/LC_MESSAGES | ||
| static | ||
| templates | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .python-version | ||
| bun.lock | ||
| CLAUDE.md | ||
| DESIGN.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| manage.py | ||
| package.json | ||
| PRODUCT.md | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
🔥 Hearth
A real-time household management app: a shared shopping list, a weekly meal planner, and a recipe cookbook — with live sync between household members over WebSockets. Built from the Hearth design prototype.
Charcoal · cream · flame-orange, Archivo type, grain-textured surfaces.
Stack
- Django 6 (full-stack: templates + forms), managed with uv
- HTMX for reactivity — mutations swap server-rendered fragments
- Django Channels (
channels+channels-redis+daphne) for WebSocket sync - Tailwind CSS 4 (CSS-first
@theme), built with the Tailwind CLI via Bun - SQLite database, Redis/Valkey channel layer, S3-compatible (RustFS) media storage
- Docker for packaging; Daphne (ASGI) + WhiteNoise for static
How real-time sync works
Every mutation is an HTMX POST that (1) returns the affected region as an
hx-swap-oob fragment to update the actor instantly, and (2) broadcasts the same
update to the household's Channels group so the partner's browser applies it too.
HTML (not JSON) travels over the socket, so HTMX's ws extension swaps it directly.
- Shopping: the whole board is re-rendered and OOB-swapped. Search + category filtering is client-side over the full board, so a partner's in-progress search is never clobbered by an incoming sync.
- Planner: a tiny "ping" element is OOB-swapped in and self-fires an HTMX GET, so each client reloads its own week — never yanked to the actor's week.
Local development
Requirements: Python 3.13 (via uv), Bun, a Redis/Valkey and an S3-compatible store
(docker compose up valkey rustfs), configured via .env (see .env.example).
uv sync # Python deps
bun install # front-end toolchain
bun run build # build Tailwind CSS
uv run python manage.py migrate
uv run python manage.py seed_hearth
uv run python manage.py runserver
Open http://127.0.0.1:8000 and sign in as you / ada (password hearth123).
runserver serves ASGI (WebSockets included) because daphne is first in
INSTALLED_APPS.
While iterating on styles, run the CSS watcher in another terminal:
bun run watch
Production (Docker)
cp .env.example .env # set DJANGO_SECRET_KEY, DJANGO_ALLOWED_HOSTS, AWS_*…
docker compose up --build
Compose runs three services — web (Daphne on :8000), valkey (channel layer),
rustfs (S3-compatible media) — and the entrypoint migrates on start. Static files
are collected at image build time; seed with manage.py seed_hearth if needed.
App at http://localhost:8000.
Project layout
hearth/ Django project (settings, asgi with Channels routing, urls)
core/
models.py Household, Membership, ShoppingItem, Recipe*, MealEntry
views.py HTMX views: mutations return OOB fragments + broadcast
services.py household resolution, week math, board/planner view-models
websockets/ HouseholdConsumer (HTML over ws), broadcast() → group_send, routing
constants.py 12 categories, 4 meal rows, item catalog
management/ seed_hearth command (recipes + demo data)
templates/ base shell, per-view pages, partials/ (fragments + modals)
static/css/ app.tailwind (Tailwind input) → app.css (build output)
static/ vendored HTMX, fonts, images (served by WhiteNoise)