Last updated: 6 May 2026

Privacy policy

Indoor Bike stores everything on your device. We don't run a server, we don't have analytics, we don't have accounts. The only time data leaves your phone is when you explicitly ask it to: uploading a ride to a third-party service you've configured, or sharing a workout file.

This page describes, in plain language, exactly what the Indoor Bike Android app and the indoorbike.app website do with data. It applies to the version of the app and site published at the date above. If anything changes materially, we'll update the date and call out the change in the project's release notes.

The Android app

What's stored on your device

All of the above lives in the app's private storage on your phone. No account, no cloud sync, no server-side copy. Uninstalling the app removes everything.

What goes over Bluetooth

The app speaks the standard Bluetooth Low Energy FTMS (Fitness Machine Service) profile to your trainer, the standard Heart Rate Service to a heart-rate monitor, and a vendor service to a Zwift Click controller where applicable. Communication is point-to-point with your devices. It doesn't go to a server.

Permissions the app requests

The app is built without Google Play Services, Firebase, Crashlytics, or any analytics SDK. The only external network connections it can make are the ones you explicitly initiate (workout / repository imports, and the optional integration described next).

Optional Intervals.icu sync

Intervals.icu is a third-party training analytics service. The integration is off by default. If you enable it in Settings → Cloud sync, the app:

Once a ride is uploaded, the data is governed by Intervals.icu's own privacy policy. Disabling the integration in Settings clears the credentials and stops further uploads; rides already uploaded stay with intervals.icu unless you delete them there.

The website

indoorbike.app is a static site. There is no backend, no database, no account system, and no analytics. The site does not set first-party cookies. The bullets below describe each page's data behaviour.

Browsing the homepage and community pages

Loading any page transmits only the standard HTTP request headers your browser sends to any website (IP address, User-Agent). The static-site host's server logs may retain these for an operator-defined period to detect abuse; we don't ingest, aggregate, or analyse those logs for product purposes.

The community browser (/community/) fetches static JSON files: /registry.json on first load, then each repository's manifest when you click into it. These are normal HTTPS GETs to the same site or to whichever host the repository's manifest lives on. No data about your visit is sent to those hosts beyond what the request itself carries.

The workout editor

The editor is fully client-side. The workout you build is saved to your browser's localStorage under a key the editor owns (indoorbike.editor.workout.v1) and your FTP setting under indoorbike.editor.ftp.v1. Both stay on your device; the editor does not transmit them anywhere. Clearing site data in your browser removes them.

When you generate a share link or QR code, the workout is encoded into the URL itself as a hash fragment (#wz=…). Browsers never send the hash fragment to the server, so the receiving page can decode the workout entirely client-side. The editor's "Send to phone" feature uses the browser's standard share API; the file is handed to whichever app you select. No copy goes through us.

The /share/ page

Visiting a share link with a workout in the URL means your browser decodes the workout from the hash fragment and renders it. As above, the hash fragment never leaves your browser. The "Send to Indoor Bike" button uses the browser's share API; the file is offered to your installed apps and never returns to us.

Third-party assets we load

The website pulls in a small number of static assets from public CDNs. Loading them causes your browser to make a request directly to those hosts; their privacy and logging policies apply to those connections. We don't add tracking parameters or send any custom data with the requests.

We may self-host these in a future release to remove the dependency altogether.

Cookies, tracking, advertising

None. The site does not set first-party cookies. There is no advertising, no fingerprinting, no analytics, no A/B-test framework. The hosting provider may set technical cookies for protocol-level reasons (e.g. CDN routing); these are operational and not used for any product purpose by us.

Children

The app and site are not directed at children under 13. We don't knowingly collect data from anyone, of any age. See above.

Changes to this policy

Material changes will be reflected by updating the "Last updated" date at the top and called out in the app's and website's release notes. Past versions of this policy are visible in the project's git history on Codeberg.

Contact

For privacy questions or data-related requests, the fastest route is to open an issue on the project's Codeberg repository. Sensitive matters can be flagged in a private issue.