Stack
Framework
- Next.js 15 (App Router)
- React 19
- TypeScript
Containerization and runtime
- Docker (linux/amd64 and linux/arm64)
- Shared entrypoint that runs DB migrations by default and can bootstrap embedded SeaweedFS before app startup
Next.js client
- UI: Tailwind CSS, Headless UI, @tailwindcss/typography
- Interactions:
react-dnd,react-dropzone - Authentication: Better Auth client SDK
- Local storage/cache: Dexie.js (IndexedDB)
- Document rendering:
- PDF: react-pdf, pdf.js
- EPUB: react-reader, epubjs
- Markdown/Text: react-markdown, remark-gfm
- Text preprocessing/matching: compromise, cmpstr
Next.js server
- APIs: Route Handlers for sync, blob/content access, migrations, audiobook export, TTS/Whisper proxying
- State sync: request-based today (not realtime push updates)
- Authentication: Better Auth server handlers/adapters
- Metadata DB: Drizzle ORM with SQLite (
better-sqlite3) by default and optional Postgres (pg)- App tables are manually maintained in Drizzle schema files
- Auth tables are auto-generated by the Better Auth CLI and migrated alongside app tables via Drizzle
- Blob storage: embedded SeaweedFS (
weed mini) by default, or external S3-compatible storage via AWS SDK v3 - Audio/processing pipeline: OpenAI-compatible TTS providers, ffmpeg for audiobook assembly, optional whisper.cpp for word timestamps
Tooling and testing
- ESLint
- TypeScript
- Playwright end-to-end tests
- Drizzle migration/generation scripts