Skip to content

Admin console redesign with Growth and People analytics - #372

Merged
DevelopedByDev merged 5 commits into
mainfrom
codex/admin-console-redesign
Nov 2, 2026
Merged

DevelopedByDev merged 5 commits into
mainfrom
codex/admin-console-redesign

Conversation

@DevelopedByDev

@DevelopedByDev DevelopedByDev commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Supersedes #366 (Growth panel) and #367 (PostHog cleanup) and adds the redesign approved from the HTML mockup. Everything ships together in this PR.

What changes

Redesign (apps/admin)

  • Uses the main app's bordered shell: chrome background, 12px bordered panels, 8px gaps, Geist and Lucide icons, with @overlay/ui controls.
  • The sidebar is grouped into Insights (Growth), Operations (People, Audit log) and Access (Roles, Groups, Catalog). The operator's name and role sit in the footer, next to the theme toggle and sign-out.
  • Light/dark is stored in the overlay_admin_theme cookie and read on the server, because the nonce CSP doesn't allow an inline theme script.
  • Shared tokens are remapped inside the shell, so the existing Roles, Groups and Catalog panels pick up the palette without being rewritten.
  • Fixes the Tailwind @source paths. They pointed at apps/packages, so @overlay/ui package classes were missing from the admin build.

Growth

  • Four headline tiles with week-over-week change and sparklines.
  • A weekly-active bar chart with tooltips.
  • W1/W4 retention, with cells shaded by rate.
  • Created / Work / Money cards and the top workspaces by spend.
  • A 4/12/26-week range switch; getGrowthSummary now returns 182 days.

People

  • admin/console:listUserDirectory returns people newest first, with name, email, user ID, sign-up time, plan (paid when the billing account has an active or trialing paid subscription) and last active day (the latest growthUserDays row).
  • ?q= matches an exact user ID or email, otherwise part of a name or email among the newest 5,000 accounts.

Audit log is now its own page, with an allowed/denied pill on each row.

From #367: stops sending usage events to PostHog. The merge with main kept main's new chat preflight code and removed only the PostHog calls from it. The growth analytics plan doc is deleted, since this is its last phase.

Checks

  • apps/admin typecheck, ESLint and unit tests: 31 tests pass.
  • npx tsc -p convex --noEmit passes.
  • The Convex suites adminConsole, growthAnalytics, adminAuthorizationParity and adminSeparation pass. This includes a new test for the People fields, ordering and search.
  • The pre-push hook passed: lint, project typecheck and tests.
  • Every page was reviewed in a local browser on a temporary fixture with fake data (not committed), in dark, light and narrow layouts. The range switch and chart tooltip work.

Not yet verified: the pages against real data with a signed-in operator session. The Roles, Groups and Catalog API calls were checked only for layout.

After merge

  1. Deploy Convex production from clean, current main once the matching web build is live, per internal/develop/convex-workflow.md.
  2. The existing production growth backfill completed and yesterday’s rollup was verified during integration. Do not restart it for this release. A fresh installation needs its initial backfill once, per the admin-console runbook.

🤖 Generated with Claude Code

DevelopedByDev and others added 4 commits November 1, 2026 10:32
admin/console:getGrowthSummary reads only the growth tables: 90 days of
totals, new paid accounts per day, the last 12 signup cohorts and the top
workspaces by spend. GET /api/v1/admin/growth serves it to admin, auditor
and billing operators; support has no access. The panel shows headline
numbers against the prior week, weekly trends per group, W1/W4 retention
and the top workspaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Growth is counted from Convex now, so the client and server metrics
pipelines, retention.engaged, the signed-in ping, feature-level captures
(chat, Work, integrations, auth callback, sign-out) and the billing,
automation and workspace lifecycle mappings are removed. PostHog keeps
pageviews, identify/reset, feature flags and one signup event, renamed
user.signed_up. The unused Convex withMetrics wrapper and its aggregation
query are deleted; the functionMetrics table and cleanup cron stay until
the table is empty. The growth plan is retired into admin-console.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…edesign

