No description
Find a file
Jon Seager 12dcc37cbe
fix: persist session cookie with max-age for Safari PWA support
Session cookie lacked a Max-Age attribute, making it ephemeral. Safari's
standalone PWA mode aggressively clears session cookies on app suspend,
causing frequent logouts. Set Max-Age to 30 days to match the server-side
session lifetime.
2026-02-15 10:36:05 +00:00
.cargo perf(build): add release profile, lld linker, and defer script tags 2026-02-06 18:05:16 +00:00
.github ci: add e2e browser test job to GitHub Actions 2026-02-10 10:45:12 +00:00
migrations feat: add entity image support with display on detail pages 2026-02-10 17:50:13 +00:00
scripts build: add treefmt and pre-commit 2026-02-09 11:35:21 +00:00
src fix: persist session cookie with max-age for Safari PWA support 2026-02-15 10:36:05 +00:00
static fix: address static assets code review findings 2026-02-13 17:13:02 +00:00
templates fix: address static assets code review findings 2026-02-13 17:13:02 +00:00
tests fix: address static assets code review findings 2026-02-13 17:13:02 +00:00
.gitignore chore: update gitignore 2026-02-13 11:27:02 +00:00
build.rs fix(build): pass git hash to Nix builds via env var 2026-02-07 11:17:03 +00:00
Cargo.lock fix: apply EXIF orientation to uploaded photos 2026-02-12 18:07:52 +00:00
Cargo.toml fix: security hardening and code health improvements in domain layer 2026-02-13 16:20:11 +00:00
CLAUDE.md docs: trim CLAUDE.md from 972 to ~250 lines 2026-02-09 16:43:19 +00:00
flake.lock build: add treefmt and pre-commit 2026-02-09 11:35:21 +00:00
flake.nix build: fail-fast pre-commit hooks for faster iteration 2026-02-12 15:30:57 +00:00
fly.toml feat: add /health endpoint for Fly.io health checks 2026-02-08 15:37:35 +00:00
LICENSE docs: add LICENSE 2026-02-03 20:53:45 +00:00
README.md docs: add note about Claude usage in README 2026-02-12 15:55:57 +00:00

cover image

B{rew}log is a self-hosted specialty coffee logging platform optimised for filter brewing enthusiasts. B{rew}log can be used for tracking roasters, roasts, brews, cafes and brewing gear.

B{rew}log features an LLM-powered "Bag Scanning" feature, which enables it to automatically fill roaster and coffee information using a photo of a bag. It also supports "check-ins" to log coffee enjoyed in a cafe.

B{rew}log ships as a single Rust binary that serves a web UI, a REST API, and a CLI client. The application uses SQLite as a backend, and will automatically create and migrate the database on start-up.

Note

This application was built almost entirely with Claude Code. I used this project as an excuse to explore the current state of the art in agentic coding tools. I've reviewed much of the code, and I'm largely responsible for the rules and the layout of the repository but nonetheless the vast majority of the code was written by Claude and Opus 4.6.

Quick Start (Demo)

Before you start, you'll need to sign up for Openrouter and Foursquare Places and get API keys for both.

Then create a docker.env file:

# You'll need an API key from OpenRouter
BREWLOG_OPENROUTER_API_KEY=sk-or-...
# I've had good results with Gemini models, but you can try 'openrouter/free' to experiment
BREWLOG_OPENROUTER_MODEL=google/gemini-3-flash-preview
# FourSquare Places API key for location searching
BREWLOG_FOURSQUARE_API_KEY=fsq3...

You can see the full list of configuration options below. Once your .env file is complete, start the container using the environment file

# Create a data directory to store the database
mkdir data
# Run the container
docker run \
  --rm \
  -p 3000 \
  --env-file docker.env \
  -v $PWD/data:/data \
  ghcr.io/jnsgruk/brewlog:latest

On first start with an empty database the server prints a one-time registration URL:

No users found. Register the first user at:
  http://localhost:3000/register/abc123...
This link expires in 1 hour.

Open that URL, choose a display name, and register a passkey. This creates an account and signs in automatically.

Install from Git

To build and install from source, you'll need a working Rust toolchain:

cargo install --locked --git https://github.com/jnsgruk/brewlog.git

Then create a .env file containing at least your OpenRouter and Foursquare API keys, and start the server:

brewlog serve

CLI Authentication

To use the CLI or API for write operations, create a token via browser hand-off:

brewlog token create --name "my-cli-token"
# Browser opens → authenticate with a passkey → token printed once

export BREWLOG_URL="http://localhost:3000"
export BREWLOG_TOKEN="<token from above>"

# Create data from the CLI
brewlog roaster add --name "Radical Roasters" --country "United Kingdom"

Run brewlog --help for the full command reference.

Configuration

All settings are read from environment variables or CLI flags. A .env file in the working directory is loaded automatically via dotenvy.

Server (brewlog serve)

Variable Purpose Default
BREWLOG_RP_ID WebAuthn Relying Party ID (server domain) localhost
BREWLOG_RP_ORIGIN WebAuthn Relying Party origin (full URL) http://localhost:3000
BREWLOG_DATABASE_URL Database connection string sqlite://brewlog.db
BREWLOG_BIND_ADDRESS Server bind address 127.0.0.1:3000
BREWLOG_INSECURE_COOKIES Disable the Secure cookie flag (auto-enabled for localhost defaults) 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 http://localhost:3000
BREWLOG_TOKEN API bearer token for write operations

Integrations

Variable Purpose Default
BREWLOG_OPENROUTER_API_KEY OpenRouter API key for AI extraction required
BREWLOG_OPENROUTER_MODEL LLM model for AI extraction openrouter/free
BREWLOG_FOURSQUARE_API_KEY Foursquare Places API key for nearby cafe search required

Contributing

cargo build                           # Build
cargo clippy --allow-dirty --fix      # Lint
cargo fmt                             # Format
cargo test                            # Test

See CLAUDE.md for architecture, code patterns, and development conventions.

License

Apache License 2.0