Skip to content

Overview page loading indicator#1004

Merged
N2D4 merged 1 commit intodevfrom
overview-loading-indicator
Nov 6, 2025
Merged

Overview page loading indicator#1004
N2D4 merged 1 commit intodevfrom
overview-loading-indicator

Conversation

@N2D4
Copy link
Contributor

@N2D4 N2D4 commented Nov 6, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced dashboard metrics visualizations with daily signup and active user trend charts
    • Added geographic distribution display showing users by country
    • Improved loading state feedback with "Recalculating metrics" messaging
  • Improvements

    • Optimized data loading performance for faster dashboard rendering

Copilot AI review requested due to automatic review settings November 6, 2025 19:19
@vercel
Copy link

vercel bot commented Nov 6, 2025

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

Project Deployment Preview Comments Updated (UTC)
stack-backend Ready Ready Preview Comment Nov 6, 2025 7:26pm
stack-dashboard Ready Ready Preview Comment Nov 6, 2025 7:26pm
stack-demo Ready Ready Preview Comment Nov 6, 2025 7:26pm
stack-docs Ready Ready Preview Comment Nov 6, 2025 7:26pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 6, 2025

Walkthrough

The pull request refactors the metrics dashboard UI layer by extracting data-fetching logic into dedicated data-driven components, simplifies page-level state management, and consolidates backend version-checking conditions. Backend imports are reorganized, and prefetch strategies are updated to preload metrics and user data across dashboard routes.

Changes

Cohort / File(s) Summary
Backend API routes
apps/backend/src/app/api/latest/check-version/route.ts, apps/backend/src/app/api/latest/internal/metrics/route.tsx
Version checking logic consolidated into a single condition; metrics route imports reorganized to include usersCrudHandlers.
Dashboard metrics data-driven components
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/charts-section-with-data.tsx, apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe-section-with-data.tsx, apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-loading.tsx
New client components added to encapsulate data fetching and rendering for charts, globe visualization, and loading fallback states.
Dashboard metrics page refactoring
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-page.tsx, apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/page-client.tsx
Metrics page restructured to delegate rendering to new data-driven components wrapped in Suspense; page-client simplified to determine state based on user count instead of metrics internals.
Prefetch configuration
apps/dashboard/src/lib/prefetch/url-prefetcher.tsx
Prefetchers updated to preload metrics (with and without anonymous data) and single-user queries for dashboard routes.
Template implementation
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
New \_refreshUsers override added to concurrently refresh user cache and both variations of metrics.

Sequence Diagram

sequenceDiagram
    participant MetricsPage as Metrics Page
    participant GlobeSec as GlobeSectionWithData
    participant ChartsSec as ChartsSectionWithData
    participant AdminApp as useAdminApp
    participant Metrics as useMetrics Hook
    participant Users as useUsers Hook

    rect rgb(200, 220, 240)
    Note over MetricsPage: Old Flow (Direct Rendering)
    MetricsPage->>Metrics: Direct fetch metrics
    MetricsPage->>Users: Direct fetch users
    MetricsPage->>MetricsPage: Render charts/globe inline
    end

    rect rgb(220, 240, 200)
    Note over MetricsPage: New Flow (Component Delegation)
    MetricsPage->>GlobeSec: Render with Suspense
    GlobeSec->>AdminApp: useAdminApp(projectId)
    AdminApp->>Metrics: useMetrics(includeAnonymous)
    Metrics-->>GlobeSec: metrics data
    GlobeSec->>GlobeSec: Render globe

    MetricsPage->>ChartsSec: Render with Suspense
    ChartsSec->>AdminApp: useAdminApp(projectId)
    AdminApp->>Metrics: useMetrics(includeAnonymous)
    AdminApp->>Users: useUsers()
    Metrics-->>ChartsSec: metrics data
    Users-->>ChartsSec: user data
    ChartsSec->>ChartsSec: Render charts & tables
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Metrics page refactoring: Significant restructuring moving from inline rendering to component delegation; requires verification that data flow through Suspense boundaries is correct and includeAnonymous state propagation is consistent.
  • New data-driven components: Three new components (ChartsSectionWithData, GlobeSectionWithData, MetricsLoadingFallback) with internal configurations and nested rendering logic; review should confirm chart configurations match intended behavior and error boundaries are properly applied.
  • State management change in page-client.tsx: Logic shift from metrics-based state determination to user-count-based state determination; verify this aligns with intended behavior and doesn't introduce edge cases.
  • Prefetch strategy expansion: Multiple new prefetch calls added across routes; validate that prefetch timing and data shape match component consumption.

