Polymeter Metronome and Practice Trainer

an example of Sustainable Software

Try it: https://metronome.varasys.io · This page on the web: https://metronome.varasys.io/README.html · Source: https://codeberg.org/VARASYS/metronome


Part 1 — Sustainable software

This app is small, and it works — but that is not really the point of it. The point is to show that software can be built to respect the people who use it, and that almost every annoying, extractive, or manipulative thing you have come to expect from an app is a choice, not a law of nature. Here is every way this one is built differently, in plain terms — on the left, what the software industry would tell you to do; on the right, what this app does instead. It is a demo, so every row is a real, working feature you can check for yourself.

It's yours, and it stays yours

What most apps doWhat this app does
Make you sign up first — an account before you can touch anything, so you can be tracked and emailedNo account, ever — open it and start; there is nothing to sign up for
Keep your stuff on their servers — where they can mine it, and where you can't just take it and leaveYour stuff stays on your device — your settings and history live in your own browser, uploaded nowhere
Route sharing through their system — so a share needs their account and passes through their serversSharing is just a link — the link itself carries the whole thing; no account on either end
Sync your data to their cloud — in a form they can read, so a copy of you becomes theirsSync goes to a place you choose — scrambled on your device first, to a store you own, so it stays gibberish to everyone else
Trap your work in a private format — one only their app can open, that becomes unreadable the day the app diesYour work is plain, readable text — an open format any program can read, today or in twenty years
Make leaving painful — no export, a buried "delete", a cancellation mazeLeaving is one tap — take your data with you as a link or a file, whenever you like

No tricks, no toll booths

These manipulations even have a name — dark patterns: tricks deliberately built into an app to get you to do something you didn't mean to. They are not accidents or sloppiness; they are designed, by people paid to design them. This app simply refuses to use them.

What most apps doWhat this app does
Watch everything you do — tracking on by default, and the data sold to whoever paysNo analytics at all — the app never phones home; there is nothing to collect and nothing to opt out of
Show ads and farm your attention — because if it's free, you are the productNo ads, nothing sold — you are the user, not the product
Nag and guilt-trip you — pop-ups until you give in, and a "no" button that shames you for clicking itNever nags — it just opens and works; no interruptions, nothing to click past
Bill you forever — a subscription, or a "free" trial that quietly starts chargingFree, with nothing to cancel — no subscription, no trial, no bill

Built to outlive us

What most apps doWhat this app does
Rot from the inside — built on a tower of other people's code that breaks when any one piece changesOne small self-contained file — nothing outside it to break; it should still open in a browser decades from now
Die when the company does — it needs their servers running, and vanishes when the money dries upCannot be shut down — no servers to keep alive, and the code is public, so anyone can keep it going
Demand to be online — a constant connection, so they can keep watching and gating youWorks offline, forever — add it to your phone straight from the web (no app store), and after that the network is optional
Bloat until your device is "too old" — pushing perfectly good hardware into the landfillRuns on almost anything — an old phone, or a $4 chip; it asks so little that hardware lasts longer

Two ways to bring your own data

Out of the box your practice log is kept in your browser's own storage on the device you used, and goes nowhere else. If you want the same log on your phone and your laptop, sync never sends it to this project — it goes to a store you pick. There are two kinds, for two kinds of people:

Sustainable isn't magic

Honesty is part of the point, so here are the trade-offs. The built-in demo sync store is deliberately throwaway — it can reset after a day. That is not a flaw to apologise for; it is what a demo is. The sustainable part is that you can point sync at a store you own and never depend on this project at all. And keeping no analytics has an honest cost: the project genuinely cannot see what people find confusing or where they give up, so the only way an awkward corner ever gets fixed is if someone says so. That is the trade for never watching you — and it is one worth making.

"No analytics" — the honest fine print

