Free book library with Kindle-like reader. EPUB/PDF upload, parsing, SEO pages, and offline reading.
Live: textstack.app (public) · textstack.dev (admin)
| Document | Description |
|---|---|
| CLAUDE.md | AI assistant context (commands, key files, concepts) |
| STATUS.md | Where the project is right now — in flight, known-broken, won't-do |
| CHANGELOG.md | Release index — one line per change, by deploy date |
| Incidents | Postmortems: what broke, why it was invisible, what it taught |
| Changelog archive | The full write-up behind every changelog line |
| Vision | Goals, principles, stack |
| Architecture | System design: services, projects, pipeline, external deps |
| Delivery | PR → images → deploy flow, external dependencies, secret controls |
| Data model | Every table: purpose, status, PII |
| API Docs | http://localhost:8080/scalar/v1 (live) |
| Local Dev | Docker, migrations |
| Environment Variables | Complete env var reference |
| Production Deployment | Cloudflare tunnel, nginx, Docker |
| Backup & Restore | make backup, GHA daily dump, restore drill |
| Uptime Monitoring | External probes + alert runbook |
| Incident Runbook | First-response for DB/worker/SSG/site outages |
| infra/scripts/README | Pollers (SEO publish, SEO backfill, quality) — what, install, logs |
| infra/systemd/README | User-level systemd units |
| Play Store release | Android release runbook (EAS, tracks, OTA) |
| Android App Links | Deep links / assetlinks |
| E2E Testing Guide | Playwright setup, UI mode, troubleshooting |
| LLM Provider Swap | Swap the Ollama calls (distractors, metadata) for a hosted API |
| Feature | Description | Docs |
|---|---|---|
| Reader | Kindle-like reading (settings, navigation, mobile) | reader.md |
| Offline | IndexedDB caching, download manager | offline-reading.md |
| Auth | Google, Apple, email/password, guest sessions, JWT | user-auth.md, ADR-014 |
| Search | PostgreSQL FTS (trigger-maintained search_vector) |
feat-0006 |
| Vocabulary | SRS vocab builder + Ollama LLM | vocabulary-srs.md |
| Ingestion | EPUB/PDF extraction, admin + user uploads | ingestion.md |
| MCP server | Connect TextStack to Claude Desktop / Cursor / ChatGPT | mcp.md |
| Chapter review | Assistant reviews a chapter over MCP | chapter-review.md |
| SSG | Prerendered HTML for crawlers | ssg-prerender.md |
docs/
├── 00-vision/ # Why: goals, vision
├── 01-architecture/ # How: design, ADRs, architecture review
├── 02-system/ # What: schemas, APIs
├── 03-ops/ # Run: setup, deploy, Play release
├── 04-dev/ # Build: test, security
├── 05-features/ # Feature docs
├── claude/ # Reference loaded from CLAUDE.md
├── incidents/ # Postmortems
├── qa/ # Manual scenarios and reports
├── changelog-archive/ # Full write-ups behind CHANGELOG lines
└── marketing/ research/ loadtest/
| Feature | Docs |
|---|---|
| Text Extraction | feat-0003 |
| Observability | feat-0005 |
| i18n | /:lang/ routes; English only since 2026-04-21 (Ukrainian removed) |
| E2E Testing | Playwright e2e tests with CI pipeline |
| Text Selection | Highlights, translate, Explain, TTS in reader (free dictionary removed 2026-10-03) |
| Vocabulary SRS | Spaced repetition vocab builder with Ollama LLM distractors |
| Reading Stats | Heatmap, streaks, goals, achievements |
- New to project: Vision → Architecture → Local Dev
- Backend work: Data model → Ingestion → API Docs (Scalar)
- Frontend work: Reader → Offline → Auth
- Ops: Local Dev → Production Deployment → Backup
All in 01-architecture/adr/. Numbering is messy (three 007s, 0001 vs 001); read the status
line at the top of each file.
| ADR | Title | Status |
|---|---|---|
| 0001 | Audience-based multisite | Superseded by 007 |
| 001 | Storage via bind mounts | In force |
| 002 | Google OAuth only | Obsolete |
| 003 | Work/Edition data model | In force |
| 004 | PostgreSQL FTS | In force |
| 005 | Multisite via Host | Superseded by 007 |
| 006 | Modular monolith | In force |
| 007 | Single domain consolidation (+ deploy runbook) | Implemented |
| ADR-007 | Reader auto-save (number clash) | In force |
| ADR-010 | SEO backfill automation | Implemented |
| ADR-011 | Mobile reader progress | Partly superseded |
| ADR-012 | PDF original-first | Display in force; RAG parts obsolete |
| ADR-013 | Reader position model | In force |
| ADR-014 | Guest sessions | In force (amended) |
| ADR-015 | Position is a place in the text | In force |
| ADR-016 | Chapter review in BookInsight |
Implemented |
| ADR-017 | OAuth AS for MCP | In force |
| ADR-018 | Re-ingest updates chapters in place; reader data never cascades | In force |
| ADR-019 | Reader position: shared rules, not a shared state machine | Accepted |
| ADR-020 | Build once on GitHub, deploy by digest (+ delivery pipeline) | Accepted |
| ADR-021 | Migrations are owned by the migrator; Api reports a schema behind its build | Accepted |
| ADR-022 | One consumer per queue; recover at startup, give the claim back on shutdown | Accepted |
| ADR-023 | Api and Worker are single-instance; no fire-and-forget for real work | Accepted |
| ADR-024 | Auth fails closed by path (/me, /internal like /admin) + public-routes snapshot |
Accepted |
| Event | Update |
|---|---|
| Entity added | 01-architecture/data-model.md |
| Endpoint added | (auto in Scalar) |
| Architecture decision | New ADR |
| Migration created | Mention if significant |
| New page type (indexable/not) | seo-implementation.md |
- Choosing between 2+ valid approaches
- Decision affects multiple modules
- Hard to reverse
- Security implications