File-driven homebrewing tool. Recipes in, brew sessions out — everything as plain JSON you can read, version, share, and round-trip with the tools you already use.
Werb sits at the intersection of BeerSmith (calculation depth) and Docusaurus (file-first, your data is yours). One recipe is one BeerJSON file. One brew is one session file. Every calculation has a JSON Schema.
Runs as a Tauri desktop app on macOS / Windows / Linux, and as a Progressive Web App in any modern browser.
macOS users — “Werb is damaged and can’t be opened”? The desktop builds aren’t code-signed/notarized yet (Apple Developer ID pending), so Gatekeeper quarantines the download. It’s not actually damaged. Either:
- right-click
Werb.app→ Open → Open (or System Settings → Privacy & Security → Open Anyway), or- clear the quarantine flag:
xattr -dr com.apple.quarantine /Applications/Werb.appOr skip the install entirely and use the PWA — same app, nothing to sign, works offline once loaded.
Most brewing apps lock your recipes inside a proprietary cloud silo. Werb takes the opposite stance: your recipes are plain BeerJSON files on your disk, your brew sessions are plain JSON next to them, and the calc engine is a typed open library you can audit. If Werb disappears tomorrow, your data is still BeerJSON — readable in every other brewing tool.
- Import BeerJSON and BeerXML recipes from BeerSmith, Brewfather, etc.
- Compute IBU (Tinseth / Rager), color (Morey / Daniels), gravity, ABV, FG from yeast attenuation, water volumes (classic mash or BIAB), mash strike temperature, carbonation (priming + force), yeast pitch rate, yeast starter sizing, and brewing-salt additions to a target water profile.
- Scale a recipe to your equipment profile in one click.
- Brew with a live session screen: timeline with countdowns, per-hop addition reminders, measurement logging (gravity, pH, temperature, volume, ABV), screen wake-lock.
- Reflect with a post-brew sensory tasting form (7-axis radar chart, star rating, lessons-learned tags) that surfaces on the recipe screen so the next brew of the same recipe sees what to adjust.
- Track rough batch cost from a bundled price table with a single inflation coefficient for your local market.
- Export as BeerJSON, BeerXML, or a printable HTML (foldable into a PDF).
- Sync across devices via a private GitHub repo (optional, manual push/pull, your PAT never leaves the machine).
The app speaks English and French end-to-end (auto-detected, switchable in Settings) and ships dark and light themes — the signature Cassis dark for indoor brew days, a warm-cream light for outdoor sessions in the sun. Everything works offline. Web build is a full PWA — installable to your home screen on phones and tablets.
Requirements:
- Node.js 20+ and pnpm.
- Rust toolchain via rustup, with the WASM target installed (the BeerXML parser ships as a WASM crate). Homebrew's
rustformula omits thewasm32-unknown-unknowntarget, so the desktop dev / test commands fail withwasm32-unknown-unknown target not found in sysrootif you install Rust that way — use rustup instead. - wasm-pack to bundle the crate (
cargo install wasm-pack). - For desktop builds only: the Tauri toolchain.
git clone --recurse-submodules <repo># vendor/beerjson/ is a submodule# Already cloned? Run: git submodule update --init --recursive# One-time Rust setup (skip if rustup is already configured):
rustup target add wasm32-unknown-unknown
cargo install wasm-pack
pnpm install
pnpm gen:types # generate TS types from JSON Schemas
pnpm -F @werb/desktop build:wasm # build the BeerXML WASM crate (tests need it)
pnpm test# 430+ tests across calc / adapters / desktop hooks# Web dev:
pnpm -F @werb/desktop dev
# Desktop dev (Tauri):
pnpm -F @werb/desktop tauri:dev
# Production web build:
pnpm -F @werb/desktop buildThe BeerJSON 2.x schemas (used by the validator, the Rust type
generator, and the schema-driven tests) live under vendor/beerjson/
as a git submodule. It tracks the werb-dev/beerjson
fork while PR #222 is
pending; once merged we'll repoint at upstream beerjson/beerjson.
schemas/ JSON Schemas — single source of truth
├─ werb-equipment.schema.json
├─ werb-session.schema.json
└─ tools/*.input.schema.json one per calc tool
packages/
├─ types/ schemas → TypeScript types (generated)
├─ calc/ pure calc engine (IBU, water, gravity, …)
├─ adapters/ BeerJSON ⇄ internal, unit helpers
└─ validate/ Ajv-based schema validation
crates/
├─ werb-beerxml/ Rust BeerXML parser
└─ werb-beerxml-wasm/ WASM bindings for the browser
apps/
└─ desktop/ React + Tauri shell
├─ src/screens/ Library, Recipe, Brew, Journal, Settings, Equipment, Editor
├─ src/data/ Storage backends, units, recipes, cost, prices
└─ src-tauri/ Rust shell + capabilities
scripts/
└─ gen-types.mjs schema → .d.ts compiler
Every calc tool is contract-first: define the JSON Schema, regenerate types, implement, test. The UI consumes those generated types.
A standalone Rust binary that converts and validates recipe files from the shell. Useful for bootstrapping a recipe archive on GitHub, scripting batch imports, or wiring schema validation into CI on a recipes-only repo.
# Bulk-convert mixed BeerXML/BeerJSON files into per-recipe .beerjson
werb convert ~/Downloads/*.xml ~/old-recipes/ -o ./recipes
# Validate every recipe in a folder against the BeerJSON 2.x schema
werb validate ./recipes
# ✓ ./recipes/blanche.beerjson# ✗ ./recipes/typo.beerjson# /beerjson/recipes/0/style/category_number: want integer, but got string# 1 valid · 1 invalidInstall: download the binary for your platform from the latest release, or cargo install --git https://github.com/werb-dev/werb werb-cli. The full reference lives in the docs site.
- Everything stays on your device by default. Web build uses OPFS; desktop build writes to the platform's app-data directory.
- GitHub sync is opt-in. Your Personal Access Token is stored in your browser's local storage and never leaves the device. Push / Pull is manual and explicit.
- No telemetry, no analytics, no third-party scripts.
v0.3 — public alpha. The brewing math is well-tested and matches reference tables (Tinseth + Rager IBU, Morey + Daniels color, classic + BIAB water, yeast pitch + starter sizing, FG from attenuation); UI is responsive (tablet-first, phone-usable), localised in English and French, and ships in both Cassis dark and warm-cream light. Cost estimator uses approximate EUR baseline prices — calibrate via Settings → Cost adjustment.
Tested against an iPad Air 2 (iOS 15.8.4) for the PWA path including the older Safari file-picker quirks.
- BeerJSON 2.x — recipe interchange format. Werb reads and writes it round-trip.
- BeerXML 1.0 — legacy interchange format. Read-only support via the bundled WASM parser.
- BJCP 2021 Style Guidelines — embedded as the editor's style picker.
MIT — see LICENSE.
Issues and PRs welcome. The contract-first workflow makes contributions easy to scope:
- Pick or open an issue.
- If your change touches a calculation, write the JSON Schema first.
- Regenerate types (
pnpm gen:types). - Implement + add tests.
pnpm lint && pnpm typecheck && pnpm test && pnpm buildshould stay green.
Before tagging a release, walk through docs/SMOKE_TEST.md on a clean profile.
Werb is built in the evenings between brew days. If it helped you ship a batch you're proud of, sponsor me on GitHub — every contribution lands as a few more hours per month on the roadmap (PDF brew sheet, inventory module, mash profile library …), the Apple developer + signing fees that keep the desktop builds landing without scary OS warnings, and the occasional sack of pale malt that becomes a regression-test brew.
Cheers, and good brewing. 🍺



