No description
  • Ruby 61.4%
  • HTML 18.2%
  • CSS 15.2%
  • JavaScript 4.7%
  • Dockerfile 0.4%
  • Other 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
whysthatso 0766d22edd Trip cost calculator: per-person and total trip costs from the car's averages
GET /cars/:id/trip shows lifetime consumption, the price of the last fill-up and
other costs per km (purchase price + expenses over the km driven); distance and
people are entered and the amounts computed live in the browser.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 18:48:25 +03:00
.claude/agents Phase 0: plan, legacy data snapshot, agent definitions 2026-09-28 22:53:32 +03:00
bin infrastructure changes 2026-09-29 11:01:44 +03:00
config Code review fixes, tests first, plus README and plan updates 2026-09-29 01:27:55 +03:00
db remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00
docs Trip cost calculator: per-person and total trip costs from the car's averages 2026-10-05 18:48:25 +03:00
lib Trip cost calculator: per-person and total trip costs from the car's averages 2026-10-05 18:48:25 +03:00
migrations remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00
public Trip cost calculator: per-person and total trip costs from the car's averages 2026-10-05 18:48:25 +03:00
test Trip cost calculator: per-person and total trip costs from the car's averages 2026-10-05 18:48:25 +03:00
views Trip cost calculator: per-person and total trip costs from the car's averages 2026-10-05 18:48:25 +03:00
.dockerignore remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00
.gitignore Phase 0: plan, legacy data snapshot, agent definitions 2026-09-28 22:53:32 +03:00
.herb.yml infrastructure changes 2026-09-29 11:01:44 +03:00
.woodpecker.yml infrastructure changes 2026-09-29 11:01:44 +03:00
app.rb Trip cost calculator: per-person and total trip costs from the car's averages 2026-10-05 18:48:25 +03:00
config.ru Phase 1: scaffold and red test suite 2026-09-28 23:43:05 +03:00
Dockerfile infra fixes 2026-09-29 11:52:06 +03:00
Gemfile remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00
Gemfile.lock remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00
mise.toml Phase 1: scaffold and red test suite 2026-09-28 23:43:05 +03:00
Rakefile remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00
README.md remove importer, move around migrations to accommodate container mount directory 2026-09-29 11:12:00 +03:00

Tankbuch

Tankbuch is a small single-user web app (Sinatra, Sequel, SQLite, Alpine.js) for recording fuel fill-ups and other car expenses and for showing lifetime statistics per car. The root URL opens a phone-first fill-up form: odometer, litres, total, brand and fuel chips with the last values preselected, live price per litre and consumption while typing, and a "TANK FULL" confirmation after saving. Each car has a dashboard with cost of ownership, mileage, litres, fuel cost, lifetime consumption (tank to tank), weighted price per litre, cost per km, a cost split, a by-year table, the fuel cost of the last twelve months, the current odometer with a check-in, and the recent fill-ups. It replaces a spreadsheet whose history was imported once. It runs on a private network without login. The full specification, including every formula, is in docs/PLAN.md.

Setup

Ruby 4.0.1 comes from mise (mise.toml). Install the gems, migrate and start the server:

bundle install
APP_ENV=production bundle exec rake db:migrate
APP_ENV=production bundle exec rake server

Then open http://<host>:9292/ on the phone. rake server migrates before it starts Puma, so the second line is optional.

Environments and settings

Variable Default Meaning
APP_ENV development (or RACK_ENV) production for the LAN instance. In development Sinatra only accepts requests addressed to localhost, so phones on the LAN get 403.
DATABASE_URL sqlite://<project>/db/<env>.sqlite3 Any Sequel URL. Tests always use an in-memory database.
PORT, BIND 9292, 0.0.0.0 Puma listen address.
PERMITTED_HOSTS unset (any host) Comma-separated host names to restrict Host headers, e.g. tankbuch.lan.

There is no authentication. Cross-site form posts are rejected (a foreign Origin header gets 403). Behind a TLS reverse proxy forward X-Forwarded-Proto and keep X-Forwarded-For consistent with any X-Real-IP, otherwise the same protection rejects your own posts.

Database and Syncthing

The SQLite database lives in the project at db/<env>.sqlite3 (git-ignored); db/production.sqlite3 is the one the LAN instance uses. Set DATABASE_URL to use another location. The project sits inside a Syncthing folder whose root is ~/syncthing/projects (the directory with .stfolder), so create or extend ~/syncthing/projects/.stignore with a pattern relative to that root:

whysthatso/apps/tankbuch/db/*.sqlite3*

This keeps Syncthing from syncing the live database and its -journal files mid-write. Back the database up by copying db/production.sqlite3 while the server is stopped, or with sqlite3 db/production.sqlite3 ".backup backup.sqlite3".

Imported data

The history from the old spreadsheet was imported once into db/production.sqlite3; the importer has since been removed. Imported rows have source = import and an import_ref like Multivan diesel!40, carry a note for each data correction made during the import, and show an "Imported" badge. They may lack a brand or an odometer reading. Edit them in the history view like any other entry.

Tests

bundle exec rake test              # the whole suite
bundle exec rake test:backend      # models, statistics, formatting
bundle exec rake test:frontend     # templates and assets
bundle exec rake test:routes       # the web layer through rack-test

The statistics tests pin every number of a small fixture car.

Layout

app.rb                     routes
config/                    boot (database, Money configuration), Puma
migrations/                cars, fill_ups, expenses
lib/tankbuch/              models, stats, units, format, view helpers
views/                     ERB templates and shared partials
public/                    stylesheets (design tokens, base, layout, components), Alpine components,
                           vendored Alpine.js 3.17.4 (MIT) and the Pixelify Sans, Space Grotesk and
                           Space Mono fonts (SIL Open Font License, see public/fonts/OFL.txt)
test/                      minitest suite
docs/PLAN.md               specification

Money is handled with the money gem (EUR, half-up rounding) and stored as integer cents; volumes are integer millilitres. Numbers are shown with a narrow no-break space as thousands separator and the unit after the value (6 692.43 €, 44 638 km, 9.18 l/100km).