Capgo is a free, open source build & deployment project written in TypeScript and released under AGPL-3.0. It has 212 GitHub stars, 134 forks and 41 open issues, and was last pushed 10 hours ago. On this registry it ranks #84 of 84 tracked projects in Build & Deployment, with 5 head-to-head comparisons available. It gained 4 stars over the last 30 tracked days.

What is Capgo?

Capgo is an open-source console and updater for shipping over-the-air bundle updates to Capacitor apps on Android and iOS, built for mobile teams that need to release fixes without waiting on app store review.

What it is

Capgo is a TypeScript project in the Capacitor ecosystem, published under the AGPL-3.0 licence and tagged for android, capacitor, cordova, and ios. It provides a console to manage and distribute live updates, an updater plugin that the app consumes, and an open-source backend that can be installed in your own infrastructure. The console covers bundle management — download, assign to channel, rollback — together with channel support for different environments, automatic updates, delta updates, and update encryption and signing. It supports Capacitor 8, 7, 6, and 5, on both Android and iOS.

The concrete problem is release latency: a fix that is ready today still waits for app store review before users receive it. Capgo replaces Ionic Appflow for this job — the README describes the Capacitor updater plugin as "the official alternative to Ionic Appflow." Teams that adopt it can run the hosted service at capgo.app or self-host the backend, rather than routing every live update through a commercial vendor.

Key capabilities

  • Bundle management: download bundles, assign them to a channel, and roll back.
  • Channel support for managing different environments, including setting a channel on a specific device to QA or debug one user.
  • Auto update, which automatically downloads and sets the latest bundle for the app.
  • Rollback that resets the app to the last working bundle when an incompatible bundle has been set.
  • Delta updates that download only the changed files to make updates instant.
  • Security through encryption and signing of each update.
  • Deployment statistics for viewing how a release is rolling out.

Who uses it and how

  • The README reports use in more than 3000 projects, with the production Capgo deployment operating at a scale of roughly 50M devices.
  • Teams running staging, QA, and production builds use channels to keep environments separate.
  • QA and support workflows set a channel on one specific device to debug a single user without touching the wider rollout.
  • Projects shipping frequent small changes rely on delta updates so only changed files are transferred.
  • Release engineering uses rollback as the safety net when a bundle turns out to be incompatible.

Getting started

Use the hosted Cloud service at capgo.app, or self-host the backend from the Cap-go/capgo repository, where installing only Supabase is sufficient.

How it compares

The named competitor is Ionic Appflow, which the README positions the Capacitor updater plugin against. Capgo is AGPL-3.0 open source, and its backend can be installed in your own infrastructure, whereas Appflow is a commercial hosted service. Self-hosting means the bundles and update traffic stay on your own Supabase instance, and the cloud option is offered directly rather than being the only path.

When to use it — and when not to

Self-hosting requires operating Supabase as the required backend piece; the production deployment also runs Cloudflare Workers, which carry 99% of traffic, through the Hono adapter. Teams not building on Capacitor should look elsewhere, since the updater is Capacitor-specific. Note that the AGPL-3.0 licence carries copyleft obligations worth reviewing, and the repository currently holds 41 open issues.

project readme (upstream, from github) — read inline

Console to manage and distribute your live update

Capgo - Instant updates for capacitor

Bugs Security Rating Maintainability Rating Code Smells Lines of Code Technical Debt Reliability Rating Duplicated Lines (%) Vulnerabilities CodSpeed Known Vulnerabilities GitHub license Bump version Build source code and send to Capgo semantic-release Commitizen friendly


➡️ Get Instant updates for your App with Capgo

Missing a feature? We’ll build the plugin for you 💪


Features

  • ☁️ Cloud / Self hosted Support: Use our Cloud to manage your app updates or yours.
  • 📦 Bundle Management: Download, assign to channel, rollback.
  • 📺 Channel Support: Use channels to manage different environments.
  • 🎯 Set Channel to specific device to do QA or debug one user.
  • 🔄 Auto Update: Automatically download and set the latest bundle for the app.
  • ✅ Official Appflow alternative: our Capacitor updater plugin is the official alternative to Ionic Appflow.
  • 🛟 Rollback: Reset the app to last working bundle if an incompatible bundle has been set.
  • 🔁 Delta Updates: Make instant updates by only downloading changed files.
  • 🔒 Security: Encrypt and sign each updates with best in class security standards.
  • ⚔️ Battle-Tested: Used in more than 3000 projects.
  • 📊 View your deployment statistics
  • 🔋 Supports Android and iOS
  • ⚡️ Capacitor 8/7/6/5 support
  • 🌐 Open Source: Licensed under GNU AFFERO GENERAL PUBLIC LICENSE
  • 🌐 Open Source Backend: Self install our backend in your infra

