forked from mirror/crumbs-original
docs: deduplicate README, add OpenAPI spec with auto-generated API docs
- Slim README to essentials, link to docs/ for details - Add docs/openapi.yaml as single source of truth for the API - Add scripts/generate-api-docs.ts to produce docs/API.md from the spec - Add pnpm docs:api / make docs-api target Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
66c91df983
commit
26cae27857
@@ -1,24 +1,6 @@
|
||||
# Crumbs by Bretzel
|
||||
# 🥨 Crumbs by Bretzel
|
||||
|
||||
A self-hostable, offline-first note-taking app inspired by Google Keep. Part of the [Bretzel](https://bretzel.app) app universe. Built with SvelteKit, SQLite, and Tailwind CSS.
|
||||
|
||||
## Features
|
||||
|
||||
- **Notes CRUD** - Create, edit, and delete notes with rich Markdown support
|
||||
- **Markdown** - Bold, italic, headings, lists, code blocks, tables, links
|
||||
- **Checklists** - Interactive task lists with checkboxes
|
||||
- **Image Attachments** - Upload and display images in notes
|
||||
- **Tags** - Organize notes with inline #hashtags
|
||||
- **Colors** - 12 color-coded note backgrounds (matching Google Keep)
|
||||
- **Pin** - Pin important notes to the top
|
||||
- **Archive** - Archive notes to declutter your main view
|
||||
- **Trash** - Soft delete with restore capability
|
||||
- **Search** - Full-text search across titles, content, and tags
|
||||
- **Dark Mode** - System-aware with manual toggle
|
||||
- **Single-User Auth** - Password-protected access
|
||||
- **PWA** - Installable as a standalone app with offline support
|
||||
- **Local-First** - Notes stored in IndexedDB, synced to server via LWW CRDTs
|
||||
- **Docker** - Single command deployment with `docker compose up`
|
||||
A self-hostable, offline-first note-taking app inspired by Google Keep. Part of the [Bretzel](https://bretzel.app) app universe.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -33,118 +15,60 @@ Open http://localhost:3000 and set your password on first visit.
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Start dev server
|
||||
pnpm dev
|
||||
|
||||
# Run unit tests
|
||||
pnpm test:unit
|
||||
|
||||
# Run E2E tests (requires Playwright browsers)
|
||||
npx playwright install chromium
|
||||
pnpm test:e2e
|
||||
|
||||
# Type check
|
||||
pnpm check
|
||||
|
||||
# Build for production
|
||||
pnpm build
|
||||
```
|
||||
|
||||
Run `make help` to see all available commands, or use pnpm directly:
|
||||
|
||||
```bash
|
||||
pnpm test # Unit + E2E tests
|
||||
pnpm check # Type checking
|
||||
pnpm build # Production build
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Rich notes with Markdown, checklists, image attachments, and 12 color themes
|
||||
- Organize with #tags, pinning, archive, and trash
|
||||
- Full-text search across titles, content, and tags
|
||||
- Dark mode with system detection
|
||||
- PWA — installable, works offline via IndexedDB + LWW CRDT sync
|
||||
- Single-user password auth (Argon2)
|
||||
- Docker deployment with a single command
|
||||
|
||||
See [docs/FEATURES.md](docs/FEATURES.md) for detailed feature documentation.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|-----------|
|
||||
| Framework | SvelteKit 2 |
|
||||
| Framework | SvelteKit 2 (Svelte 5 runes) |
|
||||
| Language | TypeScript (strict) |
|
||||
| UI | Tailwind CSS 4 |
|
||||
| Database | SQLite (better-sqlite3) |
|
||||
| ORM | Drizzle ORM |
|
||||
| Database | SQLite (better-sqlite3) + Drizzle ORM |
|
||||
| Client DB | IndexedDB (idb) |
|
||||
| Sync | LWW CRDTs |
|
||||
| Auth | Argon2 + session cookies |
|
||||
| Markdown | markdown-it |
|
||||
| PWA | @vite-pwa/sveltekit |
|
||||
| Testing | Vitest + Playwright |
|
||||
| Container | Docker (multi-stage) |
|
||||
| CI/CD | GitHub Actions |
|
||||
|
||||
## Project Structure
|
||||
## Documentation
|
||||
|
||||
```
|
||||
src/
|
||||
├── lib/
|
||||
│ ├── components/ # Svelte UI components
|
||||
│ ├── server/db/ # Drizzle schema & connection
|
||||
│ ├── server/auth.ts # Authentication logic
|
||||
│ ├── sync/ # CRDT sync engine (client + server)
|
||||
│ ├── stores/ # Svelte reactive stores
|
||||
│ ├── types/ # TypeScript type definitions
|
||||
│ └── utils/ # Markdown, tags, colors, debounce
|
||||
├── routes/
|
||||
│ ├── api/ # REST API endpoints
|
||||
│ ├── login/ # Login page
|
||||
│ ├── setup/ # First-run setup page
|
||||
│ └── +page.svelte # Main notes view
|
||||
└── hooks.server.ts # Auth middleware
|
||||
tests/
|
||||
├── unit/ # Vitest unit tests
|
||||
└── e2e/ # Playwright E2E tests
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/api/notes?filter=all\|archived\|trashed` | List notes |
|
||||
| POST | `/api/notes` | Create a note |
|
||||
| GET | `/api/notes/:id` | Get a note |
|
||||
| PATCH | `/api/notes/:id` | Update a note |
|
||||
| DELETE | `/api/notes/:id` | Delete a note permanently |
|
||||
| GET | `/api/search?q=query` | Full-text search |
|
||||
| GET | `/api/tags` | List all tags |
|
||||
| POST | `/api/sync` | Push sync changes |
|
||||
| GET | `/api/sync?since=timestamp` | Pull changes since timestamp |
|
||||
| POST | `/api/auth/setup` | First-time password setup |
|
||||
| POST | `/api/auth/login` | Login |
|
||||
| POST | `/api/auth/logout` | Logout |
|
||||
| GET/POST/DELETE | `/api/notes/:id/attachments` | Manage image attachments |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `DATABASE_URL` | `./data/crumbs.db` | SQLite database file path |
|
||||
| `DATA_DIR` | `./data` | Data directory for attachments |
|
||||
| `ORIGIN` | `http://localhost:3000` | Server origin (CSRF protection) |
|
||||
| `PORT` | `3000` | Server port |
|
||||
| `NODE_ENV` | `development` | Node environment |
|
||||
| Document | Description |
|
||||
|----------|-------------|
|
||||
| [Features](docs/FEATURES.md) | Detailed feature list and behavior |
|
||||
| [Architecture](docs/ARCHITECTURE.md) | Local-first sync design, tech rationale, DB schema |
|
||||
| [Deployment](docs/DEPLOYMENT.md) | Docker, Node.js, reverse proxy, backups, env vars |
|
||||
| [API](docs/API.md) | REST API reference (auto-generated) |
|
||||
|
||||
## CI/CD
|
||||
|
||||
GitHub Actions workflows are included:
|
||||
- **CI** — lint, type check, unit tests, E2E tests, Docker build on every push/PR
|
||||
- **Release** — builds and pushes Docker image on `v*` tags
|
||||
|
||||
- **CI** (`ci.yml`): Runs on every push/PR - lint, type check, unit tests, build, E2E tests, Docker build
|
||||
- **Release** (`release.yml`): Runs on version tags (`v*`) - builds and pushes Docker image to a configurable registry
|
||||
|
||||
Configure your registry via GitHub Secrets:
|
||||
- `REGISTRY_URL` - Container registry URL
|
||||
- `REGISTRY_USER` - Registry username
|
||||
- `REGISTRY_TOKEN` - Registry access token
|
||||
|
||||
## Sync Architecture
|
||||
|
||||
Crumbs uses a local-first architecture with Last-Write-Wins (LWW) conflict resolution:
|
||||
|
||||
1. All reads come from IndexedDB (instant, works offline)
|
||||
2. Writes go to IndexedDB + a sync queue
|
||||
3. Background sync pushes queued changes to server every 30s
|
||||
4. Server resolves conflicts using timestamps (newer wins)
|
||||
5. Client pulls server changes and merges with local state
|
||||
|
||||
This ensures the app works fully offline and syncs automatically when connectivity is restored.
|
||||
Configure registry via GitHub Secrets: `REGISTRY_URL`, `REGISTRY_USER`, `REGISTRY_TOKEN`.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user