Heatwave
E-commerce platform for WarmlyYours radiant heating products. Built
with Ruby on Rails 8.1, PostgreSQL 18, and Bootstrap 5.3.
📚 Generated docs site: docs.warmlyyours.dev
— full YARD reference for app/ and lib/, project conventions,
architecture docs, and the agent skills library. Rebuilt on every
push to master.
Quick Start
# 1. Clone
git clone git@github.com:warmlyyours/heatwave.git
cd heatwave
# 2. One command. Installs the pinned toolchain (Ruby/Node/Python/uv via mise),
# gems, JS deps, the Docker Postgres/Redis cluster, local TLS, and
# config/database.yml — then, when 1Password is unlocked, writes
# config/master.key + .env.mcp. Prepares the dev database once
# config/master.key + config/database.yml exist.
bin/setup
# 3. Start the dev server
mise exec -- bin/dev
Two prerequisites
bin/setupcan't install for you: Homebrew (it
bootstraps everything else, including mise), and 1Password — the desktop
app with Settings → Developer → Integrate with 1Password CLI enabled, signed
into WarmlyYours with access to vault IT. With those,bin/setupalso
pullsconfig/master.keyand populates.env.mcp(config/database.ymlis
generated regardless). It then prepares the dev database whenever
config/master.key+config/database.ymlare present. If 1Password is locked
it skips the secret fetches and says so — unlock it and re-runbin/setup
(idempotent), or addconfig/master.keyand runmise exec -- bin/rails db:prepareby hand.
URLs
All Ruby / Node / Yarn commands run via
mise exec --. Bare
commands pick up the wrong system-installed toolchain. See
AGENTS.md for the full toolchain non-negotiables.
Project Structure
heatwave/
├── app/ Rails application (controllers, models, views, services, javascript)
├── client/ Webpack frontend (JS / SCSS)
├── config/ Rails + environment config
├── db/ Migrations, seeds, structure.sql, scenic views
├── doc/ Curated long-form docs (architecture, features, ops, …)
├── .agents/skills/ Agent skill packs (agentskills.io spec) — also surfaced on the docs site
├── script/ Utility scripts (MCP setup, IDE setup, validators)
├── test/ Minitest test suite
├── AGENTS.md Toolchain rules + hard-block commands for AI agents
├── CLAUDE.md Symlink → AGENTS.md (Claude Code reads this)
└── CONVENTIONS.md ERP YARD + Markdown documentation conventions
Documentation
- 📖 Documentation Index — hand-curated TOC of every doc subdirectory
- 📐 CONVENTIONS.md — YARD + Markdown style for Ruby docstrings
- 🤖 AGENTS.md — toolchain, hard-block commands, code-deletion safety, migration safety, Zeitwerk rules, git commit technique. Required reading if you wire up any AI tooling against this repo.
- 🌐 docs.warmlyyours.dev — generated reference site (YARD + curated
doc/markdown +.agents/skills/)
Essential reading
| Document | What's in it |
|---|---|
| Skills index | Code conventions, organized by area (Rails, Hotwire, infra, etc.) |
| Commit Conventions | Commit type/scope taxonomy |
| API & integration testing | Minitest workflow + COVERAGE=1 |
| System tests | Playwright system-test suite |
| Safe migrations | online_migrations + structure.sql |
By topic
- Development: doc/development/
- Frontend: doc/frontend/
- Architecture: doc/architecture/
- Features: doc/features/
- Infrastructure: doc/infrastructure/
- Integrations: doc/integrations/
- Deployment: doc/deployment/
- Operations: doc/operations/
- Troubleshooting: doc/troubleshooting/
- Skills (agent + human reference): .agents/skills/
Per-deploy changelogs are tracked via GitHub releases and PR
descriptions. Don't add files under adoc/changelog*directory
— for durable engineering narratives, file under the rightdoc/
topic folder with a descriptive name. For staged work and follow-up
plans, usedoc/tasks/with theYYYYMMDDHHMM_NAME.md
timestamp convention.
AI Agents (MCP, skills, .claude)
Agent context is the same across Claude Code, Aider, and OpenAI Codex
CLI:
AGENTS.mdis the canonical instruction file
(agents.md convention).CLAUDE.mdis a
symlink to it..agents/skills/holds 82+ first-party skill
packs (Agent Skills spec) plus any vendored
third-party skills tracked inskills-lock.json..claude/skills
is a symlink →../.agents/skills.
MCP servers
Single source of truth: .mcp.json (committed),
populated from 1Password by script/setup_mcp_servers.sh. See
.agents/skills/mcp-servers for the active
server list and per-environment access rules.
Worktree workflow
bin/wt <branch-name> bootstraps a per-branch worktree at
../heatwave_worktrees/<branch> with the right symlinks for
credentials, env files, and the shared docker volume.
Native System Dependencies
Some gems require native C libraries — install before bundle install.
| Library | Purpose | macOS | Ubuntu / Debian |
|---|---|---|---|
zint |
Vector barcode + QR generation (ruby-zint, hexapdf-extras) |
brew install zint |
sudo apt install zint |
libvips |
Image processing — resize, format convert, PDF raster (ruby-vips, dragonfly_libvips, phash-rb) |
brew install libvips |
sudo apt install libvips-dev |
librsvg |
SVG rasterization (used by libvips) | brew install librsvg |
sudo apt install librsvg2-2 |
poppler |
PDF rendering (used by libvips for PDF thumbnails) | brew install poppler |
sudo apt install poppler-utils |
macOS: All four are in
Brewfile—brew bundlecovers it.Ubuntu / production: baked into the production Docker image (see
Dockerfile). The containerized deploy stack lives under
doc/infrastructure/kamal/.
Prerequisites & remaining manual steps
bin/setup handles the toolchain, dependencies, the Docker cluster, local TLS,
and config/database.yml — and, when 1Password is unlocked, config/master.key
and .env.mcp. What it can't do for you:
- Homebrew — install first;
bin/setupaborts without it. - 1Password CLI integration — desktop app → Settings → Developer →
Integrate with 1Password CLI, signed into WarmlyYours (vaultIT). Without
it the secret fetches are skipped; addconfig/master.keyby hand (IT vault
→heatwave-master-key) and re-runbin/setup --refresh-mcp. - GitHub SSH key — generate ed25519.
- Tailscale VPN — required for any deploy, server SSH, or admin-dashboard access.
- Server SSH access — add your public key to the production hosts.
- Database with real data (optional) —
bin/setup --restore-dbinstead of
the emptydb:prepareschema.
See the development setup troubleshooting guide
for common issues.
Tech Stack
| Component | Version | Notes |
|---|---|---|
| Ruby | 4.0.5 | Pinned via mise. YJIT enabled in all environments incl. dev — see config/initializers/000__yjit.rb |
| Rails | 8.1.3 | |
| Node.js | 24.8.0 | Pinned via mise |
| Yarn | 4.x | Via Corepack |
| Python | 3.12 | For MCP servers (postgres-mcp, etc.) |
| PostgreSQL | 18 | Via Docker (heatwave-postgres:18-noble) |
| Bootstrap | 5.3 | |
| Font Awesome | 7 Pro | |
| Sidekiq | 7.x | Background jobs |
Questions? Check the Documentation Index
or the generated docs site.