From 765acf5d6b668cdb8cecdfe1d7f9fbf5631ce34c Mon Sep 17 00:00:00 2001 From: Jon Seager Date: Fri, 6 Feb 2026 13:21:04 +0000 Subject: [PATCH] docs: rewrite README for clarity and brevity Consolidate from ~250 lines to ~130, focusing on intro, quick start, configuration reference, contributing, and license. Replace build-from-source with cargo install instructions. --- README.md | 278 +++++++++++++++--------------------------------------- 1 file changed, 78 insertions(+), 200 deletions(-) diff --git a/README.md b/README.md index 690727c..44b2e48 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,46 @@ # B{rew}log -**B{rew}log** is a self-hosted coffee logging platform for tracking your roasters, roasts, brews, -cafes and brewing gear. +**B{rew}log** is a self-hosted coffee logging platform for tracking roasters, roasts, brews, +cafes and brewing gear. It ships as a single Rust binary that serves a web UI, a REST API, and a +CLI client. -The application is distributed as a single Rust binary that powers both an HTTP server and a -command-line client for the API. There is a web frontend built with [Tailwind CSS](https://tailwindcss.com/) -that enables client-side reactivity with [Datastar](https://data-star.dev/). +- **Web UI** with reactive updates via [Datastar](https://data-star.dev/) and [Tailwind CSS v4](https://tailwindcss.com/) +- **REST API** for programmatic access (reads are public, writes require auth) +- **CLI client** for terminal-based workflows +- **AI extraction** — scan a coffee bag label or type a description to auto-fill forms (via [OpenRouter](https://openrouter.ai/)) +- **Nearby cafe search** powered by [Foursquare Places](https://docs.foursquare.com/developer/reference/place-search) +- **SQLite** (default) or **PostgreSQL** (compile-time feature flag) +- **Passkey authentication** — no passwords, WebAuthn only - -> [!NOTE] -> This project was built with significant assistance from Github Copilot. I used it as a test-bed -> for trying out newer agentic coding workflows, and to get some basic experience with Datastar, -> which had attracted my attention. - +## Quick Start -## Basic usage - -B{rew}log ships as one executable. You decide whether it acts as a server or a client. - -### First-time setup - -The server requires `BREWLOG_RP_ID` and `BREWLOG_RP_ORIGIN` for passkey authentication: +### Install + +```bash +cargo install --git https://github.com/jnsgruk/brewlog.git + +# For PostgreSQL instead of SQLite: +# cargo install --git https://github.com/jnsgruk/brewlog.git --no-default-features --features postgres +``` + +### Configure + +Create a `.env` file (or export the variables). Four values are required: + +```bash +BREWLOG_RP_ID="localhost" +BREWLOG_RP_ORIGIN="http://localhost:3000" +BREWLOG_OPENROUTER_API_KEY="sk-or-..." +BREWLOG_FOURSQUARE_API_KEY="fsq3..." +``` + +### Run ```bash -BREWLOG_RP_ID="localhost" \ -BREWLOG_RP_ORIGIN="http://localhost:3000" \ -BREWLOG_OPENROUTER_API_KEY="sk-or-..." \ -BREWLOG_FOURSQUARE_API_KEY="fsq3..." \ brewlog serve ``` -On first start with an empty database, the server prints a one-time registration URL: +On first start with an empty database the server prints a one-time registration URL: ``` No users found. Register the first user at: @@ -38,212 +48,80 @@ No users found. Register the first user at: This link expires in 1 hour. ``` -Open that URL in your browser, enter a display name, and register a passkey. This creates the first user account and signs you in. +Open that URL, choose a display name, and register a passkey. This creates your account and +signs you in. -> **Important**: The `BREWLOG_RP_ID` is baked into registered passkeys. If you change the domain, all existing passkeys become invalid and you'll need to re-register. +### CLI Authentication -### Authentication - -Brewlog uses passkey (WebAuthn) authentication. There are no passwords. - -1. **Web Frontend**: Sign in with your passkey to get a session cookie -2. **CLI/API**: Bearer tokens created via browser handoff - -#### Web Authentication - -1. Start the server and browse to the frontend -2. Click "Login" in the navigation bar -3. Authenticate with your passkey (fingerprint, face, security key, etc.) -4. You're now authenticated and can create/update/delete records - -#### CLI/API Authentication - -Token creation uses a browser handoff flow (similar to `gh auth login`): +To use the CLI or API for write operations, create a token via browser handoff: ```bash brewlog token create --name "my-cli-token" -# Opening browser for authentication... -# If the browser doesn't open, visit this URL: -# -# http://localhost:3000/login?cli_callback=... -# -# (authenticate with your passkey in the browser) -# -# Token created successfully! -# Token Name: my-cli-token -# -# Save this token securely - it will not be shown again: -# -# dEadB3efDeadb33fdeadb33F... -# -# Export it in your environment: -# export BREWLOG_TOKEN=dEadB3efDeadb33fdeadb33F... +# Browser opens → authenticate with your passkey → token printed once + +export BREWLOG_URL="http://localhost:3000" +export BREWLOG_TOKEN="" + +# Now you can create data from the CLI +brewlog roaster add --name "Radical Roasters" --country "United Kingdom" ``` -Export the token and use it for all CLI commands: +Run `brewlog --help` for the full command reference. -```bash -export BREWLOG_TOKEN="dEadB3efDeadb33fdeadb33F..." -export BREWLOG_URL=http://localhost:3000 +## Configuration -# Now all write operations work -brewlog roaster add \ - --name "Radical Roasters" \ - --country "United Kingdom" \ - --city "Bristol" \ - --homepage "https://radicalroasters.co.uk" - -brewlog roast add \ - --roaster-id "deadbeef" \ - --name "Chelbesa Lot 2" \ - --origin "Ethiopia" \ - --region "Gedeo" \ - --producer "Chelbesa Cooperative" \ - --process "Washed" \ - --tasting-notes "Blueberry, Jasmine" -``` - -#### Token Management - -```bash -# List your active tokens -brewlog token list - -# Revoke a token -brewlog token revoke --id abc123 -``` - -#### API Usage - -For direct API access, include your token as a Bearer token: - -```bash -curl http://localhost:3000/api/v1/roasters \ - -H "Authorization: Bearer dEadB3efDeadb33fdeadb33F..." \ - --json '{"name":"Radical Roasters","country":"United Kingdom"}' -``` - -**Note**: All read operations (GET requests) are public and don't require authentication. Only write operations (POST/PUT/DELETE) require authentication. - -## CLI Commands - -The CLI uses a subcommand structure. Each entity command supports `add`, `list`, `get`, `update`, and `delete` subcommands (except where noted): - -``` -brewlog serve Run the HTTP server -brewlog roaster Manage roasters -brewlog roast Manage roasts -brewlog bag Manage bags of coffee -brewlog gear Manage brewing gear (grinders, brewers, filter papers) -brewlog brew Manage brews (add, list, get, delete — no update) -brewlog cafe Manage cafes -brewlog cup Manage cups (cafe visits) -brewlog token Manage API tokens (create, list, revoke) -brewlog backup Export all data to JSON on stdout (requires BREWLOG_TOKEN) -brewlog restore --file F Restore data from a JSON backup into an empty database (requires BREWLOG_TOKEN) -``` - -Use `brewlog --help` for detailed options on any command. - -## Environment Variables - -All configuration is via environment variables or CLI flags. A `.env` file in the working directory is loaded automatically at startup (via [dotenvy](https://crates.io/crates/dotenvy)). +All settings are read from environment variables or CLI flags. A `.env` file in the working +directory is loaded automatically via [dotenvy](https://crates.io/crates/dotenvy). ### Server (`brewlog serve`) -| Variable | Purpose | Default | -|----------|---------|---------| -| `BREWLOG_DATABASE_URL` | Database connection string | `sqlite://brewlog.db` | -| `BREWLOG_BIND_ADDRESS` | Server bind address | `127.0.0.1:3000` | -| `BREWLOG_RP_ID` | WebAuthn Relying Party ID (your domain, e.g. `localhost` or `brewlog.example.com`) | — (required) | -| `BREWLOG_RP_ORIGIN` | WebAuthn Relying Party origin (full URL, e.g. `http://localhost:3000`) | — (required) | -| `BREWLOG_SECURE_COOKIES` | Set to `true` to enable the Secure cookie flag (for HTTPS) | `false` | -| `RUST_LOG` | Log level filter | `info` | -| `RUST_LOG_FORMAT` | Log output format: omit for compact human-readable, set to `json` for structured JSON | — | +| Variable | Purpose | Default | +| ------------------------ | ------------------------------------------------------ | --------------------- | +| `BREWLOG_RP_ID` | WebAuthn Relying Party ID (your domain) | **required** | +| `BREWLOG_RP_ORIGIN` | WebAuthn Relying Party origin (full URL) | **required** | +| `BREWLOG_DATABASE_URL` | Database connection string | `sqlite://brewlog.db` | +| `BREWLOG_BIND_ADDRESS` | Server bind address | `127.0.0.1:3000` | +| `BREWLOG_SECURE_COOKIES` | Enable the `Secure` cookie flag (set `true` for HTTPS) | `false` | +| `RUST_LOG` | Log level filter | `info` | +| `RUST_LOG_FORMAT` | Set to `json` for structured log output | — | ### CLI Client -| Variable | Purpose | Default | -|----------|---------|---------| -| `BREWLOG_URL` | Server URL for CLI commands | `http://localhost:3000` | -| `BREWLOG_TOKEN` | API token for authenticated CLI operations | — | +| Variable | Purpose | Default | +| --------------- | ------------------------------------- | ----------------------- | +| `BREWLOG_URL` | Server URL | `http://localhost:3000` | +| `BREWLOG_TOKEN` | API bearer token for write operations | — | ### Integrations -| Variable | Purpose | Default | -|----------|---------|---------| -| `BREWLOG_OPENROUTER_API_KEY` | [OpenRouter](https://openrouter.ai/) API key for AI extraction | — (required) | -| `BREWLOG_OPENROUTER_MODEL` | LLM model for AI extraction | `openrouter/free` | -| `BREWLOG_FOURSQUARE_API_KEY` | [Foursquare](https://foursquare.com/) Places API key for nearby cafe search | — (required) | +| Variable | Purpose | Default | +| ---------------------------- | --------------------------------------------------------------------------- | ----------------- | +| `BREWLOG_OPENROUTER_API_KEY` | [OpenRouter](https://openrouter.ai/) API key for AI extraction | **required** | +| `BREWLOG_OPENROUTER_MODEL` | LLM model for AI extraction | `openrouter/free` | +| `BREWLOG_FOURSQUARE_API_KEY` | [Foursquare](https://foursquare.com/) Places API key for nearby cafe search | **required** | -## Integrations +### Database -### AI Extraction - -The web UI uses an LLM via [OpenRouter](https://openrouter.ai/) to extract roaster and roast details from photos or text descriptions. `BREWLOG_OPENROUTER_API_KEY` is required. It powers: - -- Photo extraction buttons on the roaster and roast forms -- Text-based extraction from typed descriptions -- The **Scan Bag** feature on the home page, which extracts both roaster and roast data from a single coffee bag label photo -- The **Scan Bag** feature on the check-in page, which identifies a roast from a bag photo - -### Nearby Cafe Search - -The check-in and cafes pages search for nearby coffee shops via the [Foursquare Places API](https://docs.foursquare.com/developer/reference/place-search). `BREWLOG_FOURSQUARE_API_KEY` is required. Searches can be made by GPS coordinates or city name. - -## Database - -SQLite is the default database. PostgreSQL is supported via a compile-time feature flag: +SQLite is the default. PostgreSQL is supported via a compile-time feature flag: ```bash -# SQLite (default) -cargo build --release - -# PostgreSQL -cargo build --release --features postgres --no-default-features +cargo build --release # SQLite +cargo build --release --features postgres --no-default-features # PostgreSQL ``` Migrations run automatically on server startup. -### Backup & Restore - -Backup and restore go through the API and require authentication (`BREWLOG_TOKEN`). +## Contributing ```bash -# Export all data to JSON -brewlog backup > backup.json - -# Restore into an empty database -brewlog restore --file backup.json +cargo build # Build +cargo clippy --allow-dirty --fix # Lint +cargo fmt # Format +cargo test # Test ``` -The API endpoints are also available directly: +See [CLAUDE.md](CLAUDE.md) for architecture, code patterns, and development conventions. -- `GET /api/v1/backup` — export all data as JSON (requires auth) -- `POST /api/v1/backup/restore` — restore from a JSON backup (requires auth, database must be empty) +## License -## Installation - -At present, the only way to use `brewlog` is to build it from source: - -```bash -git clone https://github.com/jnsgruk/brewlog.git -cd brewlog -cargo build --release -``` - -The resulting binary lives at `target/release/brewlog`. - -During development you can run directly: - -```bash -cargo run -- serve -``` - -## Testing - -The project includes unit and integration tests: - -```bash -cargo test -``` +[Apache License 2.0](LICENSE)