Console to manage and distribute your live update
Features
- ☁️ Cloud / Self hosted Support: Use our Cloud to manage
- 📦 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
- 🔁 Delta Updates: Make instant updates by only downloading changed files.
- 🔒 Security: Encrypt and sign each updates with best in class security
- ⚔️ 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
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
- Cloudflare Workers runs the same backend code (via the Hono adapter) but is
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 scriptsscripts/- Dev/build scripts used by CI and local toolingtests/- Backend Vitest tests (run in parallel)playwright/- Frontend E2E testsdocs/- Extra documentation and guidesandroid/,ios/- Capacitor native projects (mobile builds)
supabase/is enough to run the backend locally.src/is the web console you point to your own backend.cloudflare_workers/is only needed if you want to run the Workers layer
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.
supabase/functions/_backend/private/- Private API used internally.
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
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:
Provides access to native Action Sheets.- App - Handles
- Browser -
- Camera -
- Device -
- Dialog -
- Haptics -
- Keyboard -
- Motion -
- Network -
- Share -
- Storage -
- 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 testssupabase/tests/- SQL tests for functions, RLS, and DB logic
- 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.)
# 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
supabase/seed.sql.
- The repository is a Bun workspace monorepo. The Capgo app lives at the root
cli/.
- Capgo's Vitest CLI coverage now resolves the local
cli/workspace by
- SQL tests in
supabase/tests/are run by the Supabase CLI test runner. - Run
bun run supabase:startfirst so the local DB is available (worktree-isolated).
Dev contribution
Coding Style
- Use Composition API with
SFC syntax
- ESLint with
Dev tools
- TypeScript
- bun - fast javascript runtime, package manager, bundler,
- critters - Critical CSS
- Cloudflare - zero-config deployment
- VS Code Extensions
IDE support
- Iconify IntelliSense -
Icon inline display and autocomplete
- i18n Ally -
All in one i18n support
- Windi CSS Intellisense -
IDE support for Windi CSS
- ESLint
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 thesupabase 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:
triggersforever (pg_netqueue consumer)bundle,channel,files,privateuntil 2026-10-28 (old Capgo CLI
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:
- If an uppercase environment variable exists (e.g.,
SUPA_URL), it uses that value - Otherwise, it falls back to the appropriate value from
configs.jsonbased on the branch (prod,preprod,development, orlocal)
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.