Skip to content

StackHandler is now a client component#988

Merged
N2D4 merged 13 commits intodevfrom
client-stack-handler
Nov 6, 2025
Merged

StackHandler is now a client component#988
N2D4 merged 13 commits intodevfrom
client-stack-handler

Conversation

@N2D4
Copy link
Contributor

@N2D4 N2D4 commented Oct 30, 2025

Summary by CodeRabbit

  • New Features

    • Unified, client-driven auth/account handler with improved routing and alias handling for sign-in, sign-up, verification, and account flows.
  • Tests

    • End-to-end tests added for listing users, verifying anonymous-user filtering, ordering, and default behavior.
  • Refactor

    • Simplified handler architecture by delegating rendering to a single client component for clearer behavior and easier maintenance.

Copilot AI review requested due to automatic review settings October 30, 2025 00:18
@vercel
Copy link

vercel bot commented Oct 30, 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 6:41pm
stack-dashboard Ready Ready Preview Comment Nov 6, 2025 6:41pm
stack-demo Ready Ready Preview Comment Nov 6, 2025 6:41pm
stack-docs Ready Ready Preview Comment Nov 6, 2025 6:41pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

Warning

Rate limit exceeded

@N2D4 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 22 minutes and 59 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 5c95e8b and 75e07c2.