Usage

Capgo is deployed to production on Cloudflare workers and Supabase.

Cloudflare workers take 99% of the traffic. Supabase is used for internal calls, for internal tasks such as CRON jobs that call functions.

When self-hosted, installing only Supabase is sufficient.

Why Cloudflare Workers + Supabase

We support both deployments for practical reasons:

  • Supabase is the legacy backend and the only required piece for self-hosting.
  • Cloudflare Workers runs the same backend code (via the Hono adapter) but is much cheaper at Capgo scale. With ~50M devices, Supabase Edge Functions are cost-prohibitive because they follow AWS pricing. Cloudflare is ~10x cheaper for our traffic profile.

In production, we route most traffic through Cloudflare Workers for cost and scale, while Supabase remains the reference backend and the default for self-hosted deployments. Capgo cloud console and current CLI calls go to the Cloudflare API hosts (VITE_API_HOST / hostApi). Capgo cloud still publishes a small Supabase function allowlist for Postgres pg_net (triggers) and for legacy CLI compatibility via /functions/v1 through 2026-10-28. Self-hosted deployments keep using /functions/v1. Plugin hot paths and other unused Capgo cloud endpoints are not published on Supabase.

Project structure (self-hosting map)

If you're self-hosting, the key pieces live in a few top-level directories:

  • supabase/ - Primary backend for self-hosting
    • supabase/functions/ - Edge functions (Deno) that power the API
      • _backend/ - Core implementation used by both Supabase and Cloudflare
      • public/ - Public API routes used by customers and apps
      • private/ - Internal API routes for the console and ops tooling
      • plugins/ - Plugin endpoints (updates, stats, channel_self, etc.)
      • triggers/ - Database triggers and CRON functions
    • supabase/migrations/ - Database schema and RLS policies
    • supabase/seed.sql - Local seed data for tests/dev
  • supabase/schemas/prod.sql - Production schema dump (reference only)
  • cloudflare_workers/ - Optional Cloudflare Workers deployment (prod traffic)
    • cloudflare_workers/snippet/ - Geo routing for replicas
    • Worker entry points and deploy config live here
  • src/ - Frontend Vue 3 web console (Vite + Tailwind + DaisyUI)
    • src/pages/ - File-based routes
    • src/components/ - Reusable UI components
    • src/services/ - API clients and integrations
    • src/stores/ - Pinia stores
  • sql/ - Raw SQL helpers and maintenance scripts
  • scripts/ - Dev/build scripts used by CI and local tooling
  • tests/ - Backend Vitest tests (run in parallel)
  • playwright/ - Frontend E2E tests
  • docs/ - Extra documentation and guides
  • android/, ios/ - Capacitor native projects (mobile builds)

Quick self-hosting path:

  1. supabase/ is enough to run the backend locally.
  2. src/ is the web console you point to your own backend.
  3. cloudflare_workers/ is only needed if you want to run the Workers layer instead of (or in front of) Supabase.

Backend endpoints (what lives where)

The backend is split by responsibility to keep routes clear and access scoped:

  • supabase/functions/_backend/public/ - Public API exposed to customers. This is the documented API on the website for customers that want to interact with Capgo programmatically (apps, channels, bundles, devices, etc.).
  • supabase/functions/_backend/private/ - Private API used internally. The console (web UI) uses this heavily for admin/ops workflows. It is not publicly accessible. Some UI flows still use the public API where appropriate.
  • supabase/functions/_backend/plugin_runtime/ - Plugin API used by the @capgo/capacitor-updater plugin running inside apps:
    • plugins/updates - device update checks and bundle download flow
    • plugins/stats - upload usage stats from devices
    • plugins/channel_self - allow a device to opt into a channel (QA/debug)
  • supabase/functions/_backend/triggers/ - Triggers & CRON for automated backend jobs (queue consumers, scheduled tasks, DB-triggered flows).

When self-hosting, you generally expose public + plugin_runtime (via the plugin worker / Deno updates · stats · channel_self entries). private should stay internal and locked down. triggers runs automatically.

Production schema (prod.sql)

supabase/schemas/prod.sql is a schema dump of the production database. It is generated via bun run schemas (or bun run schemas:local) and is meant for reference/diffing, not as a source of truth. All actual schema changes live in supabase/migrations/.

Documentation

https://github.com/Cap-go/capacitor-updater/wiki/Capgo-Sandbox-App

Plugins

