8410b6315b463928f4c617d2dd585b2182af941f
Deploy plumbing so Petal can run on the public VPS behind the Traefik already on that box, with vLLM reached over headscale. - Dockerfile: node build -> go build -> alpine runtime. CGO stays off (modernc SQLite is pure Go), so the runtime layer exists only for ffmpeg (read-aloud transcodes Piper's WAV) and tzdata (the companion's bedtime nag and night mode read the local clock). Runs as uid 10001 with /data as the single writable mount. - docker-compose.yml: Traefik labels following this host's convention (external `traefik` network, `web-secure` entrypoint, `default` cert resolver). Petal publishes no host port. ./data is a bind mount, not a named volume, so the nightly backup and a restore are reachable from the host. - Piper runs as two sibling containers rather than host systemd units. The plan assumed Piper was already installed on the VPS; it is not, the host has no lingering user session to keep user units alive, and containers keep the TTS ports on an internal network unreachable from anywhere but Petal. One image, voice chosen per service, model cached in a shared volume -- so the pt-PT voice is a new service, not a new image. - db.Backup + a `-backup` flag: VACUUM INTO, not a file copy. Petal runs in WAL mode, so the newest committed pages may live in petal.db-wal; copying the three files separately can capture a torn mid-checkpoint state. VACUUM INTO reads one coherent snapshot without taking a write lock, and emits a single file with no -wal/-shm companions. Refuses an existing destination so a failed run can't destroy the last good backup. - deploy/backup-petal.sh: nightly snapshot, compress, push to millenia over headscale with a post-transfer size check, prune both sides. - deploy/petal.env.example: LLM_TIMEOUT raised 30s -> 90s for the WAN+VPN round trip, since the voice and collocation passes send a whole document and the timeout is a hard deadline on Complete.
🌸 Petal
A self-hosted, privacy-first writing editor with warm bubbly design, auto-save, and
local-LLM grammar/ESL suggestions. See petal-spec.md for the full
design spec and BUILD_PLAN.md for build progress.
Stack
Go + chi backend · SQLite (modernc, pure Go) · React + Vite + Tiptap + Tailwind v4 frontend ·
local vLLM/Ollama for AI suggestions. Single-binary deployment (frontend embedded via go:embed).
Local development
Two processes during development:
# 1. Backend (serves /api on :8080)
go run ./cmd/server
# 2. Frontend dev server (HMR on :5173, proxies /api → :8080)
cd web && npm install && npm run dev
Open http://localhost:5173 while developing.
Production build (single binary)
cd web && npm run build # emits web/dist (embedded by the Go binary)
cd .. && go build -o petal ./cmd/server
./petal # serves UI + API on :8080
Configuration is via environment variables — copy .env.example to .env.
Status
Early build, multi-session. Auth (Authentik), Copyleaks plagiarism, and Docker/Traefik
deployment are deferred — see BUILD_PLAN.md.
Description
Petal is a self-hosted, privacy-first writing editor for an ESL user. It replaces Grammarly with a warm, bubbly web app that combines Tiptap rich text editing, auto-save cloud storage, and periodic AI-powered grammar/ESL suggestions backed by a local vLLM inference endpoint.
27 MiB
Languages
TypeScript
49.2%
Go
44.1%
Python
3.8%
CSS
1.7%
Shell
0.9%
Other
0.2%