📒 Files selected for processing (1)
  • packages/template/src/components-page/stack-handler-client.tsx (1 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Refactors StackHandler to delegate routing/rendering to a new StackHandlerClient; updates init-stack generator to emit a no-arg Next.js Handler; adds an e2e test for listing users (including anonymous), changes dashboard tsconfig JSX runtime to "preserve", and adds a backend development env var.

Changes

Cohort / File(s) Summary
Environment
apps/backend/.env.development
Added STACK_SEED_INTERNAL_PROJECT_USER_GITHUB_ID=admin@example.com.
TypeScript config
apps/dashboard/tsconfig.json
Changed JSX runtime from "react-jsx" to "preserve".
E2E tests
apps/e2e/tests/js/list-users.test.ts
Added test covering user listing with includeAnonymous true/false and default behavior; creates regular and anonymous users and asserts results and ordering.
Init generator
packages/init-stack/src/index.ts
Generator now outputs a no-argument Handler that renders StackHandler directly; removed imports/usage of stackServerApp and handler props in the generated code.
Handler implementation
packages/template/src/components-page/stack-handler-client.tsx, packages/template/src/components-page/stack-handler.tsx
Added StackHandlerClient (exporting BaseHandlerProps) with alias-aware routing, path normalization, redirect logic, and component mapping; replaced previous multi-platform stack-handler.tsx with a thin wrapper delegating to StackHandlerClient (legacy props kept as deprecated).

Sequence Diagram(s)

sequenceDiagram
    participant App as App / Caller
    participant Wrapper as StackHandler (wrapper)
    participant Client as StackHandlerClient
    participant RouteMap as Route Mapping & Aliases
    participant Component as Resolved Component

    rect rgb(240,245,255)
      Note over App,Wrapper: New flow (post-change)
      App->>Wrapper: render(BaseHandlerProps)
      Wrapper->>Client: delegate props
      Client->>Client: normalize path & search params
      Client->>RouteMap: resolve route / check aliases
      alt alias match
        RouteMap-->>Client: canonical route
        Client->>App: redirect (replace)
      else matched route
        Client->>Component: renderComponent with props
        Component-->>Client: UI
        Client-->>Wrapper: UI
        Wrapper-->>App: UI
      end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Inspect route alias mapping and canonical redirect correctness in packages/template/src/components-page/stack-handler-client.tsx.
  • Verify backward-compatibility/deprecation handling in the StackHandler wrapper for callers still passing app/routeProps.
  • Confirm packages/init-stack/src/index.ts output compiles as valid Next.js handler files.
  • Review e2e test for correct setup/teardown and flakiness risk.

Possibly related PRs

Poem

🐰 I hopped through modules, neat and spry,

Swapped handlers so the client flies high,
Tests now count each hidden friend,
A dev env var tucked in to send,
Small hops, big code — carrots for the sky!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is empty except for a template comment about reading CONTRIBUTING.md, providing no actual implementation details or context. Add a comprehensive description explaining the refactoring rationale, how StackHandler now delegates to StackHandlerClient, migration impacts, and any breaking changes for reviewers.
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 'StackHandler is now a client component' accurately reflects the main architectural change shown in the diff: StackHandler was refactored to delegate to StackHandlerClient and is now a client component.

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 StackHandler component to simplify its API by removing the need for passing app, routeProps, params, and searchParams props. The main implementation has been moved to a new client component (StackHandlerClient) that uses hooks to retrieve necessary data, while the original file becomes a thin wrapper that maintains backward compatibility by accepting deprecated parameters.

  • Moved StackHandler implementation to a new stack-handler-client.tsx file marked with "use client"
  • Original stack-handler.tsx now serves as a compatibility wrapper that forwards props to StackHandlerClient
  • Updated code generation in init-stack to use simplified API without app/routeProps parameters

Reviewed Changes

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

Show a summary per file
File Description
packages/template/src/components-page/stack-handler.tsx Replaced with minimal wrapper that accepts deprecated props and delegates to StackHandlerClient
packages/template/src/components-page/stack-handler-client.tsx New client component containing the refactored StackHandler logic using hooks
packages/init-stack/src/index.ts Updated handler file generation to use simplified StackHandler API
apps/e2e/tests/js/list-users.test.ts Added tests for listing users with/without anonymous users
apps/dashboard/tsconfig.json Changed JSX compilation from react-jsx to preserve
apps/backend/.env.development Added STACK_SEED_INTERNAL_PROJECT_USER_GITHUB_ID configuration

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

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

Refactored StackHandler to be a client component by extracting logic into StackHandlerClient and using React hooks instead of server-side props.

  • Extracted all routing logic from stack-handler.tsx into new stack-handler-client.tsx with "use client" directive
  • StackHandler now acts as a thin wrapper that accepts deprecated props for backward compatibility but delegates to StackHandlerClient
  • Uses useStackApp() hook to access app context instead of requiring app prop
  • Uses Next.js client hooks (usePathname, useSearchParams) instead of server-side params and searchParams props
  • Updated handler code generation in init-stack to generate cleaner code without server-side props
  • Changed dashboard tsconfig JSX mode from react-jsx to preserve for Next.js compatibility
  • Added E2E tests for anonymous user listing functionality

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Clean architectural refactoring that improves code organization by separating client and server concerns. Maintains full backward compatibility through deprecated props. E2E tests added for new functionality. All changes are well-structured and follow Next.js best practices for client components.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
packages/template/src/components-page/stack-handler.tsx 5/5 Converted to thin wrapper that delegates to StackHandlerClient, maintains backward compatibility with deprecated props
packages/template/src/components-page/stack-handler-client.tsx 5/5 New client component extracted from stack-handler.tsx, uses useStackApp hook and Next.js client hooks (usePathname, useSearchParams)
packages/init-stack/src/index.ts 5/5 Updated generated handler code to remove app and routeProps parameters, now generates simpler <StackHandler fullPage /> component

Sequence Diagram

sequenceDiagram
    participant User
    participant NextJS as Next.js Route
    participant SH as StackHandler
    participant SHC as StackHandlerClient
    participant Hooks as useStackApp/usePathname/useSearchParams
    participant Provider as StackProvider (Context)
    participant Component as Auth Component

    User->>NextJS: Navigate to /handler/sign-in
    NextJS->>SH: Render StackHandler (Server)
    Note over SH: Accepts deprecated props (app, routeProps)<br/>but ignores them
    SH->>SHC: Delegate to StackHandlerClient (Client)
    activate SHC
    SHC->>Hooks: useStackApp()
    Hooks->>Provider: Access StackContext
    Provider-->>Hooks: Return stackApp instance
    Hooks-->>SHC: stackApp
    SHC->>Hooks: usePathname() & useSearchParams()
    Hooks-->>SHC: pathname & searchParams
    SHC->>SHC: Parse path relative to handler URL
    SHC->>SHC: Route to appropriate component
    SHC->>Component: Render SignIn component
    deactivate SHC
    Component-->>User: Display sign-in page
Loading

6 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

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

♻️ Duplicate comments (3)
packages/template/src/components-page/stack-handler-client.tsx (1)

212-222: useMemo dependencies are correct for cross-platform support.

The past review comment flagged origin in the dependency array as misleading since it's a constant in the Next.js path. However, examining the platform-conditional code (lines 200-210), origin is dynamic in the React platform (line 209: window.location.origin). The dependency array correctly includes all values used in the memoized computation for both platforms.

packages/init-stack/src/index.ts (1)

948-951: LGTM! Simplified handler aligns with client-driven architecture.

The handler generation is now streamlined to just render <StackHandler fullPage /> without passing app or routeProps, which correctly delegates all routing logic to the new StackHandlerClient component introduced in this PR. This simplification improves maintainability and aligns with the refactoring objectives.

The spacing issue from the past review comment has also been resolved.

packages/template/src/components-page/stack-handler.tsx (1)

5-5: Fix the typo in the comment.

The comment states "returns " but the implementation actually returns <StackHandlerClient />.

Apply this diff:

-// This file exists as a component that can be both client and server, ignores its parameters, and returns <StackHandler />
+// This file exists as a component that can be both client and server, ignores its parameters, and returns <StackHandlerClient />
🧹 Nitpick comments (2)
packages/template/src/components-page/stack-handler-client.tsx (1)

60-65: Clarify misleading comment about path alias handling.

The comment on line 61 states "also includes the uppercase and non-dashed versions," but the pathAliases object only contains lowercase, dashed versions. The actual case-insensitive and dash-removal logic is implemented later in the renderComponent function (line 186), not in this object definition.

Consider updating the comment to accurately reflect that this object defines explicit aliases, while the default case in renderComponent handles case variations.

apps/backend/.env.development (1)

9-9: Clarify variable naming; value should be a GitHub user ID, not an email address.

The variable STACK_SEED_INTERNAL_PROJECT_USER_GITHUB_ID is used as providerAccountId when creating GitHub OAuth accounts (seed.ts, lines 329–365). GitHub OAuth expects a numeric user ID, but the value admin@example.com is an email address, creating a semantic mismatch between the variable name and its actual value.

For the development seed, either:

  1. Rename to STACK_SEED_INTERNAL_PROJECT_USER_GITHUB_ACCOUNT_ID and update the value to a numeric GitHub user ID (e.g., "123456"), or
  2. If email is intentional as a placeholder, rename to STACK_SEED_INTERNAL_PROJECT_USER_OAUTH_IDENTIFIER to reflect that it accepts flexible identifiers

Add an inline comment explaining the expected format.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e36f0e and 6fcf292.

📒 Files selected for processing (6)
  • apps/backend/.env.development (1 hunks)
  • apps/dashboard/tsconfig.json (1 hunks)
  • apps/e2e/tests/js/list-users.test.ts (1 hunks)
  • packages/init-stack/src/index.ts (1 hunks)
  • packages/template/src/components-page/stack-handler-client.tsx (1 hunks)
  • packages/template/src/components-page/stack-handler.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-12T17:55:06.710Z
Learnt from: madster456
Repo: stack-auth/stack-auth PR: 769
File: apps/backend/.env:67-71
Timestamp: 2025-08-12T17:55:06.710Z
Learning: In the stack-auth project, .env files use inline comments after the = sign (e.g., KEY=# description) as a consistent pattern throughout the configuration file. The maintainers prefer this format over separate comment lines above each key.

Applied to files:

  • apps/backend/.env.development
🧬 Code graph analysis (3)
packages/template/src/components-page/stack-handler.tsx (1)
packages/template/src/components-page/stack-handler-client.tsx (2)
  • BaseHandlerProps (67-72)
  • StackHandlerClient (196-279)
packages/template/src/components-page/stack-handler-client.tsx (7)
packages/template/src/components-page/sign-out.tsx (1)
  • SignOut (12-20)
packages/template/src/components-page/oauth-callback.tsx (1)
  • OAuthCallback (12-61)
packages/template/src/components-page/magic-link-callback.tsx (1)
  • MagicLinkCallback (16-87)
packages/template/src/components-page/mfa.tsx (1)
  • MFA (181-214)
packages/stack-shared/src/utils/errors.tsx (1)
  • StackAssertionError (69-85)
packages/stack-shared/src/utils/urls.tsx (2)
  • url (278-280)
  • getRelativePart (256-258)
packages/stack-shared/src/utils/objects.tsx (2)
  • FilterUndefined (365-367)
  • filterUndefined (373-375)
apps/e2e/tests/js/list-users.test.ts (2)
apps/e2e/tests/helpers.ts (1)
  • it (12-12)
apps/e2e/tests/js/js-helpers.ts (1)
  • createApp (41-86)
⏰ 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). (12)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: setup-tests
  • GitHub Check: build (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test
  • GitHub Check: build (22.x)
  • GitHub Check: all-good
  • GitHub Check: Security Check
🔇 Additional comments (6)
apps/e2e/tests/js/list-users.test.ts (2)

4-30: LGTM! Comprehensive test coverage for anonymous user filtering.

The test correctly verifies that:

  1. Anonymous users are created with distinct IDs
  2. includeAnonymous: false excludes anonymous users from results
  3. includeAnonymous: true includes all users in sign-up order

32-50: LGTM! Validates default behavior correctly.

This test confirms that anonymous users are excluded by default when the includeAnonymous parameter is not specified, which is the expected behavior for backward compatibility.

packages/template/src/components-page/stack-handler-client.tsx (2)

224-242: LGTM! Redirect logic correctly preserves state.

The redirectIfNotHandler helper properly:

  1. Avoids unnecessary redirects when already on the handler path
  2. Preserves query parameters during redirection
  3. Uses RedirectType.replace to avoid polluting browser history

244-278: LGTM! Clean delegation and cross-platform handling.

The main render logic correctly:

  1. Delegates routing to renderComponent with all necessary context
  2. Provides platform-appropriate not-found handling (Next.js notFound() vs React custom UI)
  3. Handles redirect responses uniformly across platforms
apps/dashboard/tsconfig.json (1)

17-17: JSX transformation change is correct for Next.js; full build verification unavailable in this environment.

The "jsx": "preserve" setting is a mandatory change Next.js makes, as it implements its own optimized JSX transform. This configuration aligns with the official @tsconfig/next base configuration. With preserve mode, JSX is kept as part of the output to be further consumed by another transform step (e.g. Next.js), and the output will have a .jsx file extension.

The configuration is valid and standard. However, a full build verification was not possible in the sandbox environment due to missing monorepo dependencies, so please confirm that builds succeed in your local development environment or CI/CD pipeline.

packages/template/src/components-page/stack-handler.tsx (1)

7-31: LGTM! Clean backward-compatibility wrapper.

The implementation correctly:

  • Imports and delegates to StackHandlerClient for actual rendering logic
  • Accepts deprecated props (app, routeProps, params, searchParams) with proper JSDoc deprecation notices
  • Silently ignores deprecated props while forwarding valid props
  • Maintains type safety by requiring BaseHandlerProps (which includes fullPage)

This design elegantly prevents the "Classes or null prototypes are not supported" error while maintaining backward compatibility and guiding users toward the new API.

Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
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 6fcf292 and 61210c4.

📒 Files selected for processing (1)
  • packages/template/src/components-page/stack-handler-client.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/template/src/components-page/stack-handler-client.tsx (7)
packages/template/src/components-page/sign-out.tsx (1)
  • SignOut (12-20)
packages/template/src/components-page/oauth-callback.tsx (1)
  • OAuthCallback (12-61)
packages/template/src/components-page/magic-link-callback.tsx (1)
  • MagicLinkCallback (16-87)
packages/template/src/components-page/mfa.tsx (1)
  • MFA (181-214)
packages/stack-shared/src/utils/errors.tsx (1)
  • StackAssertionError (69-85)
packages/stack-shared/src/utils/urls.tsx (2)
  • url (278-280)
  • getRelativePart (256-258)
packages/stack-shared/src/utils/objects.tsx (2)
  • FilterUndefined (365-367)
  • filterUndefined (373-375)
🪛 GitHub Actions: Run setup tests
packages/template/src/components-page/stack-handler-client.tsx

[error] 244-244: TS2304: Cannot find name 'MessageCard'.

🪛 GitHub Actions: Runs E2E API Tests
packages/template/src/components-page/stack-handler-client.tsx

[error] 244-244: TS2304: Cannot find name 'MessageCard'.

🪛 GitHub Actions: Runs E2E API Tests with custom port prefix
packages/template/src/components-page/stack-handler-client.tsx

[error] 244-244: Cannot find name 'MessageCard'.

⏰ 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). (8)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: all-good

@N2D4 N2D4 merged commit 3f5c6d8 into dev Nov 6, 2025
19 checks passed
@N2D4 N2D4 deleted the client-stack-handler branch November 6, 2025 19:42
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