# ThoughtSync Self-hosted personal thought-capture web app in the **FabledSword** family — a Google-Keep-style **masonry post-it board** for capturing disparate thoughts in under a second, designed to grow into a lightweight second brain (labels, search, `[[wiki-links]]`, graph). - **Stack:** Quart (async Python) + Vue 3 + PostgreSQL, Docker, Fabled-Git CI. - **Auth:** native email + password (signed-cookie sessions). Multi-user with the family owner + direct-share + group-share ACL. - **Web-first.** An Android companion is a later, conditional milestone. ## Layout ``` src/thoughtsync/ Quart app (app factory, auth, models, ACL, config, db) alembic/ async migrations (schema built via `alembic upgrade head`) tests/ DB-free unit tests (pytest) frontend/ Vue 3 + Vite + TypeScript + Tailwind SPA Dockerfile 2-stage build (Vue -> python:3.12-slim runtime) docker-compose.yml local app + Postgres stack ``` ## Development Backend (needs a Postgres reachable at `THOUGHTSYNC_DATABASE_URL`): ```sh pip install -e ".[dev]" alembic upgrade head hypercorn 'thoughtsync.app:create_app()' --bind 0.0.0.0:5000 ``` Frontend (proxies `/api` to `:5000`): ```sh cd frontend npm install npm run dev # http://localhost:5173 ``` Or run it in Docker. **Hot-reload dev stack** (edit code, changes reload live) — Postgres + backend + Vite dev server, app at http://localhost:5173: ```sh docker compose -f docker-compose.dev.yml up ``` Or the **full production image** (SPA baked in) at http://localhost:5000: ```sh docker compose up --build ``` ## Deploy (self-host) A complete two-container stack (app + Postgres) you can copy and run. Save it as `docker-compose.yml`, change the two `CHANGE_ME` passwords (they must match), then `docker compose up -d`: ```yaml services: db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: thoughtsync POSTGRES_PASSWORD: CHANGE_ME # change this POSTGRES_DB: thoughtsync volumes: - thoughtsync-db:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U thoughtsync"] interval: 5s timeout: 5s retries: 10 app: image: git.fabledsword.com/bvandeusen/thoughtsync:latest # :dev for the current dev build restart: unless-stopped depends_on: db: condition: service_healthy environment: THOUGHTSYNC_DATABASE_URL: postgresql+asyncpg://thoughtsync:CHANGE_ME@db:5432/thoughtsync volumes: - thoughtsync-data:/var/thoughtsync # uploaded images; omit if you don't use attachments ports: - "5000:5000" volumes: thoughtsync-db: thoughtsync-data: ``` Then open `http://:5000` and register — **the first account becomes the admin**. - **Only `THOUGHTSYNC_DATABASE_URL` is required.** `THOUGHTSYNC_SECRET_KEY` is optional; if unset, a signing key is generated and persisted in the database (sessions survive restarts). - Uploaded images live under the `thoughtsync-data` volume at `/var/thoughtsync`. - The app waits for the database and runs migrations (`alembic upgrade head`) automatically on start. - **Image tags:** `:latest` (stable, built from `main`) · `:dev` (latest `dev` build) · `:` on `main` only (immutable, the rollback unit). There are no version-shaped tags: nothing pins one, and the build reports its own version at `/api/config` and `/health`. - **Putting it on the public internet:** there are four things to do first — close registration, terminate TLS and forward `X-Forwarded-Proto`, stop publishing the app port, and back up the attachment volume as well as the database. See [docs/public-hosting.md](docs/public-hosting.md), which also lists what the app hardens on its own and what it deliberately doesn't. - **Install as an app (PWA):** ThoughtSync is installable ("Add to Home Screen" / the browser's install button) for an app-like window. Browsers only offer install over a **secure context**, so put the app behind a reverse proxy terminating **HTTPS** (or reach it via `localhost`) — plain `http://:5000` won't show the install prompt. ## Milestones - **M0 — Foundation & Identity** ✅: Quart+Vue+Postgres skeleton, native auth, sharing-ACL spine, Fabled-Git CI. - **M1 — Capture Core** ✅: note model + masonry board (quick-add, colors, pin, edit-in-place, archive, trash+restore). - **M1.5 — Roles & DB-backed Settings** ✅: first user is admin, admin Settings UI, `DATABASE_URL` is the only required env. - M2 — Organize: labels/tags, search, checklists, attachments. - M3 — Second-brain seeds: `[[wiki-links]]`, backlinks, graph view, reminders. - M4 — Launch hardening: responsive/PWA, settings UI, polish. Work happens on `dev`; `main` is protected (PR-only).