Possibly related PRs

  • Config override CRUD #803: Modifies the same admin-app-impl.ts file; adds config override caching alongside the new _refreshUsers concurrent refresh logic.
  • Improved anonymous users #857: Updates apps/backend/src/app/api/latest/internal/metrics/route.tsx; related to backend metrics handling alongside version checking refactors in this PR.

Poem

🐰 Metrics scattered far and wide,
Now with Suspense as our guide,
Separate components, data organized tight,
Dashboard refactored—a rabbit's delight! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only the repository's CONTRIBUTING.md template without any actual content describing the changes, objectives, or rationale. Add a detailed description explaining the purpose of the loading indicator, which components were modified, and how Suspense is used for async data fetching.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Overview page loading indicator' directly relates to the main change—adding loading UI (MetricsLoadingFallback component) to the overview page wrapped in Suspense boundaries.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch overview-loading-indicator

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the metrics loading architecture to improve performance and user experience. The key changes include implementing Suspense boundaries for asynchronous metrics data, refreshing metrics cache when users are updated, and enabling prefetching of metrics data.

  • Adds metrics cache refresh when users are updated in the admin app
  • Implements Suspense-based loading for metrics components with dedicated loading fallbacks
  • Enables prefetching of metrics and user data for improved perceived performance

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts Override _refreshUsers to also refresh metrics cache for consistency
apps/dashboard/src/lib/prefetch/url-prefetcher.tsx Enable prefetching of metrics and user data, remove TODO comments
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/page-client.tsx Replace metrics-based check with simpler useUsers to determine initial page state
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-page.tsx Extract metrics data fetching into separate components wrapped with Suspense
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-loading.tsx New loading fallback component for Suspense boundaries
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe-section-with-data.tsx New data wrapper component for globe section with metrics data
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/charts-section-with-data.tsx New data wrapper component for charts section with metrics data
apps/backend/src/app/api/latest/internal/metrics/route.tsx Minor import reordering for consistency
apps/backend/src/app/api/latest/check-version/route.ts Simplify version check logic by consolidating conditions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +52 to 55
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
return err(true, `You are running a version of Stack Auth that is not the same as the newest known version (v${clientVersion} !== v${serverVersion}). Please update to the latest version as soon as possible to ensure that you get the latest feature and security updates.`);
}

Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

This condition is unreachable. Line 49 already checks semver.lt(clientVersion, serverVersion), which catches all cases where the client is older than the server. The condition !semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion logically simplifies to clientVersion < serverVersion, which is already handled. This appears to be a regression from removing the semver.gt check. Consider either removing this unreachable code or restoring the original logic that checked for newer client versions separately.

Suggested change
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
return err(true, `You are running a version of Stack Auth that is not the same as the newest known version (v${clientVersion} !== v${serverVersion}). Please update to the latest version as soon as possible to ensure that you get the latest feature and security updates.`);
}

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +8

const stackAppInternalsSymbol = Symbol.for("StackAuth--DO-NOT-USE-OR-YOU-WILL-BE-FIRED--StackAppInternals");

Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

The stackAppInternalsSymbol is duplicated across multiple files (globe-section-with-data.tsx, charts-section-with-data.tsx). This symbol is already imported in url-prefetcher.tsx from '@stackframe/stack' (line 4). Consider importing it from the package instead of redefining it to reduce duplication and ensure consistency.

Suggested change
const stackAppInternalsSymbol = Symbol.for("StackAuth--DO-NOT-USE-OR-YOU-WILL-BE-FIRED--StackAppInternals");
import { stackAppInternalsSymbol } from '@stackframe/stack';

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +11
import { UserAvatar } from '@stackframe/stack';
import { fromNow } from '@stackframe/stack-shared/dist/utils/dates';
import { Card, CardContent, CardHeader, CardTitle, Table, TableBody, TableCell, TableRow, Typography } from '@stackframe/stack-ui';
import { useAdminApp } from '../use-admin-app';
import { DonutChartDisplay, LineChartDisplay, LineChartDisplayConfig } from './line-chart';

const stackAppInternalsSymbol = Symbol.for("StackAuth--DO-NOT-USE-OR-YOU-WILL-BE-FIRED--StackAppInternals");

Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