The app on your device sends nothing: no trackers, no cookies, and it never phones home, so the copy you save behaves exactly like the hosted one. The only record a visit leaves is on the web server — the same kind of access log every website has kept for thirty years — and it is deliberately minimal. Before a single line is written, your IP address is blunted to a /24 (the last part is zeroed, so 66.234.152.199 is stored as 66.234.152.0, and an IPv6 address to a /48); no full address is ever saved. Each line records only the time, that masked address, which page was requested, and the bare mechanics of it (method, protocol, response status, the size of the request and its response, and how long it took). It does not record your browser's User-Agent, the site you came from (the Referer), any cookies, or the connection's encryption details — those are discarded before writing, so they exist in no file, journal, or backup. Your shared tracks and set lists ride in the part of a link after the #, which browsers never send to any server, so your patterns never reach the log at all. The detailed lines are deleted after 30 days; the only thing that outlives them is a plain running count — how many page views and how many downloads there have been, sampled every minute or so and not broken down by page. It carries nothing about who or what: no address (not even the masked one), no page, and no way to tell one visitor from another or to link two visits. That count is kept for about a year, so the project can answer "is anyone still using this?" without keeping anything about anyone. It is the reverse of how most analytics work: here the bare aggregate is what is kept for a while, and everything that could identify a request is thrown away fast — keeping the number is precisely what lets the records be deleted.

Don't take our word for it — here is the site's entire logging configuration, copied straight from the running server. ip_mask rewrites both IP fields to a /24 (IPv6 /48) inside the encoder, so the full address is destroyed before the line is written — not stored-then-anonymised, simply never written. The four delete lines drop the client port, the entire request-header map (that is what removes User-Agent, Referer and any cookie — not a blocklist but the whole map, so even a header nobody has heard of cannot leak), the TLS details, and every response header. output stdout sends the line to the service journal, which expires it after 30 days.

# metronome.<domain> -- the site's entire access-log configuration
log {
    output stdout
    format filter {
        wrap json
        fields {
            request>remote_ip ip_mask {
                ipv4 24
                ipv6 48
            }
            request>client_ip ip_mask {
                ipv4 24
                ipv6 48
            }
            request>remote_port delete
            request>headers delete
            request>tls delete
            resp_headers delete
        }
    }
}

Two footnotes so a sharp reader can't catch us out: this is the per-site block — the surrounding config only sets up HTTPS and static-file serving, neither of which logs anything; and while request>headers delete removes the Host header from the log, request.host is recorded as a separate field, which is just which site was asked for (always this domain) and says nothing about you. The block is a snapshot of infrastructure maintained outside this repo; by standing agreement it is updated here whenever the masking, deletion, or retention changes there.


Part 2 — What it actually does

Underneath all of that, it is a genuinely flexible metronome. Set a tempo and it clicks — but you can also stack up several rhythms at once, each with its own beat pattern, subdivision and drum sound, to practise polyrhythms and odd time signatures an ordinary metronome can't handle. Add a guitar, ukulele, bass, piano or harmonica on top, each one showing the chord or scale you're working on.

Press Practice and it quietly logs the session — your tempo, your notes — so you can pick up exactly where you left off. Arrange your favourite grooves into set lists, step through them, and share any of it as a plain link. It adds to your phone or desktop like a normal app and keeps working with no connection at all.

Older experiments — the desktop editors and the hardware form-factor prototypes — are still tucked in the app's menu, kept only as a record of how this final version came to be.


Part 3 — How it's built (for the technically minded)

This part is for developers and the curious — skip it if that's not you; nothing above depends on it.

Every deployed page is one self-contained .html file with zero runtime dependencies. build.sh inlines a shared engine, the seed set lists, base styling and the brand assets into each page; it asserts that no build markers survive, so what ships is fully offline-capable. Even this page is proof: the Markdown you're reading is rendered to README.html by a tiny Markdown renderer inside build.sh — no library, no dependency.

./build.sh          # assemble the self-contained pages into dist/ (git-ignored)
./deploy.sh         # build, stamp version, mirror dist/ to the Caddy web root
node tests/run.mjs  # track-format conformance suite (the cross-implementation contract)

The public site deploys on git push to main (a CI job builds and refreshes the origin). main is the canonical home of the whole project — the app, the galleries, the firmware, the tests and docs. The concepts branch keeps only the hardware design work (KiCad / SPICE / wokwi).

License

GNU AGPL v3 © VARASYS · Simplifying Complexity.