Replace plain textarea with shared tiptap editor and sanitized html rendering. Adds interactive checklists on read surfaces and mobile overflow fixes.
famapp
Self-hosted family coordination web app. Shared calendar, lists, notes, and garden tracker — installable as a PWA, protected by OIDC single sign-on.
Features
Modules
| Module | What it does |
|---|---|
| Calendar | Month / week / day views, drag-to-create, household and private calendars, event reminders |
| Lists | Shopping and task lists with real-time sync, reorder, keyboard-first item entry |
| Notes | Markdown notes with pinning, safe preview, and optional remind-at scheduling |
| Garden | Plant and container tracking, care schedules, care logs, species lookup via OpenPlantBook |
Platform capabilities
| Capability | Detail |
|---|---|
| Dashboard | Per-user named dashboards, drag-resize widget grid, configurable widget instances |
| Quick-add | Cmd/Ctrl+K command palette and + FAB — every module registers its own actions |
| Share links | Any entity produces a temporary public link (/s/<token>), scoped read or read-write |
| Activity log | Household-scoped feed of every create / update / delete across all modules |
| Reminders | Generic reminder engine ticked every 30 s; notes and calendar events both use it |
| Push notifications | VAPID web push + in-app inbox + optional ntfy fallback |
| Themes | Two palettes (default / warm) × light / dark / system, zero flash on load |
| PWA / offline | Installable on iOS and Android, offline shell, stale-while-revalidate caching |
| Structured logging | JSON logs via pino in production, pretty-printed in dev, LOG_LEVEL configurable |
| Nightly backups | pg_dump cron for both databases, 14-day daily / 8-week weekly / 6-month monthly retention |
Requirements
- Docker with the Compose plugin (v2)
- Caddy (or any reverse proxy that handles HTTPS)
- Authentik — famapp delegates all authentication to an Authentik OIDC provider; see the bootstrap guide
- A domain with DNS pointing to your host
Quick start
Full details are in deploy/README.md. The short version:
# 1. Clone and enter the repo
git clone https://github.com/ginnoir/famapp.git /srv/famapp
cd /srv/famapp
# 2. Create your environment file
cp .env.production.example deploy/.env
# Edit deploy/.env — see Configuration below for required values
# 3. Configure your reverse proxy
# Add deploy/Caddyfile.snippet to your Caddyfile, then reload Caddy
# 4. Bootstrap Authentik and record the OIDC client id/secret in deploy/.env
# See deploy/authentik/README.md
# 5. Start the stack
docker compose -f deploy/compose.example.yaml up -d
The container runs database migrations automatically on start. The first user to sign in becomes the household owner; a second sign-in joins the same household as a member.
Pin FAMAPP_IMAGE in deploy/.env after the first deploy:
FAMAPP_IMAGE=registry.ginnoir.com/ginnoir/famapp:v0.4.7
Development setup
Requires Node ≥ 22 and pnpm 10.
git clone https://github.com/ginnoir/famapp.git
cd famapp
pnpm install
# Copy the example env and fill in dev values (set ENABLE_DEV_LOGIN=true)
cp .env.example .env
# Start the local database, run migrations, seed, and launch the dev server
pnpm dev:local
Then open http://localhost:3000/login and click Dev login.
Additional dev commands:
| Command | Purpose |
|---|---|
pnpm dev:reset |
Drop and reseed the local database |
pnpm db:studio |
Open Drizzle Studio against the local database |
pnpm db:generate |
Generate a new migration after schema changes |
pnpm typecheck |
Run tsc --noEmit |
pnpm lint |
ESLint |
pnpm test:e2e |
Playwright E2E suite |
pnpm vapid:generate |
Print VAPID key env vars to stdout |
pnpm gen:icons |
Regenerate PWA icons from public/icon.svg |
See docs/dev-login.md for push notification and E2E testing setup.
Configuration
Copy .env.production.example to deploy/.env and fill in values. Key variables:
| Variable | Required | How to generate |
|---|---|---|
AUTH_URL |
Yes | Public HTTPS URL for the app (e.g. https://fam.yourdomain.com) |
AUTH_SECRET |
Yes | openssl rand -base64 32 |
AUTH_OIDC_ISSUER |
Yes | From Authentik — https://auth.yourdomain.com/application/o/famapp/ |
AUTH_OIDC_CLIENT_ID |
Yes | From Authentik application |
AUTH_OIDC_CLIENT_SECRET |
Yes | From Authentik application |
FAMAPP_DB_PASSWORD |
Yes | Strong random password |
AUTHENTIK_DB_PASSWORD |
Yes | Strong random password |
AUTHENTIK_SECRET_KEY |
Yes | openssl rand -base64 60 |
VAPID_PUBLIC_KEY |
Push | pnpm vapid:generate |
VAPID_PRIVATE_KEY |
Push | pnpm vapid:generate |
VAPID_SUBJECT |
Push | mailto:your-email@example.com |
NTFY_URL / NTFY_TOPIC |
Optional | ntfy push fallback |
famapp_OPENPLANTBOOK_CLIENT_ID |
Optional | OpenPlantBook API — plant species lookup |
LOG_LEVEL |
Optional | error / warn / info / debug (default: info) |
Architecture
famapp uses an extensibility-first module system: every feature lives under src/modules/<name>/ and declares its tables, routes, dashboard widgets, quick-add actions, and share/reminder/search behaviors via a manifest. Core services (sharing, push, reminders, activity log, search) operate generically — adding a new module does not require touching core code.
See CLAUDE.md for the full architecture brief and docs/decisions/ for ADRs.
Deployment
| Resource | Link |
|---|---|
| Full host setup | deploy/README.md |
| Authentik bootstrap | deploy/authentik/README.md |
| Backup / restore | deploy/backups/README.md |
| Pre-deploy checklist | docs/tasks/09-pre-deploy-checklist.md |
| Changelog | CHANGELOG.md |
Cutting a release: tag vX.Y.Z on main and push — Gitea Actions builds and pushes registry.ginnoir.com/ginnoir/famapp:vX.Y.Z automatically.