- Ruby 61.4%
- HTML 18.2%
- CSS 15.2%
- JavaScript 4.7%
- Dockerfile 0.4%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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> |
||
| .claude/agents | ||
| bin | ||
| config | ||
| db | ||
| docs | ||
| lib | ||
| migrations | ||
| public | ||
| test | ||
| views | ||
| .dockerignore | ||
| .gitignore | ||
| .herb.yml | ||
| .woodpecker.yml | ||
| app.rb | ||
| config.ru | ||
| Dockerfile | ||
| Gemfile | ||
| Gemfile.lock | ||
| mise.toml | ||
| Rakefile | ||
| README.md | ||
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).