DisplacedForest/ferment
Summary
Ferment is a self-hosted, Docker-deployable fermentation tracking app for home winemakers, brewers, and mead makers. It logs gravity readings from smart hydrometers (Tilt, iSpindel), manages multi-phase fermentation protocols with configurable completion criteria, and integrates with Home Assistant via MQTT and webhooks. It's a Next.js 15 app with SQLite backend, not a SaaS — you run it on your own hardware.
Great for
home fermenters or IoT hobbyists who want to self-host a fermentation logger with smart hydrometer integration and Home Assistant automation — or TypeScript/Next.js developers looking for a real-world full-stack project with hardware device integration
Easy wins
- +Add unit tests for the phase-engine.ts and alert-detection.ts logic — these are pure functions with no UI dependency and currently have zero test coverage
- +The queries.ts getBatches() builds raw SQL IN clauses manually with sql.join() instead of using Drizzle's inArray() operator — refactor to use the proper ORM abstraction and reduce the duplicated pattern across ~6 queries
- +Add a screenshot/demo GIF to the README (currently just a commented-out placeholder) — would significantly increase project visibility
- +The HydrometerManager component fires un-awaited fetch calls in handleToggleActive and handleDelete with no error handling — add try/catch and user feedback
Red flags
- !Zero tests across the entire codebase — the phase engine, alert detection, and reading bucketing logic are non-trivial and completely untested
- !Single commit history (commit_count: 1) suggests this was pushed as a bulk initial commit — no incremental development history to review contributor intent or design evolution
- !API authentication is opt-in (FERMENT_API_KEY unset = open API by default) — documented, but a risky default for a self-hosted tool that might be port-forwarded
- !No rate limiting mentioned or visible in the API routes, which matters for the hydrometer ingest endpoint that could receive high-frequency POSTs
Code quality
The architecture is well-thought-out: clean separation between db/schema, lib/business logic, and components. The phase engine and reference-data modules are solid TypeScript with real domain modeling. However, queries.ts has a recurring pattern of manual SQL IN-clause construction (sql.join(batchIds.map(...))) that bypasses Drizzle's inArray() helper — this is fragile and inconsistent with ORM usage elsewhere. Error handling in settings components is thin: handleToggleActive and handleDelete in HydrometerManager do bare awaited fetches with no .catch() or user-facing error states. The StepProtocol wizard component is very long (~500+ lines) and manages significant drag-and-drop state that could be extracted.
What makes it unique
There are existing open-source fermentation trackers (Fermentrack, Brewfather's self-hosted alternatives, BrewPi), but Ferment's specific combination of Next.js App Router architecture, Drizzle+SQLite simplicity, and Home Assistant MQTT auto-discovery as a first-class feature is reasonably differentiated. It's not reinventing the wheel, but it's a cleaner, more modern tech stack than most incumbents and targets a slightly different self-hosting audience (Docker one-liner vs. Raspberry Pi image flashers).
Scores
Barrier to entry
mediumThe project has a CONTRIBUTING.md, CI, Dockerfile, and clean folder structure, but zero tests, a single 1-commit history, no labeled issues, no good-first-issue tags, and no community — a contributor would need to self-direct entirely.