All the following official plugins are already installed and pre-configured:

  • Action Sheet - Provides access to native Action Sheets.
  • App - Handles high level App state and events.
  • App Launcher - Allows to check if an app can be opened and open it.
  • Browser - Provides the ability to open an in-app browser and subscribe to browser events.
  • Camera - Provides the ability to take a photo with the camera or choose an existing one from the photo album.
  • Clipboard - Enables copy and pasting to/from the system clipboard.
  • Device - Exposes internal information about the device, such as the model and operating system version, along with user information such as unique ids.
  • Dialog - Provides methods for triggering native dialog windows for alerts, confirmations, and input prompts.
  • Filesystem - Provides a NodeJS-like API for working with files on the device.
  • Geolocation - Provides simple methods for getting and tracking the current position of the device using GPS, along with altitude, heading, and speed information if available.
  • Haptics - Provides physical feedback to the user through touch or vibration.
  • Keyboard - Provides keyboard display and visibility control, along with event tracking when the keyboard shows and hides.
  • Local Notifications - Provides a way to schedule device notifications locally (i.e. without a server sending push notifications).
  • Motion - Tracks accelerometer and device orientation (compass heading, etc.).
  • Network - Provides network and connectivity information.
  • Push Notifications - Provides access to native push notifications.
  • Screen Reader - Provides access to TalkBack/VoiceOver/etc. and Provides simple text-to-speech capabilities for visual accessibility.
  • Share - Provides methods for sharing content in any sharing-enabled apps the user may have installed.
  • Splash Screen - Provides methods for showing or hiding a Splash image.
  • Status Bar - Provides methods for configuring the style of the Status Bar, along with showing or hiding it.
  • Storage - Provides a simple key/value persistent store for lightweight data.
  • Text Zoom - Provides the ability to change Web View text size for visual accessibility.
  • Toast - Provides a notification pop up for displaying important information to a user. Just like real toast!

Tests

Tests are split by backend (API/plugin), CLI, database SQL, and frontend:

  • tests/ - Backend Vitest tests (API + plugin + CLI)
  • playwright/e2e/ - Frontend Playwright tests
  • supabase/tests/ - SQL tests for functions, RLS, and DB logic

Backend test groups (Vitest):

  • API tests: public/private endpoints and general backend behavior
  • Plugin tests: tests/updates*.test.ts, tests/stats*.test.ts, tests/channel_self*.test.ts
  • CLI tests: tests/cli*.test.ts (CLI auth, upload, metadata, etc.)

Run tests:

# Supabase Edge Functions (default)
bun test:all
bun test:backend
bun test:cli
bun test:front

# CLI workspace
bun run cli:build
bun run cli:test
bun run cli:check

# Legacy aliases kept for compatibility
bun test:local
bun test:all:local
bun test:cli:local

# Database SQL tests (Supabase CLI)
supabase test db

# Cloudflare Workers
bun test:cloudflare:all
bun test:cloudflare:backend
bun test:cloudflare:updates

# Local Cloudflare Workers (required for cloudflare tests)
./scripts/start-cloudflare-workers.sh

Notes:

  • Tests run in parallel across files. If a test mutates shared data, add dedicated seed data in supabase/seed.sql.
  • The repository is a Bun workspace monorepo. The Capgo app lives at the root and the CLI lives in cli/.
  • Capgo's Vitest CLI coverage now resolves the local cli/ workspace by default, so monorepo changes are exercised together.
  • SQL tests in supabase/tests/ are run by the Supabase CLI test runner.
  • Run bun run supabase:start first so the local DB is available (worktree-isolated).

Dev contribution

Coding Style

Dev tools

Deploy on Cloudflare Pages

Use the CLI to deploy to preprod

bun run dev-build
# then deploy
bun run deploy:cloudflare:console:preprod

or Prod

bun run build
# then deploy
bun run deploy:cloudflare:console:prod

Development

You will need to start each local server in separate terminals.

Before continuing, ensure you have the following installed:

You can install the supabase CLI globally with bun install supabase -g and you'll be able to invoke supabase from anywhere.

Alternatively, you can install the supabase CLI locally with bun install supabase --save-dev but, to invoke it, you have to use: ./node_modules/supabase/bin/supabase.

In the following guideline, we will assume that you have installed the supabase CLI globally.

Start Supabase DB Locally

Start the Supabase DB:

bun run supabase:start

Ports may differ per git worktree. To see the exact URLs/keys for the current worktree run:

bun run supabase:status
Seed Supabase DB locally

[!WARNING] ⚠️ Ensure Docker is running.

bun run supabase:db:reset
Start Frontend locally
bun install
bun serve:local
Login

Visit http://localhost:5173

There are two login credentials you can use:

Account Username Password
Demo User test@capgo.app testtest
Admin User admin@capgo.app adminadmin

The demo user account has some demo data in it. If the data is not fresh, just reset the db with supabase db reset. The seed has been made in a way that ensures the data is always fresh.

The admin user account has administration rights so the user can impersonate other users. You can find the interface for that in the "Account" section.

Supabase DB Reset

[!WARNING] ⚠️ Ensure Docker is running.

This will seed the DB with demo data.

supabase db reset

Deploy Supabase self hosted

To deploy the supabase instance in self-hosted, use the Supabase official guide.

Before deploying, duplicate supabase/functions/.env.example to supabase/functions/.env, replace the placeholder values with your self-hosted credentials, and keep the file local (it is gitignored). Use that file for commands such as supabase secrets set --env-file supabase/functions/.env.

Organization invitation emails depend on Bento. If BENTO_PUBLISHABLE_KEY, BENTO_SECRET_KEY, and BENTO_SITE_UUID are not configured in supabase/functions/.env and synced to Supabase secrets, invite-org emails will not be sent.

Deploy Supabase cloud

To deploy the Supabase instance on cloud, you need a paid account, which costs $25/month.

Link the project to the cloud with the following command:

supabase link

https://supabase.com/docs/reference/cli/supabase-link

Then you need to push the migrations to the cloud with the following command:

supabase db push --linked

https://supabase.com/docs/reference/cli/supabase-migration-up

And seed the DB with demo data:

supabase seed buckets

https://supabase.com/docs/reference/cli/supabase-seed-buckets

Seed the secret for functions:

supabase secrets set --env-file supabase/functions/.env

Deploy Capgo Cloud Supabase functions

Capgo Cloud (prod / preprod / alpha) only publishes allowlisted Supabase functions from scripts/supabase-cloud-functions.ts:

  • triggers forever (pg_net queue consumer)
  • bundle, channel, files, private until 2026-10-28 (old Capgo CLI still called these via supabase.functions.invoke on sb.capgo.app; new CLI uses api.capgo.app / files.capgo.app)

Console Capgo-cloud traffic uses Cloudflare (VITE_API_HOST); self-host / local consoles keep supabase.functions.invoke. Capgo cloud deploy also deletes functions outside the allowlist (skip-list / delete-args).

bun run deploy:supabase:prod
# or: bunx supabase functions deploy $(bun scripts/supabase-cloud-functions.ts deploy-args) --project-ref <ref>

Deploy self-hosted Supabase functions

Self-hosted installs should keep deploying every function:

supabase functions deploy

Environment Variables for Self-Hosted Deployments

By default, the configuration uses Capgo production values from configs.json. For self-hosted deployments, you must override all configuration values using environment variables.

Required Environment Variables

All configuration keys from configs.json can be overridden by setting their uppercase equivalent as environment variables:

Environment Variable Description Default (Prod) Required for Self-Hosted
BASE_DOMAIN Console domain console.capgo.app ✅ Yes
SUPA_ANON Supabase anonymous key Capgo production key ✅ Yes
SUPA_URL Supabase URL https://sb.capgo.app ✅ Yes
API_DOMAIN API domain api.capgo.app ✅ Yes
CAPTCHA_KEY Turnstile captcha key Capgo production key ⚠️ Optional
Example Self-Hosted Configuration
# .env file for self-hosted deployment
BASE_DOMAIN=console.yourdomain.com
SUPA_ANON=your-supabase-anon-key
SUPA_URL=https://your-supabase-url.supabase.co
API_DOMAIN=api.yourdomain.com
CAPTCHA_KEY=your-turnstile-key
Bento Email Variables

If you want organization invitation emails to work, you also need to configure these Bento environment variables:

BENTO_PUBLISHABLE_KEY=your-bento-publishable-key
BENTO_SECRET_KEY=your-bento-secret-key
BENTO_SITE_UUID=your-bento-site-uuid
How It Works

The configuration system (scripts/utils.mjs) checks for environment variables first:

  1. If an uppercase environment variable exists (e.g., SUPA_URL), it uses that value
  2. Otherwise, it falls back to the appropriate value from configs.json based on the branch (prod, preprod, development, or local)

Important: Without setting these environment variables, your self-hosted instance will attempt to connect to Capgo's production infrastructure, which will fail.

Build

To build the web app in mobile, in order to push to mobile stores, run:

bun install
bun mobile

And you will see the generated files in the dist directory, ready to be served on stores.

Frequently asked questions

Is Capgo free to use?

Capgo is open source under the AGPL-3.0 licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does Capgo do?

OTA updates for Capacitor apps without app store delays

What is Capgo written in?

Capgo is primarily written in TypeScript. Its source is publicly available at https://github.com/cap-go/capgo, and it has 212 GitHub stars.