An indie founder's portfolio operations hub - revenue, users, crashes and reviews for every app you ship, in one place. A web console (setup and deep admin) and a mobile app (KPIs, alerts and an iOS widget in your pocket) both talk to the same Supabase hub.
One product, two shells, a shared data layer - not one UI stretched across two screens. See ADR-001.
| Overview | Revenue | Users | Health |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Home screen widget | Sources |
|---|---|
![]() |
![]() |
The Health tab includes a measurement suspect panel: it flags malformed event reporting (more session ends than starts, funnels with missing start events) instead of charting bad data as truth.
helm/ bun workspaces monorepo
├── apps/
│ ├── web/ Refine + Vite - admin, integration wizard, billing
│ └── mobile/ Expo (SDK 56) - KPI/alert/widget, TestFlight
├── packages/ @helm/* - shared layer between apps
│ ├── types/ Supabase Database + domain types (single source)
│ ├── api/ plain fetch functions (supabase.from)
│ ├── queries/ TanStack queryOptions + keys
│ ├── domain/ formatting, severity, modules
│ └── config/ staleTime, plan limits
├── supabase/ migrations + edge functions (shared by both apps)
└── docs/ architecture and migration notes
bun install
make hooks # git hooks - run once after cloningThen copy the env template and fill in your own Supabase project:
cp apps/mobile/.env.example apps/mobile/.envHelm expects a Supabase project of your own. Apply the migrations in
supabase/migrations/ with make db-push, then deploy the edge functions with
make fn-deploy.
Real credentials live in .env; .env.example holds placeholders only. If you
stage an actual secret the pre-commit hook stops the commit, and the same scan
runs in CI. See SECURITY.md.
| Command | What it does |
|---|---|
make dev-web |
Web console (Refine/Vite) |
make dev-mobile |
Mobile (Expo, clean cache) |
make typecheck |
tsc across every workspace |
make build-web |
Web production build → apps/web/dist |
make gen-types |
Supabase schema → packages/types/src/database.ts |
make db-push |
Apply migrations to the remote database |
make fn-deploy FN=helm-payouts |
Deploy an edge function (omit FN for all) |
make ios-release |
Local IPA + TestFlight (delegates to apps/mobile/Makefile) |
make ota |
Publish an over-the-air update to the production channel |
make scan-secrets |
Scan tracked files for credentials |
make audit-secrets |
Scan the entire git history |
make clean |
Remove node_modules and build output |
Migrations live in supabase/migrations/, edge functions in
supabase/functions/.
Provider connectors sit inside helm-ingest; an hourly cron syncs every enabled
integration. Different providers are fetched concurrently while integrations
sharing one provider run in sequence, so no external API ever sees two requests
at once - that keeps reporting quotas (AdMob in particular) safe.
The metric schema is deliberately generic:
metrics: project_id, date, source, metric, value. Adding a new metric means a
new metric string plus a connector that writes it - no migration.
- Web -
make build-webproduces a staticdist/. Serve it behind your own Caddy/nginx and an auth wall; the RLS policy is permissive because Helm was built single-user first. - Mobile -
make ios-releaseruns the EAS build locally and submits to TestFlight, which avoids burning cloud build quota.
- docs/README.md - documentation index
- docs/architecture/monorepo.md - package rules, import direction
- docs/integrations/architecture.md - sync orchestration, adapter interface
- docs/migration/ - migration phases
- MONOREPO-EXECUTION.md - phase 0 setup spec (applied)
Some documents are written in Turkish; the code, commit messages and contributor-facing guides are in English.
- CONTRIBUTING.md - workflow, commit format, PR expectations
- SECURITY.md - how to report a vulnerability
GNU AGPL-3.0. If you modify Helm and offer it to others over a network, you must make your modified source available to those users. Get in touch if you need terms that don't fit that requirement.
- Phase 0 (monorepo skeleton) ✅ - workspaces,
@helm/*scaffold, types as a single source, green build. - Phase 1 (API extract) ✅ - reads go through
@helm/api(32 modules) and@helm/queries; both apps import from@helm/*. Three write paths still callsupabase.fromdirectly (CMS asset delete, CMS revision insert, push-device upsert). Background: phase-1-api-extract.md. - Next - move those three writes into
@helm/api, then tighten the RLS policies for multi-user use (see Deployment).