# Conflicts:
#	CHANGELOG.md
#	internal/plans/GROWTH_ANALYTICS_PLAN.md
#	src/features/chat/components/chat/chatTransport.ts
#	src/features/chat/components/chat/useChatRetryController.ts
#	src/features/chat/components/chat/useChatSendController.ts
Bordered panels on the chrome background, grouped sidebar (Insights,
Operations, Access), light and dark themes via a cookie, and @overlay/ui
controls. Growth gets KPI tiles, a weekly-active chart, shaded retention,
Created/Work/Money cards and a 4/12/26-week range (the summary now returns
182 days). People shows name, email, user ID, sign-up date, last active day
and plan, newest first, with search by name, email or ID. Audit log is its
own page.

Also fixes the Tailwind @source paths, which pointed one directory too
shallow, so package classes were missing from the admin build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mintlify

mintlify Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
layernorminc 🟢 Ready View Preview Nov 2, 2026, 5:46 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@vercel

vercel Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
overlay-admin Ready Ready Preview Nov 2, 2026 7:44am UTC
overlay-landing Ready Ready Preview Nov 2, 2026 7:44am UTC

Request Review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-02T05:48:23.008484Z 42dc5f2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42dc5f2dc0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread convex/admin/console.ts
name: displayName(row),
createdAt: row._creationTime,
lastActiveDay: lastDay?.day,
plan: await planOf(ctx, row.billingAccountId),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve the workspace plan instead of the personal billing account

For a person using a paid workspace, this passes their personal billing account ID to planOf, so the People directory incorrectly labels them as Free. The subscriptions schema explicitly identifies this field as the personal account link, while paid plans belong to workspace billing accounts; convex/billing/workspacePayer.ts resolves those through the workspace instead. Derive the displayed plan from the relevant workspace account, or remove the person-level plan badge rather than reporting paid customers as free.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 3/5

[High impact] The PR changes an operator console and removes analytics across the wider app.

The PR needs fixes before merging because paid users can appear as Free and changing the Growth range can crash the page.

Fix All in CodexFindings

  1. P1 Paid people appear free ▶
  2. P1 Changing range crashes Growth ▶
  3. P2 Monthly spend drops daily rows ▶
Fix with agent prompt
### Issue 1
convex/admin/console.ts:undefined-836
`listUserDirectory` reads the plan from `row.billingAccountId`, but normal profile sync never sets that field. Paid plans belong to workspace billing accounts, which the app finds through workspace preferences. A person using a paid workspace therefore appears as Free in People.

Resolve the person's relevant workspace billing account before checking its subscription. Test with records created through the normal signup and billing paths.

### Issue 2
apps/admin/src/features/admin/growth/GrowthPanel.tsx:undefined-178
`WeeklyChart` keeps `hovered` when the range changes, but the tooltip reads `weeks[hovered].endDay` without checking that the week still exists. Hover a later bar in the 12-week view, then use the keyboard to activate the 4-week option without moving the pointer. The next render reads past the shorter array and throws, breaking the page.

Clear or bound the hovered index when the weeks change.

### Issue 3
convex/admin/console.ts:931-932
If more than 200 workspaces spend in a day, taking only that day's top 200 can make the 30-day ranking wrong. A steady spender can stay below the daily cutoff while rotating one-day spenders rank above it. That workspace is omitted even if its monthly total belongs in the top ten. Included workspaces also lose spend from days below the cutoff.

Sum all daily workspace totals, or maintain a complete 30-day rollup.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR redesigns the admin console and adds Growth and People views.

  • The admin console groups its pages in a themed, bordered shell.
  • Operators can explore growth trends, retention, and workspace spend.
  • The People directory shows richer account details and searches recent sign-ups.
  • The Audit log has its own page with clear outcome labels.
  • The app stops sending product activity and operational metrics to PostHog.

Reviews (2) · Last reviewed commit: "fix(admin): keep growth cards and contro..." · Reviewed by Greptile

Comment thread convex/admin/console.ts
name: displayName(row),
createdAt: row._creationTime,
lastActiveDay: lastDay?.day,
plan: await planOf(ctx, row.billingAccountId),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Paid people appear free

listUserDirectory reads the plan from row.billingAccountId, but normal profile sync never sets that field. Paid plans belong to workspace billing accounts, which the app finds through workspace preferences. A person using a paid workspace therefore appears as Free in People.

Resolve the person's relevant workspace billing account before checking its subscription. Test with records created through the normal signup and billing paths.

Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/admin/console.ts
Line: 836

Comment:
**Paid people appear free**

`listUserDirectory` reads the plan from `row.billingAccountId`, but normal profile sync never sets that field. Paid plans belong to workspace billing accounts, which the app finds through workspace preferences. A person using a paid workspace therefore appears as Free in People.

Resolve the person's relevant workspace billing account before checking its subscription. Test with records created through the normal signup and billing paths.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Conductor

top: `calc((100% - 22px) * ${1 - (hoveredValue ?? 0) / max} - 8px)`,
}}
>
<span>Week to {shortDay(weeks[hovered].endDay)}</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Changing range crashes Growth

WeeklyChart keeps hovered when the range changes, but the tooltip reads weeks[hovered].endDay without checking that the week still exists. Hover a later bar in the 12-week view, then use the keyboard to activate the 4-week option without moving the pointer. The next render reads past the shorter array and throws, breaking the page.

Clear or bound the hovered index when the weeks change.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/admin/src/features/admin/growth/GrowthPanel.tsx
Line: 178

Comment:
**Changing range crashes Growth**

`WeeklyChart` keeps `hovered` when the range changes, but the tooltip reads `weeks[hovered].endDay` without checking that the week still exists. Hover a later bar in the 12-week view, then use the keyboard to activate the 4-week option without moving the pointer. The next render reads past the shorter array and throws, breaking the page.

Clear or bound the hovered index when the weeks change.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Conductor

Comment thread convex/admin/console.ts
Comment on lines +931 to +932
const rows = await ctx.db.query('growthWorkspaceUsage')
.withIndex('by_day_cents', (q) => q.eq('day', day)).order('desc').take(GROWTH_WORKSPACE_ROWS_PER_DAY)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Monthly spend drops daily rows

If more than 200 workspaces spend in a day, taking only that day's top 200 can make the 30-day ranking wrong. A steady spender can stay below the daily cutoff while rotating one-day spenders rank above it. That workspace is omitted even if its monthly total belongs in the top ten. Included workspaces also lose spend from days below the cutoff.

Sum all daily workspace totals, or maintain a complete 30-day rollup.

Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/admin/console.ts
Line: 931-932

Comment:
**Monthly spend drops daily rows**

If more than 200 workspaces spend in a day, taking only that day's top 200 can make the 30-day ranking wrong. A steady spender can stay below the daily cutoff while rotating one-day spenders rank above it. That workspace is omitted even if its monthly total belongs in the top ten. Included workspaces also lose spend from days below the cutoff.

Sum all daily workspace totals, or maintain a complete 30-day rollup.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Conductor

@DevelopedByDev DevelopedByDev added the needs-preview Request exact-SHA hosted Preview and isolated backend for browser or end-to-end QA label Nov 2, 2026
@DevelopedByDev

Copy link
Copy Markdown
Collaborator Author

Integration review and QA handoff

Reviewed and tested head 6c0f2a62436cb1bde7627aca6cb99fbb12877a62.

  • Customer Preview: https://pr-372.preview.getoverlay.io, READY deployment dpl_6mLJ7Np9pxM6yUHEMJnXNWLbxHrz, isolated backend wandering-canary-476 (preview/pr-372).
  • Admin Preview: https://overlay-admin-6rabmgusa-divyansh-lalwanis-projects.vercel.app, READY deployment dpl_6C8sFFPaotpkQo5oVNYXLF9WK5YU, same isolated backend.
  • Real WorkOS AuthKit sign-in passed on the initial reviewed head. Reused that session on the final admin build. Synthetic data only: empty and populated Growth, 4/12/26-week ranges, chart hover, retention, light/dark persistence after reload, People name/email/ID search and no-match, paid-plan and recent-activity display, Audit filtering, Roles/Groups and Catalog navigation.
  • Live support-role test on the final admin build: People 200, Growth/Audit 403, restricted navigation after reload. Restored the test operator. Unassigned zero-capability role/group fixtures were created, edited, read back and archived; group editing was also exercised through the browser.
  • Found and fixed clipped summary cards/header controls at narrow widths. Final hosted 390x844 screenshot and element bounds confirm the cards and controls fit.
  • Authenticated customer Work/Chats navigation and existing conversation loading passed; browser error log empty. No paid inference or production writes for QA.
  • Focused tests: 25 Convex, 31 admin, 15 web tests pass. Current-head required CI, including exhaustive shards, type/boundary checks, compilation and security aggregate, passes.
  • Reviewed removed PostHog calls and preserved pageviews, identity/reset, signup, feature flags, Sentry and lifecycle audit sinks. Saved PostHog dashboard/alert dependencies could not be audited: connector requires reauthentication. This remains an explicit limitation.
  • Existing production growth backfill was verified complete, with yesterday's rollup present. Do not restart it for this release.

No remaining code blocker found. Production verification and Preview cleanup follow the native-main release.

@DevelopedByDev
DevelopedByDev merged commit 9775b98 into main Nov 2, 2026
28 checks passed
@DevelopedByDev
DevelopedByDev deleted the codex/admin-console-redesign branch November 2, 2026 07:46
@DevelopedByDev

Copy link
Copy Markdown
Collaborator Author

Production verification

Merged as 9775b983d99bc5f450a0d10bb23bbc27a146ecc2; published main SHA verified.

  • Native customer Production: dpl_8CHVXMgjqQkCnZEQz8YyHygfXFKt, READY at the merge SHA, serving https://www.getoverlay.io.
  • Native admin Production: dpl_CWdqreQ3jrgY4FShg9aWXzQLwc7T, READY at the same SHA, serving https://admin.getoverlay.io.
  • Convex dry-run and deployment passed from clean current canonical main after matching customer web was READY. No index deletions. Readback confirms Growth/People functions present and retired metrics writers/aggregation absent; cleanup remains.
  • Production operator session renders populated Growth (weekly chart/retention, no loading/error state). People navigation renders its heading; broader People/search and role/write acceptance was completed against isolated Preview with synthetic records. Native browser tooling subsequently timed out, so no additional production UI claims are made.
  • Authenticated customer Work and Chats load after release with an empty browser error log. No inference or customer-content writes during production smoke.
  • Existing growth backfill remains complete and yesterday's rollup is present; no backfill restarted.
  • Main Security Checks, CodeQL, Semgrep and Docs passed. All required PR checks passed on the tested head.
  • Closed Preview cleanup verified: custom URL HTTPS 404, exact owned Convex backend removed by guarded controller; cleanup workflow green after retrying its hostname-propagation check. Temporary admin branch bindings and exact sandbox callback removed with readback. Private temporary QA key/session files removed.
  • Six unrelated canonical files restored with exact hash/mode verification, including the owner's deleted-by-main plan retained as a local untracked file; desktop checkout restored. Integration checkout clean.

Remaining limitation: saved PostHog dashboard/alert dependencies were not audited because the connector requires reauthentication. Source/runtime checks verify the retained tracking boundaries; this does not establish external dashboard compatibility.

This branch was successfully deployed

3 active (1 outdated) deployments
Preview – overlay-admin — 6c0f2a62 Deployed Nov 2, 2026 by vercel[bot]
Preview – overlay-landing — 6c0f2a62 Deployed Nov 2, 2026 by vercel[bot]
staging - docs — 42dc5f2d Deployed Nov 2, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-preview Request exact-SHA hosted Preview and isolated backend for browser or end-to-end QA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant