feat: auth by default, theme toggle, CoderPad startup, review fixes
- Require a session on every route; public routes opt out with @allow_anonymous - Split password hashing and pepper loading into passwords.py - Add a system/light/dark theme toggle backed by light-dark() colors - Ignore stale 401s from an earlier session, PATCH only changed book fields, and block overlapping journal-entry saves - Add bin/start and CoderPad Vite server settings for the pad's start/restart - Rewrite README as a mise onboarding guide; expand .gitignore - Include review-round fixes and tests
This commit is contained in:
@@ -1,58 +1,71 @@
|
||||
# My Library: Personal Book Collection Tracker
|
||||
# My Library
|
||||
|
||||
Flask + React + PostgreSQL. Users catalog their books, track reading progress, keep a reading journal per
|
||||
book, and search/filter their library. Each user sees only their own data.
|
||||
A personal book tracker. You sign up, add the books you own, track how far you are in each one, and keep a
|
||||
reading journal for every book. You can search your library by title or author and filter it by genre. Each
|
||||
user sees only their own books.
|
||||
|
||||
## Run (CoderPad)
|
||||
It is a Flask (Python) API with a React (TypeScript) frontend, backed by PostgreSQL.
|
||||
|
||||
The pad starts Flask (`backend/app.py`, port 5000) and Vite automatically. The schema is created on startup.
|
||||
Optionally set `PASSWORD_PEPPER` (≥ 32 chars). Without it, a development pepper is generated into
|
||||
`backend/.pepper` and a warning is logged.
|
||||
## What you need
|
||||
|
||||
## Run (local)
|
||||
- [mise](https://mise.jdx.dev) – installs the right versions of Python, Node and the other tools for you
|
||||
- [Docker](https://www.docker.com) – runs the PostgreSQL database
|
||||
|
||||
## First-time setup
|
||||
|
||||
```bash
|
||||
mise trust && mise install # Python 3.14, Node 24
|
||||
docker compose up -d db # postgres:16 on 127.0.0.1:5432
|
||||
until docker compose exec -T db pg_isready -U postgres; do sleep 1; done
|
||||
mise exec -- python -m venv .venv && .venv/bin/pip install -r backend/requirements.txt
|
||||
mise exec -- npm install
|
||||
.venv/bin/python backend/app.py # API on :5000
|
||||
mise exec -- npm run dev # UI; /api is proxied to Flask
|
||||
mise trust # allow mise to use this project's mise.toml
|
||||
mise install # install Python, Node, uv, ruff and biome
|
||||
mise run setup # create the Python virtual environment and install all dependencies
|
||||
```
|
||||
|
||||
## Test
|
||||
## Run the app
|
||||
|
||||
```bash
|
||||
.venv/bin/python -W error -m unittest discover -s backend/tests -t backend -v # real Postgres (books_test); run from repo root
|
||||
mise exec -- npm test && mise exec -- npm run typecheck
|
||||
mise run dev
|
||||
```
|
||||
|
||||
## Design
|
||||
This starts the database, the API (port 5000) and the web app. Open http://localhost:5173 and create an
|
||||
account. Press `Ctrl+C` to stop it.
|
||||
|
||||
- **Feature slices.** One Flask Blueprint per feature: `auth.py`, `books.py` and `notes.py` each hold their
|
||||
routes, validation and SQL. `db.py` holds the pool and transactions; `validation.py` holds the shared input rules.
|
||||
- **Isolation in SQL.** Every query filters on the session's user (`AND user_id = %s`, or joins to `books`
|
||||
for notes). Another user's book and a missing book return the same 404.
|
||||
- **Passwords.** Peppered PBKDF2-HMAC-SHA256 (FIPS-approved, stdlib only). See [ADR-0001](docs/adr/0001-password-hashing-pbkdf2.md).
|
||||
- **Sessions.** Opaque tokens hashed at rest; 30-minute idle and 12-hour absolute expiry; real logout; CSRF
|
||||
handled by SameSite plus a JSON-only rule. See [ADR-0002](docs/adr/0002-server-side-sessions.md).
|
||||
- **Data rules in two places.** The API returns specific 400s, and Postgres CHECK and FK constraints
|
||||
backstop them.
|
||||
- **Frontend.** React Router (search and filter state lives in the URL), a small auth context, Tailwind.
|
||||
No state library.
|
||||
You can also start the parts on their own: `mise run db`, `mise run dev:api` and `mise run dev:web`.
|
||||
|
||||
Full spec: [docs/superpowers/specs/2026-10-02-book-tracker-design.md](docs/superpowers/specs/2026-10-02-book-tracker-design.md)
|
||||
To stop the database when you are done, run `docker compose down`.
|
||||
|
||||
## Known trade-offs
|
||||
## Run the tests
|
||||
|
||||
| Not included | Add when |
|
||||
|---|---|
|
||||
| Pagination | libraries exceed a few hundred books |
|
||||
| Trigram/full-text index | ILIKE search slows (thousands of books) |
|
||||
| Login rate limiting | before production |
|
||||
| Migrations tool | schema changes after first deploy |
|
||||
| Pepper rotation | before production key management |
|
||||
```bash
|
||||
mise run test # everything
|
||||
mise run test:py # backend only
|
||||
mise run test:ts # frontend only, plus the type check
|
||||
```
|
||||
|
||||
A request that fails with 4xx rolls back its transaction, including the session idle-window slide, so failed
|
||||
requests don't extend the 30-minute idle timeout.
|
||||
The backend tests use a real PostgreSQL database called `books_test`. It is created for you, so the database
|
||||
from `mise run db` just needs to be running (the test task starts it).
|
||||
|
||||
## Lint and format
|
||||
|
||||
```bash
|
||||
mise run format # fix formatting and import order (writes changes)
|
||||
mise run lint # check linting, formatting and types without changing files
|
||||
```
|
||||
|
||||
Run `mise run lint` and `mise run test` before you push.
|
||||
|
||||
## Change backend dependencies
|
||||
|
||||
Edit `backend/requirements.in`, then run:
|
||||
|
||||
```bash
|
||||
mise run lock # rebuild the pinned backend/requirements.txt
|
||||
mise run setup # install the new versions
|
||||
```
|
||||
|
||||
## Settings
|
||||
|
||||
- `DATABASE_URL` – the PostgreSQL connection string. It defaults to the local Docker database.
|
||||
- `PASSWORD_PEPPER` – a secret of at least 32 characters used when storing passwords. If you do not set it,
|
||||
a development value is created in `backend/.pepper` and a warning is logged. Always set it outside local
|
||||
development.
|
||||
|
||||
Run `mise tasks` to see every available task.
|
||||
|
||||
Reference in New Issue
Block a user