The stackAppInternalsSymbol is duplicated across multiple files (globe-section-with-data.tsx, charts-section-with-data.tsx). This symbol is already exported from '@stackframe/stack' and imported in url-prefetcher.tsx. Consider importing it from the package instead of redefining it to reduce duplication and ensure consistency.

Suggested change
import { UserAvatar } from '@stackframe/stack';
import { fromNow } from '@stackframe/stack-shared/dist/utils/dates';
import { Card, CardContent, CardHeader, CardTitle, Table, TableBody, TableCell, TableRow, Typography } from '@stackframe/stack-ui';
import { useAdminApp } from '../use-admin-app';
import { DonutChartDisplay, LineChartDisplay, LineChartDisplayConfig } from './line-chart';
const stackAppInternalsSymbol = Symbol.for("StackAuth--DO-NOT-USE-OR-YOU-WILL-BE-FIRED--StackAppInternals");
import { UserAvatar, stackAppInternalsSymbol } from '@stackframe/stack';
import { fromNow } from '@stackframe/stack-shared/dist/utils/dates';
import { Card, CardContent, CardHeader, CardTitle, Table, TableBody, TableCell, TableRow, Typography } from '@stackframe/stack-ui';
import { useAdminApp } from '../use-admin-app';
import { DonutChartDisplay, LineChartDisplay, LineChartDisplayConfig } from './line-chart';

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Overview

Greptile Summary

Added loading indicators to the overview page metrics by wrapping data-fetching components in React Suspense boundaries, improving perceived performance and user experience during metrics recalculation.

Key changes:

  • Extracted globe and charts sections into separate components (GlobeSectionWithData, ChartsSectionWithData) that call useMetrics() internally
  • Wrapped both components with Suspense boundaries showing MetricsLoadingFallback during data fetching
  • Changed initial page determination from checking useMetrics() to useUsers({limit: 1}) for faster initial load
  • Re-enabled metrics prefetching in URL prefetcher to populate cache before navigation
  • Added metrics cache refresh when user data is updated for better consistency
  • Simplified version check logic (but introduced a bug that removes dev branch warning)

Confidence Score: 3/5

  • This PR is mostly safe but contains a logic bug in version checking that needs fixing
  • The loading indicator implementation is well-designed and follows React best practices with proper Suspense usage. However, the version check logic change in check-version/route.ts contains a critical bug where the condition !semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion will never trigger when client > server, effectively removing the dev branch warning. The dashboard changes are solid and improve UX.
  • apps/backend/src/app/api/latest/check-version/route.ts requires immediate attention due to flawed version check logic

Important Files Changed

File Analysis

Filename Score Overview
apps/backend/src/app/api/latest/check-version/route.ts 3/5 Simplified version check logic by combining two conditions, but the new logic may have unintended behavior
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-page.tsx 5/5 Wrapped globe and charts sections with Suspense boundaries for loading state handling
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/page-client.tsx 5/5 Switched from using metrics to useUsers for initial page determination, improving load time
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts 5/5 Added metrics cache refresh when users data is refreshed for better data consistency

Sequence Diagram

sequenceDiagram
    participant User
    participant PageClient
    participant MetricsPage
    participant Suspense
    participant GlobeSection
    participant ChartsSection
    participant AdminApp
    participant MetricsAPI
    
    User->>PageClient: Navigate to overview page
    PageClient->>AdminApp: useUsers({limit: 1})
    AdminApp-->>PageClient: user count
    
    alt users.length === 0
        PageClient->>User: Show SetupPage
    else users.length > 0
        PageClient->>MetricsPage: Render MetricsPage
        
        MetricsPage->>Suspense: Wrap GlobeSection
        Suspense->>GlobeSection: Attempt render
        GlobeSection->>AdminApp: useMetrics(includeAnonymous)
        
        alt Metrics cached
            AdminApp-->>GlobeSection: Return cached data
            GlobeSection-->>User: Display globe
        else Metrics not cached
            AdminApp->>MetricsAPI: Fetch metrics
            Suspense-->>User: Show MetricsLoadingFallback
            MetricsAPI-->>AdminApp: Return metrics data
            AdminApp-->>GlobeSection: Provide metrics
            GlobeSection-->>User: Display globe
        end
        
        MetricsPage->>Suspense: Wrap ChartsSection
        Suspense->>ChartsSection: Attempt render
        ChartsSection->>AdminApp: useMetrics(includeAnonymous)
        
        alt Metrics cached
            AdminApp-->>ChartsSection: Return cached data
            ChartsSection-->>User: Display charts
        else Metrics not cached
            AdminApp->>MetricsAPI: Fetch metrics
            Suspense-->>User: Show MetricsLoadingFallback
            MetricsAPI-->>AdminApp: Return metrics data
            AdminApp-->>ChartsSection: Provide metrics
            ChartsSection-->>User: Display charts
        end
    end
    
    Note over AdminApp,MetricsAPI: Metrics cached for 1 hour
    Note over AdminApp: Cache refreshed on user data updates
