feat(admin): chart app creation build onboarding metrics#2571
Conversation
📝 WalkthroughWalkthroughAdds onboarding tracking to the app lifecycle: two new columns on ChangesApp Build Onboarding Metrics Pipeline
Sequence DiagramsequenceDiagram
participant User as User<br/>(creates app)
participant PostAPI as POST /app<br/>(create endpoint)
participant AppsDB as Apps table
participant Trigger as set_app_onboarding<br/>_completed_at trigger
participant CoreShard as Core global<br/>stats shard
participant GetMetrics as getAppBuild<br/>OnboardingMetrics
participant GlobalStatsDB as Global stats<br/>table
participant AdminDash as Admin<br/>Dashboard
User->>PostAPI: POST /app (need_onboarding=true)
PostAPI->>AppsDB: INSERT created_from_onboarding=true
AppsDB-->>PostAPI: app created
Note over CoreShard: Daily scheduled execution
CoreShard->>GetMetrics: Get prior-day metrics
GetMetrics->>AppsDB: Query apps with build requests
AppsDB-->>GetMetrics: rows with created_at, onboarding_completed_at, build_count
GetMetrics->>GetMetrics: summarizeAppBuildOnboardingRows
GetMetrics-->>CoreShard: apps_created, apps_with_cli/manual_onboarding_builds_24h
CoreShard->>GlobalStatsDB: Update global_stats snapshot
AdminDash->>GlobalStatsDB: Fetch trend data
GlobalStatsDB-->>AdminDash: global_stats trend rows
AdminDash->>AdminDash: appBuildOnboardingSeries mapper
AdminDash-->>User: Render onboarding metrics chart
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
Merging this PR will not alter performance
Comparing Footnotes
|
e68f3b7 to
4977799
Compare
🧪 Builder onboarding TUI preview — ❌ failed▶ Open the interactive HTML report (zoomable journey tree + cast playback) Commit: 202e524 · Job summary with the result table |
4977799 to
ab04a7f
Compare
ab04a7f to
aad7d3b
Compare
aad7d3b to
202e524
Compare
202e524 to
b504255
Compare
b504255 to
09f48a1
Compare
There was a problem hiding this comment.
Stale comment
Risk: medium. Cursor Bugbot remained pending after the 8-minute polling window, so automated review is incomplete and I am not approving. Human review is needed for the migration, backend trigger, and admin dashboard changes.
Sent by Cursor Approval Agent: Pull Request Approver External
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/types/supabase.types.ts (1)
321-332: 🗄️ Data Integrity & Integration | 🟡 MinorUpdate TypeScript RPC return types to reflect actual column availability.
The new
created_from_onboardingandonboarding_completed_atcolumns are missing from the TypeScript type definitions for both RPC functions:
get_accessible_apps_for_apikey_v2(line 3596): Returns fullappsrow at SQL level but TypeScript types omit the new fields, causing type-SQL mismatch.get_org_apps_with_last_upload(line 3824): Intentionally excludes these fields (per SQL comment: "stable apps list contract"), so TypeScript correctly omits them—but this is by design.The consumer code in
src/pages/apps.vue:42-43works around this with fallback logic ('created_from_onboarding' in app), but relying on runtime field presence is fragile. Regenerate the TypeScript types to match the SQL schema.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/types/supabase.types.ts` around lines 321 - 332, The TypeScript type definitions in the Supabase types file for the RPC functions `get_accessible_apps_for_apikey_v2` and `get_org_apps_with_last_upload` are out of sync with the actual SQL schema. The `get_accessible_apps_for_apikey_v2` function should include the `created_from_onboarding` and `onboarding_completed_at` fields since it returns the full apps row at the SQL level, while `get_org_apps_with_last_upload` should continue to exclude these fields as per its design contract for a stable API. Regenerate the TypeScript type definitions from the Supabase schema to ensure they accurately reflect what each RPC function returns, eliminating the need for runtime field presence checks in consumer code like `src/pages/apps.vue`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/types/supabase.types.ts`:
- Around line 321-332: The TypeScript type definitions in the Supabase types
file for the RPC functions `get_accessible_apps_for_apikey_v2` and
`get_org_apps_with_last_upload` are out of sync with the actual SQL schema. The
`get_accessible_apps_for_apikey_v2` function should include the
`created_from_onboarding` and `onboarding_completed_at` fields since it returns
the full apps row at the SQL level, while `get_org_apps_with_last_upload` should
continue to exclude these fields as per its design contract for a stable API.
Regenerate the TypeScript type definitions from the Supabase schema to ensure
they accurately reflect what each RPC function returns, eliminating the need for
runtime field presence checks in consumer code like `src/pages/apps.vue`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: f35cf478-0df7-4267-872c-cdec0940988a
📒 Files selected for processing (15)
cli/src/types/supabase.types.tsdocs/pr-assets/admin-app-build-onboarding-chart.webpmessages/en.jsonread_replicate/schema_replicate.sqlsrc/pages/admin/dashboard/index.vuesrc/pages/apps.vuesrc/types/supabase.types.tssupabase/functions/_backend/public/app/post.tssupabase/functions/_backend/triggers/logsnag_insights.tssupabase/functions/_backend/utils/pg.tssupabase/functions/_backend/utils/postgres_schema.tssupabase/functions/_backend/utils/supabase.types.tssupabase/migrations/20260623144909_admin_app_build_onboarding_metrics.sqltests/admin-stats.test.tstests/logsnag-insights-revenue.unit.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
There was a problem hiding this comment.
Stale comment
Risk: medium. Cursor Bugbot is still pending after the 8-minute polling window and no Bugbot review comment was posted, so I am not approving without that automated signal. Human review is needed for the migration, backend metrics pipeline, and admin dashboard changes; WcaleNieWolny is already requested and I also requested Dalanir.
Sent by Cursor Approval Agent: Pull Request Approver
09f48a1 to
22c3dc0
Compare
There was a problem hiding this comment.
Stale comment
Risk: medium. Cursor Bugbot finished with a skipped status and no Bugbot review comment was posted, so I am not approving without that automated signal. Human review is still needed for the migration, backend metrics pipeline, and admin dashboard changes; WcaleNieWolny and Dalanir are already requested.
Sent by Cursor Approval Agent: Pull Request Approver External
There was a problem hiding this comment.
Stale comment
Risk: medium. Cursor Bugbot finished with a skipped check and reported 2 unresolved findings (including one high-severity metrics timing issue), so I am not approving. WcaleNieWolny and Dalanir are already requested for human review of the migration, backend metrics pipeline, and admin dashboard changes.
Sent by Cursor Approval Agent: Pull Request Approver
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/functions/_backend/triggers/logsnag_insights.ts`:
- Around line 1351-1392: The snapshot timing issue occurs because
getAppBuildOnboardingMetrics is being called too early in the day (01:01 UTC) to
capture the full 24-hour observation windows for apps created near the end of
the previous day. Find where getAppBuildOnboardingMetrics is invoked in the
snapshot recording workflow and delay the execution until after 23:59 UTC to
ensure all apps created the previous day have completed their full 24-hour build
observation window before the metric is recorded.
In `@supabase/migrations/20260623144909_admin_app_build_onboarding_metrics.sql`:
- Around line 48-52: The two CREATE INDEX statements for idx_apps_created_at and
idx_build_requests_app_created_at are missing the CONCURRENTLY keyword, which
will cause write locks on these tables during the migration. Add the
CONCURRENTLY keyword to both CREATE INDEX IF NOT EXISTS statements so that the
indexes are built without blocking concurrent write operations on the
public.apps and public.build_requests tables.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 037135c6-e2bc-4a1f-87b2-7c4102af84f8
📒 Files selected for processing (15)
cli/src/types/supabase.types.tsdocs/pr-assets/admin-app-build-onboarding-chart.webpmessages/en.jsonread_replicate/schema_replicate.sqlsrc/pages/admin/dashboard/index.vuesrc/pages/apps.vuesrc/types/supabase.types.tssupabase/functions/_backend/public/app/post.tssupabase/functions/_backend/triggers/logsnag_insights.tssupabase/functions/_backend/utils/pg.tssupabase/functions/_backend/utils/postgres_schema.tssupabase/functions/_backend/utils/supabase.types.tssupabase/migrations/20260623144909_admin_app_build_onboarding_metrics.sqltests/admin-stats.test.tstests/logsnag-insights-revenue.unit.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
| CREATE INDEX IF NOT EXISTS idx_apps_created_at | ||
| ON public.apps (created_at); | ||
|
|
||
| CREATE INDEX IF NOT EXISTS idx_build_requests_app_created_at | ||
| ON public.build_requests (app_id, created_at); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Use concurrent index creation to avoid deploy-time write blocking.
Line 48 and Line 51 create indexes without CONCURRENTLY. On large tables, this can block writes for the migration duration and degrade API availability. Move these to a dedicated migration that builds indexes concurrently.
Suggested change
-CREATE INDEX IF NOT EXISTS idx_apps_created_at
-ON public.apps (created_at);
-
-CREATE INDEX IF NOT EXISTS idx_build_requests_app_created_at
-ON public.build_requests (app_id, created_at);
+-- Run in a dedicated migration that supports non-transactional statements
+CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_apps_created_at
+ON public.apps (created_at);
+
+CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_build_requests_app_created_at
+ON public.build_requests (app_id, created_at);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@supabase/migrations/20260623144909_admin_app_build_onboarding_metrics.sql`
around lines 48 - 52, The two CREATE INDEX statements for idx_apps_created_at
and idx_build_requests_app_created_at are missing the CONCURRENTLY keyword,
which will cause write locks on these tables during the migration. Add the
CONCURRENTLY keyword to both CREATE INDEX IF NOT EXISTS statements so that the
indexes are built without blocking concurrent write operations on the
public.apps and public.build_requests tables.
22c3dc0 to
3712e7e
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3712e7e. Configure here.
| } | ||
| else { | ||
| totals.apps_with_manual_builds_24h += 1 | ||
| } |
There was a problem hiding this comment.
CLI onboarding metrics misclassified
High Severity
The admin “CLI onboarding” series keys off created_from_onboarding, but that flag is only set when apps are created through the web app POST with need_onboarding. CLI build init / addAppInternal inserts apps without need_onboarding, so those apps stay created_from_onboarding: false and land in the manual series instead of CLI onboarding.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 3712e7e. Configure here.
| apps_created: finalizedAppBuildOnboardingMetrics.apps_created, | ||
| apps_with_cli_onboarding_builds_24h: finalizedAppBuildOnboardingMetrics.apps_with_cli_onboarding_builds_24h, | ||
| apps_with_manual_builds_24h: finalizedAppBuildOnboardingMetrics.apps_with_manual_builds_24h, | ||
| }) |
There was a problem hiding this comment.
Onboarding stats lag chart completion
Medium Severity
Daily onboarding counters for cohort date D are written when the core shard runs for date D+1, but the global_stats row for D can already satisfy completed_shards and appear in the admin trend after the D shard run, so apps_created and build onboarding fields can show as zero until the next day’s core job patches them.
Reviewed by Cursor Bugbot for commit 3712e7e. Configure here.
| LEFT JOIN public.build_requests br | ||
| ON br.app_id = ca.app_id | ||
| AND br.created_at >= ca.created_at | ||
| AND br.created_at < ca.created_at + INTERVAL '24 hours' |
There was a problem hiding this comment.
All build requests counted
Medium Severity
The onboarding cohort SQL counts every build_requests row in the first 24 hours with no status filter, while other global build stats in the same file count only status = 'succeeded', so failed or pending requests can push apps over the “>2 builds” threshold incorrectly.
Reviewed by Cursor Bugbot for commit 3712e7e. Configure here.
There was a problem hiding this comment.
Risk: medium. Cursor Bugbot finished with a skipped check and reported 3 unresolved findings (including high-severity metrics timing and CLI classification issues), so I am not approving. WcaleNieWolny and Dalanir are already requested for human review of the migration, backend metrics pipeline, and admin dashboard changes.
Sent by Cursor Approval Agent: Pull Request Approver
|







Summary
global_statscounters for apps created, first-day CLI onboarding builds, and first-day manual builds.manualorcli_onboardingand normalize missing/unknown sources server-side.Screenshot
Validation
bun lintbun lint:backendbun typecheckbun run cli:checkbun test tests/admin-stats.test.tsbun test ./test/prescan/request-gate.test.tsfromcli/bun run supabase:db:resetbunx supabase db lint --localfrom.context/supabase-worktrees/c85d6572(exits 0 with existing warnings)docs/pr-assets/admin-app-build-onboarding-chart.webpNote
Medium Risk
Touches schema, migrations, and the daily global-stats shard with delayed cohort logic; mistakes would skew admin metrics but not user auth or billing.
Overview
Adds onboarding provenance on apps (
created_from_onboarding,onboarding_completed_atvia a trigger whenneed_onboardingflips off) and persists three dailyglobal_statscounters: apps created that UTC day, CLI-onboarding apps with >2 builds in the first 24h (only if onboarding completed within 24h of creation), and non-onboarding apps with the same build threshold.The global stats job computes those cohort metrics on a one-day lag so each app’s full 24h build window can finish, then writes them to the prior day’s snapshot. App create sets
created_from_onboardingfromneed_onboarding. The admin dashboard gets a multi-line chart and trend API wiring;get_org_apps_with_last_uploadis rewritten to an explicit column list so new app fields do not break the RPC contract.apps.vuenormalizes list rows that omit the new columns.Reviewed by Cursor Bugbot for commit 3712e7e. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit