Catchbox is a self-hosted, local-first capture inbox for text, URLs, images, and files. Its first priority is dependable input: accept a share locally, preserve it through connectivity failures, synchronize without duplicates, and keep the original data easy to export.
Sending something into an inbox should not depend on a perfect network connection. Catchbox treats capture as a durable workflow rather than a best-effort request:
- A client stores the complete capture locally before reporting success.
- One mixed share becomes a batch of independent items linked by a batch ID.
- Stable client IDs make retries and ambiguous-response reconciliation idempotent.
- Successful items survive when a sibling item fails.
- Original attachment bytes are preserved; previews and extracted content are reproducible.
- Slow metadata and extraction work never delays capture persistence.
Catchbox v1 will provide:
- A responsive PWA for quick capture and a chronological inbox.
- Android and iOS share integrations for text, URLs, images, and arbitrary files.
- A documented authenticated HTTP interface for scripts and future clients.
- Durable client outboxes with automatic retry, manual retry, discard, and reconciliation.
- Clear pending, synced, and failed states.
- Authenticated attachment downloads and a portable metadata-plus-originals export.
- A single-user, ARM64-compatible Compose deployment for a trusted local network.
- Backup, restore, migration, health-check, and recovery procedures.
Authentication remains mandatory for every data and attachment route, even on the LAN.
The project will use a Bun workspace monorepo with TypeScript wherever practical:
apps/
web/ React + Vite PWA
api/ Express 5 HTTP server
worker/ Asynchronous jobs
clients/
android/ Android share target
ios/ iOS share extension
packages/
db/ Drizzle schema, migrations, and repositories
shared/ Zod contracts and shared domain types
services/
extractor/ Isolated Python text extraction
infra/ Local container and Compose assets
Server metadata will live in SQLite using Drizzle migrations. Original attachments will live in a configurable server-owned filesystem directory and become ready only after an atomic final write. Derived work will run through durable jobs outside the capture request.
Contributions must preserve these rules:
- A mixed share is a batch of independently stored items linked by
batch_id. - A client persists input locally before reporting capture success.
- Network retries cannot create duplicate batches or items.
- Capture persistence does not wait for previews, metadata extraction, OCR, or indexing.
- Original attachment bytes are authoritative and preserved.
- Every data and attachment route requires authentication.
The implementation will proceed in small vertical slices:
- Workspace, shared contracts, configuration, logging, and automated checks.
- SQLite migrations, attachment storage, backup, and restore.
- Account bootstrap, sessions, authorization, and password changes.
- Idempotent batch ingestion, reconciliation, and authenticated downloads.
- PWA quick capture, durable outbox, retry behavior, and inbox.
- Worker jobs and isolated extraction.
- Android and iOS share integrations.
- ARM64 deployment, export, operations documentation, and recovery drills.
- Implementation plan — product scope, architecture, interfaces, and delivery sequence.
- Catchbox v1 specification — implementation-ready behavior, user stories, decisions, and acceptance strategy.
- Agent guide — repository invariants, conventions, and quality gates for contributors and coding agents.
Implementation tickets will be derived from the v1 specification and linked through explicit blocking relationships. Work should proceed blockers-first, one small vertical slice at a time, with tests at the highest observable seam.
Before contributing, read the implementation plan and agent guide. Do not expand v1 into collaboration, public hosting, Postgres, S3 storage, semantic search, OCR, reminders, or full note-editor parity unless that scope is explicitly changed.