Loading

9 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +52 to 54
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
return err(true, `You are running a version of Stack Auth that is not the same as the newest known version (v${clientVersion} !== v${serverVersion}). Please update to the latest version as soon as possible to ensure that you get the latest feature and security updates.`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: logic issue with new condition - when clientVersion > serverVersion, the condition !semver.gt(clientVersion, serverVersion) is false, so the entire expression is false and no error is returned. this removes the previous dev branch warning entirely

Suggested change
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
return err(true, `You are running a version of Stack Auth that is not the same as the newest known version (v${clientVersion} !== v${serverVersion}). Please update to the latest version as soon as possible to ensure that you get the latest feature and security updates.`);
}
if (semver.gt(clientVersion, serverVersion)) {
return err(false, `You are running a version of Stack Auth that is newer than the newest known version (v${clientVersion} > v${serverVersion}). This is weird. Are you running on a development branch?`);
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/backend/src/app/api/latest/check-version/route.ts
Line: 52:54

Comment:
**logic:** logic issue with new condition - when `clientVersion > serverVersion`, the condition `!semver.gt(clientVersion, serverVersion)` is false, so the entire expression is false and no error is returned. this removes the previous dev branch warning entirely

```suggestion
    if (semver.gt(clientVersion, serverVersion)) {
      return err(false, `You are running a version of Stack Auth that is newer than the newest known version (v${clientVersion} > v${serverVersion}). This is weird. Are you running on a development branch?`);
    }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c816a0 and 90807e6.

📒 Files selected for processing (9)
  • apps/backend/src/app/api/latest/check-version/route.ts (1 hunks)
  • apps/backend/src/app/api/latest/internal/metrics/route.tsx (1 hunks)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/charts-section-with-data.tsx (1 hunks)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe-section-with-data.tsx (1 hunks)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-loading.tsx (1 hunks)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-page.tsx (3 hunks)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/page-client.tsx (1 hunks)
  • apps/dashboard/src/lib/prefetch/url-prefetcher.tsx (2 hunks)
  • packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-11T04:13:19.308Z
Learnt from: N2D4
Repo: stack-auth/stack-auth PR: 943
File: examples/convex/app/action/page.tsx:23-28
Timestamp: 2025-10-11T04:13:19.308Z
Learning: In the stack-auth codebase, use `runAsynchronouslyWithAlert` from `stackframe/stack-shared/dist/utils/promises` for async button click handlers and form submissions instead of manual try/catch blocks. This utility automatically handles errors and shows alerts to users.

Applied to files:

  • apps/dashboard/src/lib/prefetch/url-prefetcher.tsx
🧬 Code graph analysis (6)
apps/backend/src/app/api/latest/check-version/route.ts (1)
packages/template/src/lib/stack-app/apps/implementations/common.ts (1)
  • clientVersion (17-17)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe-section-with-data.tsx (3)
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
  • stackAppInternalsSymbol (444-453)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/use-admin-app.tsx (1)
  • useAdminApp (29-44)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe.tsx (1)
  • GlobeSection (31-325)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/charts-section-with-data.tsx (5)
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
  • stackAppInternalsSymbol (444-453)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/line-chart.tsx (3)
  • LineChartDisplayConfig (6-10)
  • LineChartDisplay (17-69)
  • DonutChartDisplay (147-183)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/use-admin-app.tsx (1)
  • useAdminApp (29-44)
apps/dashboard/src/components/router.tsx (1)
  • useRouter (15-33)
packages/stack-shared/src/utils/dates.tsx (1)
  • fromNow (28-30)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-loading.tsx (1)
packages/stack-ui/src/components/ui/card.tsx (1)
  • CardContent (87-87)
apps/dashboard/src/lib/prefetch/url-prefetcher.tsx (2)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/use-admin-app.tsx (1)
  • useAdminApp (29-44)
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
  • stackAppInternalsSymbol (444-453)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-page.tsx (3)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/metrics-loading.tsx (1)
  • MetricsLoadingFallback (6-18)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe-section-with-data.tsx (1)
  • GlobeSectionWithData (9-18)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/charts-section-with-data.tsx (1)
  • ChartsSectionWithData (34-114)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Agent
  • GitHub Check: Vercel Agent Review
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: docker
  • GitHub Check: build (22.x)
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: all-good
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: setup-tests
🔇 Additional comments (2)
apps/backend/src/app/api/latest/internal/metrics/route.tsx (1)

2-2: LGTM! Import reorganization improves maintainability.

The import consolidation and addition of the Prisma namespace are correct. All imports are properly used throughout the file:

  • Prisma namespace is required for SQL template tags (line 47)
  • usersCrudHandlers is used for the admin list call (line 287)

Also applies to: 5-5, 10-10

packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)

436-442: Nice optimization for preloading metrics with user data!

The concurrent refresh of users and both metrics variants (with and without anonymous users) aligns well with the PR's goal of improving the overview page loading experience. Using Promise.all ensures these independent operations run in parallel for better performance.

Comment on lines +52 to 54
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
return err(true, `You are running a version of Stack Auth that is not the same as the newest known version (v${clientVersion} !== v${serverVersion}). Please update to the latest version as soon as possible to ensure that you get the latest feature and security updates.`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Client version > server is no longer flagged

The new condition (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) only fires when the client is older (because the < case already returned earlier). If the client runs a newer build (patch ahead), we now fall through and report upToDate: true, which regresses the previous behaviour and hides a real mismatch. Please restore an explicit semver.gt guard for the "client newer than server" scenario.

-    if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
+    if (semver.gt(clientVersion, serverVersion)) {
+      return err(true, `You are running a version of Stack Auth that is not the same as the newest known version (v${clientVersion} !== v${serverVersion}). Please update to the latest version as soon as possible to ensure that you get the latest feature and security updates.`);
+    }
+    if (clientVersion !== serverVersion) {

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/backend/src/app/api/latest/check-version/route.ts around lines 52 to 54,
the conditional that checks versions was changed so the "client newer than
server" case is no longer explicitly handled; reinstate an explicit
semver.gt(clientVersion, serverVersion) branch to detect when the client is
newer than the server and return the appropriate err response (same shape as
before) instead of falling through to upToDate:true, keeping the existing
messages and status format for that branch.

return err(false, `You are running a version of Stack Auth that is newer than the newest known version (v${clientVersion} > v${serverVersion}). This is weird. Are you running on a development branch?`);
}
if (clientVersion !== serverVersion) {
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
Copy link

Choose a reason for hiding this comment

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

Suggested change
if (!semver.gt(clientVersion, serverVersion) && clientVersion !== serverVersion) {
if (semver.gt(clientVersion, serverVersion)) {
return err(false, `You are running a version of Stack Auth that is newer than the newest known version (v${clientVersion} > v${serverVersion}). This is weird. Are you running on a development branch?`);
}
if (clientVersion !== serverVersion) {

The version check logic was refactored in a way that removes the handler for when the client version is newer than the server version. This will cause the API to incorrectly return "upToDate: true" when a newer client connects.

View Details

Analysis

Version check API incorrectly returns upToDate=true for newer client versions

What fails: /api/latest/check-version route in apps/backend/src/app/api/latest/check-version/route.ts line 52 combines semver.gt() and !== checks incorrectly, causing newer client versions to fall through to upToDate=true

How to reproduce:

# Send POST request with client version newer than server (same major.minor)
curl -X POST /api/latest/check-version \
  -H "Content-Type: application/json" \
  -d '{"clientVersion": "2.8.50"}' 
# When server version is 2.8.49

Result: Returns {"upToDate": true} instead of handling the newer client case

Expected: Should return error with message about client being newer than server, per original git history which had separate semver.gt(clientVersion, serverVersion) check

@N2D4 N2D4 merged commit 3b34e26 into dev Nov 6, 2025
36 checks passed
@N2D4 N2D4 deleted the overview-loading-indicator branch November 6, 2025 19:41
@coderabbitai coderabbitai bot mentioned this pull request Nov 27, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant