Skip to content

FlavioAdamo/openfit

Repository files navigation

OpenFit app icon

OpenFit

OpenFit is a private, desktop-first Electron dashboard for Google Fitbit Air and other Fitbit devices. Its adaptive interface prioritizes a small set of useful insights and only displays views, metrics, and navigation when Google Health returns real data.

OpenFit desktop dashboard screenshot

The renderer uses React, shadcn/Radix, Tailwind CSS v4, assistant-ui, Inter Variable, JetBrains Mono, and Nucleo Essential Outline icons.

Project status: the application is complete and buildable. Demo mode works without configuration. Accessing personal data requires an OAuth client in your own Google Cloud project.

How Fitbit data reaches OpenFit

Fitbit Air does not provide a public Bluetooth synchronization interface for third-party applications. The supported data path is:

Fitbit Air -> Bluetooth -> Fitbit/Google Health mobile app
                                  |
                                  v cloud sync
                         Google Health API -> OpenFit

OpenFit uses Google Health API v4 as its default provider. The legacy Fitbit Web API remains available only as a transitional adapter and is scheduled for deprecation in September 2026.

The desktop application can replace the browsing and analysis experience, but it cannot perform initial device pairing, firmware updates, or phone-to-device synchronization.

Quick start

Requirements:

  • Node.js 22 or later;
  • npm 10 or later;
  • Codex Desktop and a signed-in Codex account, only if you want to use the health assistant. OpenFit reuses the local login and does not require an API key.
npm install
npm run dev

Useful commands:

npm run build       # Type-check and bundle the renderer
npm test            # Run normalizer and adapter tests
npm run capture:ui  # Run desktop/mobile visual QA in Electron Chromium
npm run dist        # Package the app for macOS, Windows, or Linux

Packages generated locally in release/ are unsigned unless an Apple Developer ID certificate is available in the Keychain. For public distribution, follow the release checklist.

Connect Google Health

Before you begin

You need:

  • the Google account used by the Fitbit mobile app;
  • access to Google Cloud Console;
  • Fitbit Air or another supported tracker already paired and synchronized with the Fitbit app;
  • OpenFit running with npm run dev or as an installed desktop application.

API configuration, OAuth consent, and OAuth credentials must all belong to the same Google Cloud project.

1. Create a Google Cloud project

  1. Open Create a Google Cloud project.
  2. Name the project OpenFit.
  3. For a personal account, leave Organization set to No organization.
  4. Create the project and select it from the project picker.

2. Enable Google Health API

  1. With the OpenFit project selected, open Google Health API.
  2. Click Enable.
  3. Wait until the page shows that the API is enabled or displays Manage.

3. Configure the OAuth consent screen

  1. Open Google Auth Platform and click Get started.
  2. Set the application name to OpenFit and enter a support email.
  3. Select External as the audience. Internal only supports accounts in the same Google Workspace organization.
  4. Enter a contact email and complete the setup.
  5. Open Audience, add the Google account used by Fitbit as a test user, and save it.

While the application remains in OAuth testing mode, only explicitly listed test users can authorize it. Google normally expires refresh tokens for external applications in testing after seven days; reconnect the account when needed or complete Google's production requirements.

4. Add read-only scopes

Open Google Auth Platform scopes, choose Add or remove scopes, and add these read-only Google Health scopes:

https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
https://www.googleapis.com/auth/googlehealth.ecg.readonly
https://www.googleapis.com/auth/googlehealth.irn.readonly
https://www.googleapis.com/auth/googlehealth.location.readonly
https://www.googleapis.com/auth/googlehealth.nutrition.readonly
https://www.googleapis.com/auth/googlehealth.profile.readonly
https://www.googleapis.com/auth/googlehealth.settings.readonly
https://www.googleapis.com/auth/googlehealth.sleep.readonly

Do not add write scopes. OpenFit also requests the standard openid and profile scopes to display the account name and avatar.

5. Create the OAuth client

  1. Open Google Auth Platform clients.

  2. Create an OAuth client of type Web application.

  3. Name it OpenFit Desktop.

  4. Leave Authorized JavaScript origins empty.

  5. Add this exact Authorized redirect URI:

    http://127.0.0.1:42813/oauth/callback
    
  6. Create the client and retain its Client ID and Client Secret.

Do not commit or share these credentials. During authorization, OpenFit starts a temporary loopback server on port 42813, validates OAuth state and PKCE, receives the authorization code, and then closes the server.

6. Connect OpenFit

  1. Start OpenFit.
  2. Click Connect Fitbit and select Google Health.
  3. Paste the Client ID and Client Secret.
  4. Confirm that the callback URL is http://127.0.0.1:42813/oauth/callback.
  5. Click Save and connect.
  6. In the system browser, select the same Google account that you added as a test user and approve the requested access.
  7. Return to OpenFit. The first synchronization starts automatically.

The connection is working when OpenFit shows Google Health instead of Demo mode, displays a last synchronization time, and begins showing real device and health metrics. Metric availability depends on the device, region, granted consent, and recent Fitbit mobile synchronization.

Security note

The Client Secret, OAuth tokens, and health cache stay in Electron's main process and are encrypted with safeStorage using Keychain on macOS, Credential Manager on Windows, or an available secret store on Linux. They are not exposed to the renderer or written to the repository.

A Client Secret distributed in a desktop binary is not a durable global secret. The current setup is appropriate for personal use and development. A public release should move the OAuth code exchange to a small backend and complete Google's verification and security-review requirements.

Troubleshooting

redirect_uri_mismatch

  • Register http://127.0.0.1:42813/oauth/callback exactly. Do not use localhost, omit the path, or add a trailing slash.

Access blocked, access_denied, or unauthorized user

  • Confirm that the OAuth audience is External.
  • Add the correct account under Audience -> Test users.
  • Sign in with the same account used by the Fitbit app.

invalid_client

  • Copy the Client ID and Client Secret again from the same OAuth client.
  • Remove accidental leading or trailing spaces.
  • Do not mix credentials from different Cloud projects.

HTTP 403 or API not enabled

  • Confirm that Google Health API is enabled in the same project as the OAuth client.

Port 42813 is already in use

  • Close other OpenFit processes and retry. Only one OAuth flow can use the callback port at a time.

Some metrics are missing

  • Open the Fitbit app on the phone and wait for the tracker to synchronize.
  • Return to OpenFit and click Sync.
  • ECG, SpO2, skin temperature, HRV, and irregular-rhythm notifications may not be available for every device, account, or country. OpenFit hides sections for which no data exists.

For a longer checklist, see Google Health setup.

Project structure

electron/
  main.cjs                    Electron shell, OAuth loopback, IPC, encrypted storage
  preload.cjs                 Minimal typed IPC bridge
  codex-service.cjs           Read-only Codex app-server JSONL client
  google-health-service.cjs   Google Health API v4 provider
  fitbit-legacy-service.cjs   Legacy Fitbit Web API provider with PKCE
src/
  components/                 Views, charts, and assistant-ui chat
  data/                       Demo data and provider-independent normalization
  lib/                        Formatting and pure utilities
  App.tsx                     UI and connection-state orchestration
  types.ts                    Shared renderer/preload contracts
scripts/
  capture-ui.cjs              Electron visual smoke test
docs/
  ARCHITECTURE.md             System decisions and boundaries
  DATA_COVERAGE.md            Data coverage and limitations
  GOOGLE_HEALTH_SETUP.md      Extended OAuth setup guide
  RELEASE.md                  Signing, notarization, and release process

See Architecture for security boundaries and design decisions.

Interface principles

  • one primary metric per screen, with secondary details ordered by importance;
  • no empty cards: unavailable sections remain hidden;
  • one accent color for status, progress, and actions;
  • aggregated intraday samples for responsive charts without changing minimum, maximum, or latest values;
  • accessible shadcn/Radix components and responsive layouts without horizontal overflow.

Health assistant

The chat button in the top bar opens a right-side panel built with assistant-ui primitives. Its bridge uses codex app-server, the same local interface used by Codex clients, with a read-only sandbox, approvals disabled, and tool calls denied by default.

When you send a message, OpenFit creates a compact context containing normalized metrics, available dates, and details for the selected day. It does not include OAuth credentials or encrypted files. This context is sent to Codex/OpenAI only after you use the chat. Codex may navigate to an OpenFit view or date, but it cannot modify health data.

No Codex model name is hard-coded in this repository. The app-server selects its configured default model unless a model is supplied programmatically through the service options.

Official references

Icons: Nucleo Essential Outline (c) Nucleo, used under the Nucleo license.

The information displayed by OpenFit is not a diagnosis or medical advice.

About

Desktop dashboard and Codex-powered assistant for Fitbit data

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors