stack/apps/backend
Mantra 65d87a4836
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
Dashboard: DataGrid refactor + layout (stacked on overview-revamp) (#1338)
## Summary

Stacked on `overview-revamp` (now rebased against `dev`). Introduces a
first-class `DataGrid` component in
`@stackframe/dashboard-ui-components`, migrates every dashboard table
off the legacy `DesignDataTable` / hand-rolled `<Table>` pattern to it,
and ships a matching dashboard design guide.

Since the last writeup the `DataGrid` runtime has been substantially
rewritten: the virtualizer now supports `rowHeight="auto"` with
`estimatedRowHeight`, every column can opt into `cellOverflow: "wrap"`,
the toolbar + header stick under a configurable `stickyTop`, and the
seeded dummy data has been fleshed out so the migrated surfaces render
with realistic density. The AI-analytics prompt was also extended with
full schema docs for the auth / team / email / payments tables so
natural-language queries produce better SQL.

**Base:** `dev` → **Head:** `ui-fixes-minor`
**Scope:** 39 files, ~+6.5k / -2.4k

## Screenshots

Captured against the seeded Demo Project on the local dashboard
(`admin@example.com` via mock GitHub OAuth). Viewport: **1920×1200**
(standard) and **2560×1440** (widescreen). Assets hosted in [this
gist](https://gist.github.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9).

### Overview — revamped metrics + line chart

| Light | Dark |
| --- | --- |
|
![overview-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/overview-light.jpg)
|
![overview-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/overview-dark.jpg)
|

Widescreen:

| Light | Dark |
| --- | --- |
|
![overview-wide-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/overview-wide-light.jpg)
|
![overview-wide-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/overview-wide-dark.jpg)
|

### Users — DataGrid with seeded rows

| Light | Dark |
| --- | --- |
|
![users-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/users-light.jpg)
|
![users-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/users-dark.jpg)
|

Widescreen:

| Light | Dark |
| --- | --- |
|
![users-wide-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/users-wide-light.jpg)
|
![users-wide-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/users-wide-dark.jpg)
|

### Transactions — new DataGridToolbar + sticky chrome

| Light | Dark |
| --- | --- |
|
![transactions-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/transactions-light.jpg)
|
![transactions-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/transactions-dark.jpg)
|

Widescreen:

| Light | Dark |
| --- | --- |
|
![transactions-wide-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/transactions-wide-light.jpg)
|
![transactions-wide-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/transactions-wide-dark.jpg)
|

### Teams

| Light | Dark |
| --- | --- |
|
![teams-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/teams-light.jpg)
|
![teams-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/teams-dark.jpg)
|

Widescreen:

| Light | Dark |
| --- | --- |
|
![teams-wide-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/teams-wide-light.jpg)
|
![teams-wide-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/teams-wide-dark.jpg)
|

### Email Outbox

| Light | Dark |
| --- | --- |
|
![email-outbox-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-outbox-light.jpg)
|
![email-outbox-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-outbox-dark.jpg)
|

Widescreen:

| Light | Dark |
| --- | --- |
|
![email-outbox-wide-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-outbox-wide-light.jpg)
|
![email-outbox-wide-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-outbox-wide-dark.jpg)
|

### Payments — Customers

| Light | Dark |
| --- | --- |
|
![payments-customers-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/payments-customers-light.jpg)
|
![payments-customers-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/payments-customers-dark.jpg)
|

Widescreen:

| Light | Dark |
| --- | --- |
|
![payments-customers-wide-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/payments-customers-wide-light.jpg)
|
![payments-customers-wide-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/payments-customers-wide-dark.jpg)
|

### Sticky behaviour — scrolled views

Grids scrolled down ~600px. The page header is still pinned, and the
`DataGrid` toolbar + column header row stay put under it (backdrop-blur
+ `stickyTop` offset) while the virtualized body rows scroll past.
Compare the scrolled view against the top-of-page view above.

| Page | Light | Dark |
| --- | --- | --- |
| Users |
![users-light-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/users-light-scrolled.jpg)
|
![users-dark-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/users-dark-scrolled.jpg)
|
| Teams |
![teams-light-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/teams-light-scrolled.jpg)
|
![teams-dark-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/teams-dark-scrolled.jpg)
|
| Transactions |
![transactions-light-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/transactions-light-scrolled.jpg)
|
![transactions-dark-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/transactions-dark-scrolled.jpg)
|
| Payments Customers |
![payments-customers-light-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/payments-customers-light-scrolled.jpg)
|
![payments-customers-dark-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/payments-customers-dark-scrolled.jpg)
|
| Email Outbox |
![email-outbox-light-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-outbox-light-scrolled.jpg)
|
![email-outbox-dark-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-outbox-dark-scrolled.jpg)
|
| Analytics Tables |
![analytics-tables-light-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/analytics-tables-light-scrolled.jpg)
|
![analytics-tables-dark-scrolled](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/analytics-tables-dark-scrolled.jpg)
|

### Other migrated surfaces

| Page | Light | Dark |
| --- | --- | --- |
| Analytics Tables |
![analytics-tables-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/analytics-tables-light.jpg)
|
![analytics-tables-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/analytics-tables-dark.jpg)
|
| Emails |
![emails-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/emails-light.jpg)
|
![emails-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/emails-dark.jpg)
|
| Email Sent |
![email-sent-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-sent-light.jpg)
|
![email-sent-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/email-sent-dark.jpg)
|
| Domains |
![domains-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/domains-light.jpg)
|
![domains-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/domains-dark.jpg)
|
| Webhooks |
![webhooks-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/webhooks-light.jpg)
|
![webhooks-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/webhooks-dark.jpg)
|
| External DB Sync |
![external-db-sync-light](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/external-db-sync-light.jpg)
|
![external-db-sync-dark](https://gist.githubusercontent.com/mantrakp04/2fe05ddbb2d2d7cd2d237027c909c1b9/raw/external-db-sync-dark.jpg)
|

## What's new

### `DataGrid` in `@stackframe/dashboard-ui-components`

A new, fully-typed, fully-controlled grid component under
`packages/dashboard-ui-components/src/components/data-grid/`. Single
source of truth for tabular UI across the dashboard.

Package files:
- `data-grid.tsx` — main grid renderer (virtualized rows, sticky toolbar
+ header)
- `data-grid-toolbar.tsx` — built-in toolbar (search, columns, density,
export)
- `data-grid-sizing.ts` — column width / flex / min-width resolution
- `state.ts` — state helpers (`createDefaultDataGridState`, sort /
select / paginate utilities, `exportToCsv`, date formatters)
- `strings.ts` — i18n string table + `resolveDataGridStrings`
- `types.ts` — public types (`DataGridColumnDef`, `DataGridProps`,
`DataGridState`, `DataGridDataSource`, etc.)
- `use-data-source.ts` — `useDataSource` hook with `client` / `server` /
`infinite` modes
- `index.ts` — package entrypoint

Features:
- Controlled state (`state` + `onChange`) covering sorting, pagination,
column visibility, column widths, column pinning, selection,
date-display mode, and quick search.
- Column definitions with `string` / `number` / `date` / `dateTime` /
`boolean` / `singleSelect` / `custom` types, custom `renderCell`, custom
sort comparators, per-column `parseValue` / `dateFormat`, pinning,
align, flex / min / max width.
- **Cell overflow control** — new `cellOverflow: "truncate" | "wrap"`
per column. `"wrap"` + `rowHeight="auto"` lets rows grow to fit
multi-line content.
- **Dynamic row heights** — `rowHeight` now accepts `"auto"` with an
`estimatedRowHeight` hint for the virtualizer, eliminating
scroll-position jank while rows are still being measured.
- **Sticky chrome with `stickyTop`** — the toolbar and header stick
under a caller-provided offset (matching the page header height) with a
proper blur backdrop. See the _Sticky behaviour — scrolled views_
section above for the visual.
- Client-side sort + quick-search + pagination via `useDataSource` —
consumer never pre-sorts / paginates.
- Server-side and async-generator data sources for streaming / cursor
pagination.
- Paginated and infinite-scroll UI modes.
- CSV export + clipboard copy.
- Row single / multi selection with shift-range anchor.
- Row + cell click / double-click callbacks.
- Pluggable toolbar / footer / empty / loading states and i18n strings.

### Dashboard design guide

New `apps/dashboard/DESIGN-GUIDE.md`: prescriptive, AI-readable source
of truth for dashboard UI. Documents when to use each
`design-components` primitive, the `DataGrid` canonical pattern, color /
typography / spacing / motion rules, route-specific guidance, and the
migration priority. Now also documents the new `cellOverflow` and
dynamic-`rowHeight` patterns, and marks `DesignDataTable` as deprecated
in favor of `DataGrid` + `useDataSource` + `createDefaultDataGridState`.

### Overview page revamp


`apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/line-chart.tsx`
— line chart rewritten on top of the shared `AnalyticsChart` /
`DonutChartDisplay` primitives, feeding the revamped Overview.

### Data-table migrations

Every shared table under `apps/dashboard/src/components/data-table/` has
been rewritten on top of `DataGrid`:

- `api-key-table.tsx`
- `payment-product-table.tsx`
- `permission-table.tsx`
- `team-member-search-table.tsx`
- `team-member-table.tsx`
- `team-search-table.tsx`
- `team-table.tsx`
- `transaction-table.tsx` — now also wires in `DataGridToolbar` with
search / column visibility
- `user-search-picker.tsx`
- `user-table.tsx` — extracted `USER_TABLE_COLUMNS` for readability /
reuse

### Page adoption

Page-level tables migrated to `DataGrid` (or the new `useDataSource` +
`createDefaultDataGridState` pattern):

- `(overview)/line-chart.tsx`
- `analytics/tables/query-data-grid.tsx` (now with sticky header)
- `domains/page-client.tsx`
- `email-drafts/[draftId]/page-client.tsx`
- `email-outbox/page-client.tsx` (with `DataGridToolbar`)
- `email-sent/page-client.tsx`, `grouped-email-table.tsx`,
`sent-emails-view.tsx`
- `emails/page-client.tsx`
- `external-db-sync/page-client.tsx`
- `payments/layout.tsx`, `payments/customers/page-client.tsx`,
`payments/products/[productId]/page-client.tsx`
- `users/[userId]/page-client.tsx`
- `webhooks/page-client.tsx`, `webhooks/[endpointId]/page-client.tsx`
- `design-language/page-client.tsx`,
`design-language/realistic-demo/page-client.tsx`
- `playground/page-client.tsx`

### Backend & supporting changes

- `apps/backend/src/lib/ai/prompts.ts` — extends the AI-analytics prompt
with detailed schema docs for `contact_channels`, `teams`,
`team_member_profiles`, `team_permissions`, `team_invitations`,
`email_outboxes`, `project_permissions`, `notification_preferences`,
`refresh_tokens`, and `connected_accounts`, so natural-language queries
have richer context to compile against.
- `apps/backend/src/lib/seed-dummy-data.ts` — additional OAuth providers
on seed users, improving dummy-data coverage for the migrated tables
(visible on the Users grid).
- `apps/dashboard/src/app/globals.css` — adds `--data-grid-sticky-top`
token used to derive the grid's sticky offset under the page header.
- `packages/template/src/dev-tool/dev-tool-core.ts` — persist the
"closed" state when the user closes the dev-tool panel so it doesn't
reopen on next load.

## Notes for reviewers

- Rebased onto latest `dev`; conflict in `api-key-table.tsx` resolved by
keeping the `DataGrid` implementation (consistent with the other
migrated tables).
- `DesignDataTable` is still in the codebase but marked deprecated in
the design guide — new code must use `DataGrid`.
- `DataGrid` is fully controlled: consumers must pass state + onChange,
must feed `rows` from `useDataSource` (never raw arrays), and must
define columns outside the component or via `useMemo`. The guide's §4.12
spells this out.
- `rowHeight="auto"` is opt-in; the default fixed-height virtualization
path is unchanged and remains the fast path for dense, single-line grids
(users, transactions, etc.).
- Screenshots are JPEG this round — the local capture tooling's PNG path
was producing blank frames, so the new set is `.jpg` end-to-end. Same
viewports, same seeded project.

## Test plan

- [ ] `pnpm lint` passes
- [ ] `pnpm typecheck` passes
- [ ] Load the dashboard and verify every migrated surface renders,
sorts, searches, paginates, and handles row-click navigation:
  - [ ] Overview (line chart + donut metrics)
- [ ] Users list + user detail (teams, sessions, permissions, API keys)
  - [ ] Teams list + team detail (members, permissions)
  - [ ] Domains
  - [ ] Emails, email-sent, email-outbox, email-drafts
  - [ ] Webhooks list + endpoint detail
  - [ ] Payments customers, product detail, transactions (new toolbar)
  - [ ] External DB sync
  - [ ] Analytics query table (sticky header)
- [ ] Verify infinite-scroll surfaces (domains, etc.) load additional
rows on scroll
- [ ] Verify sticky header stays below the page header in light and dark
themes
- [ ] Verify CSV export produces correct output on a representative
table
- [ ] Verify column resize, visibility toggle, and sort work across
themes
- [ ] Verify `cellOverflow: "wrap"` rows grow to fit when
`rowHeight="auto"` and clip when `rowHeight` is numeric
- [ ] Spot-check AI analytics queries against the new schema context
(contact_channels, teams, email_outboxes, …)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Unified table components across dashboard with improved infinite
pagination and quick search.

* **Improvements**
* Enhanced table performance with sticky headers and better row height
handling.
* Improved sorting, filtering, and data loading with consistent state
management.
  * Better visual consistency across all data grids and table layouts.

* **UI/Styling**
* Refined table styling for better text truncation and content wrapping.
  * Optimized layout spacing and alignment across dashboard tables.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Developing-Gamer <maxcodes11110@gmail.com>
Co-authored-by: Armaan Jain <84474476+Developing-Gamer@users.noreply.github.com>
Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com>
2026-04-27 13:50:24 -07:00
..
prisma Speed up seed script by a lot 2026-04-18 17:29:21 -07:00
scripts Fix ClickHouse OOM in MAU query + optimize /internal/metrics route (#1344) 2026-04-19 22:57:46 -07:00
src Dashboard: DataGrid refactor + layout (stacked on overview-revamp) (#1338) 2026-04-27 13:50:24 -07:00
.env LLM MCP Flow (#1321) 2026-04-15 17:57:08 +00:00
.env.development LLM MCP Flow (#1321) 2026-04-15 17:57:08 +00:00
.eslintrc.cjs tsup for stack-shared (#647) 2025-04-28 21:26:52 -07:00
.gitignore private files n sm build shit (#1276) 2026-03-23 12:31:36 -07:00
instrumentation-client.ts Upgrade backend to Next.js 16 2025-12-12 16:59:07 -08:00
LICENSE Split backend and dashboard (#83) 2024-06-18 15:49:31 +02:00
next.config.mjs private files n sm build shit (#1276) 2026-03-23 12:31:36 -07:00
package.json chore: update package versions 2026-04-20 19:06:56 -07:00
prisma.config.ts [Fix]: Assortment of Bugs with Timefold Table and Payments (#1348) 2026-04-18 14:17:24 -07:00
tsconfig.json Fix lint 2026-02-27 09:59:26 -08:00
vercel.json External db sync (#1036) 2026-02-05 12:04:31 -08:00
vitest.config.ts Customizable ports (#962) 2025-10-20 15:24:47 -07:00
vitest.setup.ts Customizable ports (#962) 2025-10-20 15:24:47 -07:00