Skip to content

[Docs][util] - Generate SDK documentation so its always up to date#1096

Closed
madster456 wants to merge 41 commits intodevfrom
docs/site/sdkgen
Closed

[Docs][util] - Generate SDK documentation so its always up to date#1096
madster456 wants to merge 41 commits intodevfrom
docs/site/sdkgen

Conversation

@madster456
Copy link
Copy Markdown
Collaborator

@madster456 madster456 commented Jan 11, 2026

Generated SDK documentation so its always up to date. Includes script, mdx file changes, and UI support for the documentation. As well as a new mixins category.

Summary by CodeRabbit

  • New Features

    • Expanded team and user APIs: invitations, member listing, team/user API key creation, contact channels, permissions, sessions, OAuth, and passkey support.
    • Customer item management and checkout helpers.
    • Added email-sending examples for HTML and template workflows.
  • Documentation

    • New SDK docs generation and rich docs components for types, hooks, and objects; restructured type pages with inheritance-aware rendering.
    • Improved code block UX (scroll indicators, accessible interactions) and example registry organization.
  • Chores

    • Documentation build pipeline and ignore rules updated.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 11, 2026

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

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment Apr 3, 2026 4:43pm
stack-backend Ready Ready Preview, Comment Apr 3, 2026 4:43pm
stack-dashboard Ready Ready Preview, Comment Apr 3, 2026 4:43pm
stack-demo Ready Ready Preview, Comment Apr 3, 2026 4:43pm
stack-docs Ready Ready Preview, Comment Apr 3, 2026 4:43pm

@cmux-agent
Copy link
Copy Markdown

cmux-agent Bot commented Jan 11, 2026

Older cmux preview screenshots (latest comment is below)

Preview Screenshots

Open Diff Heatmap

Preview screenshots are being captured...

Workspace and dev browser links will appear here once the preview environment is ready.


Generated by cmux preview system

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

Adds SDK docs generation and dynamic SDK documentation components; refactors many MDX pages to use JSON-driven Type/Hook/Object renderers; introduces new public SDK types and expanded stack-app API surfaces; adds code examples for emails and doc build/watch scripts.

Changes

Cohort / File(s) Summary
SDK JSON generator
packages/template/scripts/generate-sdk-docs-json.cjs
New script that analyzes TypeScript exports and JSDoc to emit objects.json, types.json, hooks.json, mixins.json into dist/sdk-docs. Handles tag filtering, type expansion, platform tags, and property description extraction.
SDK documentation components
docs/src/components/sdk/hook-documentation.tsx, docs/src/components/sdk/object-documentation.tsx, docs/src/components/sdk/type-documentation.tsx
New React components (Hook/Type/Object + FromJson helpers) that fetch generated JSON and render signatures, descriptions, inheritance, code highlighting, and source links. Exposes new public MDX components.
MDX integration & UX
docs/src/mdx-components.tsx, docs/src/components/mdx/base-codeblock.tsx, docs/src/components/mdx/platform-codeblock.tsx, docs/src/components/sdk/sdk-components.tsx, docs/src/components/mdx/clickable-code-styles.css
Registers new SDK components for MDX; adds scroll detection/indicator to code blocks; stages platform selection via pendingPlatform; replaces anchor overlay with accessible role="link" overlay; touch/scroll CSS added.
Docs pages & templates
docs/content/docs/sdk/types/*.mdx, docs/content/docs/sdk/mixins/*.mdx, docs/content/docs/sdk/hooks/*.mdx, docs/templates/sdk/*.mdx, docs/content/docs/sdk/meta.json
Numerous MDX pages refactored to use <TypeFromJson>, <HookFromJson>, or <ObjectFromJson>; new mixin pages (Auth, Customer, Connection); navigation restructured (Mixins / Shared Types) and many type pages simplified or renamed.
Code examples & gitignore
docs/code-examples/sdk-emails.ts, docs/code-examples/index.ts, docs/.gitignore
Adds sdk-emails code examples and registers them under new sdk group; adds /public/sdk-docs/ to .gitignore.
Build & docs scripts
package.json
Adds docs:generate-sdk, generate-docs, generate-docs:watch, generate-openapi-docs:watch and updates build:docs to run SDK docs generation.
Template: stack-app public types
packages/template/src/lib/stack-app/* (notably index.ts, api-keys/index.ts, customers/index.ts, contact-channels/index.ts, teams/index.ts, users/index.ts, common.ts)
Adds/exports new public SDK types and signatures: ApiKey variants; Customer/Item/ServerItem; ContactChannel and server variants; many additions to User, ServerUser, Team APIs (hooks, CRUD, permissions, API key creation, sessions, OAuth provider helpers). Many JSDoc @stackdoc annotations added.
Docs UI small updates
docs/src/components/ui/method-layout.tsx
CollapsibleTypesSection gains optional isReactHook prop to render a React badge in headers.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant CLI as npm scripts
    participant Gen as generate-sdk-docs-json.cjs
    participant TS as TypeScript checker
    participant Out as dist/sdk-docs (JSON)
    participant DocsSite as Docs/MDX components
    participant Browser as Site Renderer

    Dev->>CLI: npm run docs:generate-sdk
    CLI->>Gen: invoke generator
    Gen->>TS: parse project exports & JSDoc
    TS->>Gen: emit types/hooks/objects/mixins
    Gen->>Out: write objects.json, types.json, hooks.json, mixins.json
    DocsSite->>Out: fetch /public/sdk-docs/*.json via FromJson components
    Browser->>DocsSite: render Type/Hook/Object pages
    DocsSite-->>Browser: display dynamic documentation (signatures, examples, source links)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 I hopped through JSON, nibbling types,

Hooks and objects now take flight,
From TS to docs I made a trail,
Dynamic pages tell the tale,
Cheers — the docs now sing at night! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.59% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the main objective: generating SDK documentation automatically to keep it up to date. It is specific, clear, and directly relates to the primary change.
Description check ✅ Passed The PR description is minimal but adequately summarizes the key changes: generation script, MDX file updates, UI support, and a new mixins category. However, it lacks detail about the scope and motivation compared to the template's likely expectations for a documentation generation feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

@cmux-agent
Copy link
Copy Markdown

cmux-agent Bot commented Jan 11, 2026

Older cmux preview screenshots (latest comment is below)

Preview Screenshots

Open Diff Heatmap

Preview screenshots are being captured...

Workspace and dev browser links will appear here once the preview environment is ready.


Generated by cmux preview system

Copy link
Copy Markdown
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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
docs/src/components/mdx/base-codeblock.tsx (1)

197-209: Apply hover-exit-only transitions per coding guidelines.

The copy button uses transition-all duration-150 which animates both on hover-enter and hover-exit, making the UI feel less responsive. Per coding guidelines, transitions should only apply on hover-exit to keep interactions snappy.

Based on learnings, hover animations should avoid hover-enter transitions and use only hover-exit transitions.

⚡ Proposed fix to make hover instant and exit smooth
          <button
            onClick={() => runAsynchronously(handleCopy)}
            className={cn(
-              "absolute top-3 right-3 z-10 p-1.5 rounded-md transition-all duration-150",
+              "absolute top-3 right-3 z-10 p-1.5 rounded-md transition-all duration-150 hover:transition-none group-hover/code:transition-none",
              "text-fd-muted-foreground hover:text-fd-foreground",
              "bg-fd-muted/50 hover:bg-fd-muted border border-fd-border/50",
              "opacity-0 group-hover/code:opacity-100",
              copied && "opacity-100 text-green-500 hover:text-green-500"
            )}
            title={copied ? "Copied!" : "Copy code"}
          >
            {copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
          </button>
docs/content/docs/sdk/types/team-profile.mdx (1)

1-6: Title and description reference outdated type names.

The page title (line 2) and description (line 6) still reference TeamProfile and ServerTeamProfile, but the actual content documents TeamMemberProfile and ServerTeamMemberProfile. This inconsistency could confuse users.

📝 Proposed fix
 ---
-title: TeamProfile
+title: TeamMemberProfile
 full: true
 ---
 
-This is a detailed reference for the `TeamProfile` and `ServerTeamProfile` objects.
+This is a detailed reference for the `TeamMemberProfile` and `ServerTeamMemberProfile` objects.
packages/template/src/lib/stack-app/teams/index.ts (1)

97-107: Return type mismatch: useUsers() returns ServerUser[] but should likely return ServerTeamUser[].

Line 101 declares useUsers(): ServerUser[] on ServerTeam, but listUsers() on line 100 returns Promise<ServerTeamUser[]>. These should be consistent—the hook should probably return ServerTeamUser[] to include team profile information.

🐛 Proposed fix
-  useUsers(): ServerUser[], // THIS_LINE_PLATFORM react-like
+  useUsers(): ServerTeamUser[], // THIS_LINE_PLATFORM react-like
🤖 Fix all issues with AI agents
In @docs/content/docs/sdk/types/team-permission.mdx:
- Around line 42-45: The revoke permission link uses a camelCase anchor
(`#serveruserrevokePermission`) that is inconsistent with the grant link's
lowercase anchor and may break; update the revoke link target for
serverUser.revokePermission to the normalized lowercase anchor
(`#serveruserrevokepermission`) so both links (`serverUser.grantPermission` and
`serverUser.revokePermission`) use consistent, lowercase anchors.

In @docs/src/components/mdx/sdk-components.tsx:
- Around line 140-144: The onKeyDown handler for the interactive element should
call e.preventDefault() when the Space key is pressed to stop the browser from
scrolling; update the anonymous onKeyDown function (the arrow function that
checks e.key === 'Enter' || e.key === ' ') so that when e.key === ' ' you first
call e.preventDefault(), then set window.location.hash = area.anchor (you can
optionally also preventDefault for Enter if desired).

In @docs/src/components/sdk/object-documentation.tsx:
- Around line 131-139: In docs/src/components/sdk/object-documentation.tsx the
code maps objectInfo.signatures into block-level <div> elements inside an inline
<code> element which is semantically incorrect; change the mapping inside the
<code> to output inline elements (e.g., replace the inner <div> from
objectInfo.signatures.map with <span> elements) and give them display:block via
classes (e.g., className="block mb-2 last:mb-0") or alternatively move the
mapped blocks outside the <code> and keep only plain text nodes inside <code>;
update the objectInfo.signatures.map usage accordingly.
🧹 Nitpick comments (14)
packages/template/src/lib/stack-app/common.ts (1)

108-112: Documentation looks good.

The JSDoc comment accurately describes the signOut method. The documentation is clear and concise.

Optional: Consider mentioning default behavior

For completeness, you could mention what happens when redirectUrl is omitted (e.g., whether the user stays on the current page or is redirected to a default location):

 /**
- * Signs out the current user and optionally redirects to a URL.
+ * Signs out the current user and optionally redirects to a URL.
+ * If no redirectUrl is provided, the user remains on the current page.
  */

However, this is purely optional and may not be necessary if the behavior is self-evident or documented elsewhere.

docs/src/components/ui/method-layout.tsx (1)

407-411: Consider consistent border styling for visual harmony.

The React badge includes a border while the type badge (line 413) does not, since getTypeStyle returns styles without borders. For visual consistency, consider either adding borders to all badge types or removing the border from the React badge.

♻️ Option 1: Remove border from React badge for consistency
-              <span className="px-1.5 py-0.5 rounded text-xs font-medium bg-blue-50 dark:bg-blue-950/50 text-blue-700 dark:text-blue-300 border border-blue-200 dark:border-blue-800/50">
+              <span className="px-1.5 py-0.5 rounded text-xs font-medium bg-blue-50 dark:bg-blue-950/50 text-blue-700 dark:text-blue-300">
packages/template/src/lib/stack-app/teams/index.ts (1)

43-46: Consider using ReadonlyJson instead of any for metadata fields.

Per coding guidelines, any types should include a comment explaining why. Since ReadonlyJson is already imported and used in TeamUpdateOptions (line 68), consider using it here for type safety:

♻️ Proposed fix
-  /** Custom metadata that can be read and written by the client. */
-  clientMetadata: any,
-  /** Custom metadata that can only be read by the client (set via server). */
-  clientReadOnlyMetadata: any,
+  /** Custom metadata that can be read and written by the client. */
+  clientMetadata: ReadonlyJson,
+  /** Custom metadata that can only be read by the client (set via server). */
+  clientReadOnlyMetadata: ReadonlyJson,
docs/code-examples/sdk-emails.ts (3)

17-29: Add Content-Type header to fetch requests.

The fetch calls are sending JSON payloads but missing the Content-Type: application/json header. While some servers may handle this gracefully, explicitly setting the header is a best practice and prevents potential parsing issues.

📡 Proposed fix for both client-side examples

Apply this pattern to lines 19-26 and 95-102:

 const response = await fetch('/api/send-email', {
   method: 'POST',
+  headers: {
+    'Content-Type': 'application/json',
+  },
   body: JSON.stringify({
     userIds: ['user-1', 'user-2'],
     subject: 'Welcome!',
     html: '<h1>Welcome!</h1>'
   })
 });

46-48: Consider alternatives to console.error for error handling examples.

The coding guidelines specify "NEVER use .catch(console.error) or similar" and recommend using runAsynchronously or runAsynchronouslyWithAlert instead. While this is documentation/example code, consider demonstrating better error handling patterns that align with the project's guidelines.

As per coding guidelines, this helps developers learn the recommended error handling approach from the start.

✨ Alternative error handling pattern
-if (result.status === 'error') {
-  console.error('Failed to send email:', result.error);
-}
+if (result.status === 'error') {
+  throw new Error(`Failed to send email: ${result.error.message}`);
+}

Or demonstrate the recommended async pattern if applicable to the Stack SDK.

Also applies to: 127-129


58-76: Add variable declarations to Python examples.

The Python examples reference stack_project_id and stack_secret_server_key without defining them. For documentation clarity, consider adding placeholder declarations or comments explaining where these values should come from.

📝 Suggested additions

Add at the beginning of each Python example:

 import requests
 
+# Replace these with your actual Stack Auth credentials
+stack_project_id = 'your-project-id'
+stack_secret_server_key = 'your-secret-server-key'
+
 def send_welcome_email():
     response = requests.post(

Also applies to: 139-161

packages/template/scripts/generate-sdk-docs-json.cjs (2)

162-170: Consider extracting magic numbers to named constants.

The property count limits (10 and 20) are used as thresholds for type expansion but their meaning isn't immediately clear. Named constants would improve readability and maintainability.

Proposed refactor
+// Maximum properties to expand for complex types
+const MAX_PROPERTIES_FOR_NAMED_TYPES = 20;
+const MAX_PROPERTIES_FOR_INLINE_TYPES = 10;
+
 // ...
 
     const properties = checker.getPropertiesOfType(type);
-    if (properties.length > 0 && properties.length < 20) {
+    if (properties.length > 0 && properties.length < MAX_PROPERTIES_FOR_NAMED_TYPES) {
       // ...
     }
   }
   
   // ...
   
   if (type.flags & ts.TypeFlags.Object) {
     const properties = checker.getPropertiesOfType(type);
-    if (properties.length > 0 && properties.length < 10) {
+    if (properties.length > 0 && properties.length < MAX_PROPERTIES_FOR_INLINE_TYPES) {
       // ...
     }
   }

Also applies to: 194-204


174-191: Potential null access on type.types.

When handling intersection types, type.types is accessed without a null check. While TypeScript intersection types should always have a types array, defensive coding would prevent potential runtime errors if the type checker returns unexpected shapes.

Proposed fix
   if (type.flags & ts.TypeFlags.Intersection) {
-    const types = type.types || [];
+    const types = type.types ?? [];
+    if (types.length === 0) {
+      return checker.typeToString(type, node, TYPE_FORMAT_FLAGS_NO_EXPAND);
+    }
     
     // Check if any part contains Options/Config types
     const hasOptionsType = types.some(t => {

As per coding guidelines, prefer ?? over || for nullish coalescing.

docs/src/components/sdk/hook-documentation.tsx (2)

30-91: SyntaxHighlightedCode is duplicated across files — extract to shared module.

This component is nearly identical to the one in type-documentation.tsx. Consider extracting it to a shared location (e.g., docs/src/components/ui/syntax-highlighted-code.tsx) to avoid code duplication and maintenance burden.

Regarding the dangerouslySetInnerHTML static analysis warning: Shiki is used by big companies like Vercel for their Next.js docs or Astro for their syntax highlighting. This pattern with dangerouslySetInnerHTML is the standard approach for rendering Shiki output, and since the code input comes from internally-generated hooks.json (not user-submitted content), the XSS risk is minimal.

However, the fallback at line 67 directly interpolates code without escaping, which could render HTML if code contains angle brackets:

🔧 Safer fallback with HTML escaping
       } catch (error) {
         console.error('Error highlighting code:', error);
-        setHighlightedCode(`<pre><code>${code}</code></pre>`);
+        // Escape HTML entities for safe fallback rendering
+        const escaped = code
+          .replace(/&/g, '&amp;')
+          .replace(/</g, '&lt;')
+          .replace(/>/g, '&gt;');
+        setHighlightedCode(`<pre><code>${escaped}</code></pre>`);
       }

416-431: Consider simplifying hover transitions per coding guidelines.

The transition-all duration-200 class applies enter transitions, which per the coding guidelines should be avoided in favor of exit-only transitions to keep UI interactions snappy.

♻️ Use exit-only transition
-                  className="group flex items-center gap-2 px-3 py-2 rounded-lg border border-fd-border bg-fd-secondary/30 hover:bg-fd-secondary/50 hover:border-fd-accent-foreground/50 transition-all duration-200 no-underline"
+                  className="group flex items-center gap-2 px-3 py-2 rounded-lg border border-fd-border bg-fd-secondary/30 hover:bg-fd-secondary/50 hover:border-fd-accent-foreground/50 transition-colors hover:transition-none no-underline"
docs/src/components/sdk/type-documentation.tsx (3)

287-348: Duplicate SyntaxHighlightedCode component — extract to shared module.

This component is identical to the one in hook-documentation.tsx. Both files would benefit from a single shared implementation.

The same note about dangerouslySetInnerHTML applies here: since input comes from internally-generated JSON files and Shiki is a trusted syntax highlighter, the XSS risk is minimal. The fallback at line 324 has the same escaping concern.

♻️ Suggested shared component location

Create docs/src/components/ui/syntax-highlighted-code.tsx:

'use client';

import { runAsynchronously } from '@stackframe/stack-shared/dist/utils/promises';
import { useEffect, useState } from 'react';
import { codeToHtml } from 'shiki';

export function SyntaxHighlightedCode({ code, language = 'typescript' }: { code: string, language?: string }) {
  // ... implementation
}

Then import from both documentation components.


758-783: Same hover transition concern as in hook-documentation.tsx.

The View Source link at line 764 uses transition-all duration-200 which applies enter transitions. Per coding guidelines, prefer exit-only transitions.

♻️ Use exit-only transition
-                className="group flex items-center gap-2 px-3 py-2 rounded-lg border border-fd-border bg-fd-secondary/30 hover:bg-fd-secondary/50 hover:border-fd-accent-foreground/50 transition-all duration-200 no-underline"
+                className="group flex items-center gap-2 px-3 py-2 rounded-lg border border-fd-border bg-fd-secondary/30 hover:bg-fd-secondary/50 hover:border-fd-accent-foreground/50 transition-colors hover:transition-none no-underline"

810-828: Duplicated normalizeServerTypes helper function.

The normalizeServerTypes function is defined twice within isNewOrEnhancedMember (lines 812-816 and 848-853). Extract it once at the top of the function.

♻️ Extract to single definition
 function isNewOrEnhancedMember(
   member: TypeMember,
   typeInfo: TypeInfo,
   parentMembers: Map<string, TypeMember>
 ): boolean {
   const parentMember = parentMembers.get(member.name);
+
+  const normalizeServerTypes = (sig: string) => {
+    return sig
+      .replace(/Server(ContactChannel|User|Team|Permission|ApiKey|Item|Project|Email)/g, '$1')
+      .replace(/\s+/g, ' ')
+      .trim();
+  };
 
   if (!parentMember) {
     return true;
   }
 
   // Check if this member has signatures not in the parent
   const memberSigCount = member.signatures?.length ?? 0;
   const parentSigCount = parentMember.signatures?.length ?? 0;
 
   if (memberSigCount > 0 && parentSigCount > 0) {
     const memberSigs = new Set(member.signatures?.map(s => s.signature) || []);
     const parentSigs = new Set(parentMember.signatures?.map(s => s.signature) || []);
 
-    const normalizeServerTypes = (sig: string) => {
-      return sig
-        .replace(/Server(ContactChannel|User|Team|Permission|ApiKey|Item|Project|Email)/g, '$1')
-        .trim();
-    };
-
     const normalizedMemberSigs = new Set(Array.from(memberSigs).map(normalizeServerTypes));
     // ... rest of the code uses normalizeServerTypes defined once above

Also applies to: 846-860

packages/template/src/lib/stack-app/users/index.ts (1)

139-147: Consider adding comments explaining any type usage for metadata fields.

Per coding guidelines, when using any, leave a comment explaining why it's used and how errors would be caught. The metadata fields use any because they hold arbitrary user-defined JSON, but this isn't documented.

💡 Add explanatory comments
   /**
    * Custom metadata that can be read and written by the client.
+   * Uses `any` as metadata is user-defined JSON with no enforced schema.
    */
   readonly clientMetadata: any,

   /**
    * Read-only metadata that can only be set from the server.
+   * Uses `any` as metadata is user-defined JSON with no enforced schema.
    */
   readonly clientReadOnlyMetadata: any,
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d01edd3 and ab71c40.

📒 Files selected for processing (40)
  • docs/.gitignore
  • docs/code-examples/index.ts
  • docs/code-examples/sdk-emails.ts
  • docs/content/docs/sdk/hooks/use-stack-app.mdx
  • docs/content/docs/sdk/hooks/use-user.mdx
  • docs/content/docs/sdk/meta.json
  • docs/content/docs/sdk/mixins/auth.mdx
  • docs/content/docs/sdk/mixins/connection.mdx
  • docs/content/docs/sdk/mixins/customer.mdx
  • docs/content/docs/sdk/types/api-key.mdx
  • docs/content/docs/sdk/types/connected-account.mdx
  • docs/content/docs/sdk/types/contact-channel.mdx
  • docs/content/docs/sdk/types/customer.mdx
  • docs/content/docs/sdk/types/email.mdx
  • docs/content/docs/sdk/types/item.mdx
  • docs/content/docs/sdk/types/team-permission.mdx
  • docs/content/docs/sdk/types/team-profile.mdx
  • docs/content/docs/sdk/types/team-user.mdx
  • docs/content/docs/sdk/types/team.mdx
  • docs/content/docs/sdk/types/user.mdx
  • docs/src/components/mdx/base-codeblock.tsx
  • docs/src/components/mdx/clickable-code-styles.css
  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/mdx/sdk-components.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • docs/src/components/sdk/object-documentation.tsx
  • docs/src/components/sdk/type-documentation.tsx
  • docs/src/components/ui/method-layout.tsx
  • docs/src/mdx-components.tsx
  • docs/templates/sdk/types/connected-account.mdx
  • package.json
  • packages/template/scripts/generate-sdk-docs-json.cjs
  • packages/template/src/lib/hooks.tsx
  • packages/template/src/lib/stack-app/api-keys/index.ts
  • packages/template/src/lib/stack-app/common.ts
  • packages/template/src/lib/stack-app/contact-channels/index.ts
  • packages/template/src/lib/stack-app/customers/index.ts
  • packages/template/src/lib/stack-app/index.ts
  • packages/template/src/lib/stack-app/teams/index.ts
  • packages/template/src/lib/stack-app/users/index.ts
💤 Files with no reviewable changes (1)
  • docs/content/docs/sdk/types/customer.mdx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

For blocking alerts and errors, never use toast; instead, use alerts as toasts are easily missed by the user

Files:

  • packages/template/src/lib/stack-app/index.ts
  • docs/code-examples/index.ts
  • docs/src/components/sdk/object-documentation.tsx
  • docs/src/mdx-components.tsx
  • docs/code-examples/sdk-emails.ts
  • packages/template/src/lib/hooks.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • docs/src/components/ui/method-layout.tsx
  • docs/src/components/mdx/base-codeblock.tsx
  • packages/template/src/lib/stack-app/teams/index.ts
  • packages/template/src/lib/stack-app/common.ts
  • docs/src/components/mdx/sdk-components.tsx
  • packages/template/src/lib/stack-app/api-keys/index.ts
  • packages/template/src/lib/stack-app/contact-channels/index.ts
  • docs/src/components/mdx/platform-codeblock.tsx
  • packages/template/src/lib/stack-app/customers/index.ts
  • docs/src/components/sdk/type-documentation.tsx
  • packages/template/src/lib/stack-app/users/index.ts
**/*.{tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

NEVER use Next.js dynamic functions if avoidable; prefer using client components instead to keep pages static (e.g., use usePathname instead of await params)

Files:

  • packages/template/src/lib/stack-app/index.ts
  • docs/code-examples/index.ts
  • docs/src/components/sdk/object-documentation.tsx
  • docs/src/mdx-components.tsx
  • docs/code-examples/sdk-emails.ts
  • packages/template/src/lib/hooks.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • docs/src/components/ui/method-layout.tsx
  • docs/src/components/mdx/base-codeblock.tsx
  • packages/template/src/lib/stack-app/teams/index.ts
  • packages/template/src/lib/stack-app/common.ts
  • docs/src/components/mdx/sdk-components.tsx
  • packages/template/src/lib/stack-app/api-keys/index.ts
  • packages/template/src/lib/stack-app/contact-channels/index.ts
  • docs/src/components/mdx/platform-codeblock.tsx
  • packages/template/src/lib/stack-app/customers/index.ts
  • docs/src/components/sdk/type-documentation.tsx
  • packages/template/src/lib/stack-app/users/index.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: NEVER try-catch-all, NEVER void a promise, and NEVER use .catch(console.error) or similar; use loading indicators instead; if asynchronous handling is necessary, use runAsynchronously or runAsynchronouslyWithAlert instead
Use ES6 maps instead of records wherever possible

Files:

  • packages/template/src/lib/stack-app/index.ts
  • docs/code-examples/index.ts
  • docs/src/components/sdk/object-documentation.tsx
  • docs/src/mdx-components.tsx
  • docs/code-examples/sdk-emails.ts
  • packages/template/src/lib/hooks.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • docs/src/components/ui/method-layout.tsx
  • docs/src/components/mdx/base-codeblock.tsx
  • packages/template/src/lib/stack-app/teams/index.ts
  • packages/template/src/lib/stack-app/common.ts
  • docs/src/components/mdx/sdk-components.tsx
  • packages/template/src/lib/stack-app/api-keys/index.ts
  • packages/template/src/lib/stack-app/contact-channels/index.ts
  • docs/src/components/mdx/platform-codeblock.tsx
  • packages/template/src/lib/stack-app/customers/index.ts
  • docs/src/components/sdk/type-documentation.tsx
  • packages/template/src/lib/stack-app/users/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Code defensively; prefer ?? throwErr(...) over non-null assertions with good error messages explicitly stating violated assumptions
Avoid the any type; when necessary, leave a comment explaining why it's used, why the type system fails, and how errors would be caught at compile-, test-, or runtime

Files:

  • packages/template/src/lib/stack-app/index.ts
  • docs/code-examples/index.ts
  • docs/src/components/sdk/object-documentation.tsx
  • docs/src/mdx-components.tsx
  • docs/code-examples/sdk-emails.ts
  • packages/template/src/lib/hooks.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • docs/src/components/ui/method-layout.tsx
  • docs/src/components/mdx/base-codeblock.tsx
  • packages/template/src/lib/stack-app/teams/index.ts
  • packages/template/src/lib/stack-app/common.ts
  • docs/src/components/mdx/sdk-components.tsx
  • packages/template/src/lib/stack-app/api-keys/index.ts
  • packages/template/src/lib/stack-app/contact-channels/index.ts
  • docs/src/components/mdx/platform-codeblock.tsx
  • packages/template/src/lib/stack-app/customers/index.ts
  • docs/src/components/sdk/type-documentation.tsx
  • packages/template/src/lib/stack-app/users/index.ts
**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{tsx,css}: Keep hover/click animations snappy and fast; don't delay actions with pre-transitions (e.g., no fade-in on button hover) as it makes UI feel sluggish; instead apply transitions after the action like smooth fade-out when hover ends
When creating hover transitions, avoid hover-enter transitions and use only hover-exit transitions (e.g., transition-colors hover:transition-none)

Files:

  • docs/src/components/sdk/object-documentation.tsx
  • docs/src/mdx-components.tsx
  • packages/template/src/lib/hooks.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • docs/src/components/ui/method-layout.tsx
  • docs/src/components/mdx/base-codeblock.tsx
  • docs/src/components/mdx/clickable-code-styles.css
  • docs/src/components/mdx/sdk-components.tsx
  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/type-documentation.tsx
🧠 Learnings (9)
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: Applies to {packages/stack,packages/js}/**/*.{ts,tsx,js,jsx} : NEVER UPDATE packages/stack OR packages/js; instead, update packages/template as those packages are copies of it

Applied to files:

  • packages/template/src/lib/stack-app/index.ts
  • packages/template/src/lib/hooks.tsx
  • package.json
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: Applies to **/e2e/**/*.{test,spec}.{ts,tsx,js,jsx} : ALWAYS add new E2E tests when changing the API or SDK interface; err on the side of creating too many tests due to the critical nature of the authentication industry

Applied to files:

  • docs/code-examples/index.ts
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: The API follows a RESTful design with routes organized by resource type: auth endpoints in `/api/latest/auth/*`, users in `/api/latest/users/*`, teams in `/api/latest/teams/*`, and OAuth providers in `/api/latest/oauth-providers/*`

Applied to files:

  • docs/.gitignore
  • docs/content/docs/sdk/meta.json
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: Applies to **/config/schema.ts,**/config/**/*.{ts,tsx} : Whenever making backwards-incompatible changes to the config schema, update the migration functions in `packages/stack-shared/src/config/schema.ts`

Applied to files:

  • packages/template/src/lib/hooks.tsx
📚 Learning: 2026-01-11T06:44:57.542Z
Learnt from: N2D4
Repo: stack-auth/stack-auth PR: 1069
File: packages/template/src/components-page/onboarding.tsx:59-61
Timestamp: 2026-01-11T06:44:57.542Z
Learning: In the stack-auth codebase, Button components from stackframe/stack-ui (including those used via MessageCard props like primaryAction and secondaryAction) can accept async functions directly and automatically handle loading states with indicators. No need to wrap these with runAsynchronouslyWithAlert.

Applied to files:

  • docs/src/components/mdx/base-codeblock.tsx
  • docs/src/components/sdk/type-documentation.tsx
📚 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:

  • docs/src/components/mdx/base-codeblock.tsx
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: Applies to **/*.{tsx,css} : Keep hover/click animations snappy and fast; don't delay actions with pre-transitions (e.g., no fade-in on button hover) as it makes UI feel sluggish; instead apply transitions after the action like smooth fade-out when hover ends

Applied to files:

  • docs/src/components/mdx/clickable-code-styles.css
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: Applies to **/*.{tsx,css} : When creating hover transitions, avoid hover-enter transitions and use only hover-exit transitions (e.g., `transition-colors hover:transition-none`)

Applied to files:

  • docs/src/components/mdx/clickable-code-styles.css
📚 Learning: 2026-01-07T00:55:19.871Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T00:55:19.871Z
Learning: Applies to **/*.{tsx,ts} : NEVER use Next.js dynamic functions if avoidable; prefer using client components instead to keep pages static (e.g., use `usePathname` instead of `await params`)

Applied to files:

  • docs/src/components/sdk/type-documentation.tsx
🧬 Code graph analysis (5)
docs/src/components/sdk/object-documentation.tsx (2)
docs/src/components/ui/method-layout.tsx (5)
  • CollapsibleMethodSection (181-289)
  • MethodLayout (79-88)
  • MethodContent (90-99)
  • MethodAside (101-118)
  • AsideSection (120-137)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
docs/src/components/mdx/base-codeblock.tsx (1)
docs/src/components/icons.tsx (1)
  • ChevronDown (67-69)
packages/template/src/lib/stack-app/contact-channels/index.ts (1)
packages/template/src/lib/stack-app/index.ts (2)
  • ContactChannel (62-62)
  • ServerContactChannel (63-63)
docs/src/components/mdx/platform-codeblock.tsx (1)
docs/src/components/icons.tsx (1)
  • ChevronDown (67-69)
packages/template/src/lib/stack-app/users/index.ts (6)
packages/stack-shared/src/interface/crud/current-user.ts (1)
  • CurrentUserCrud (67-67)
packages/template/src/lib/stack-app/contact-channels/index.ts (4)
  • ContactChannel (9-63)
  • ContactChannelCreateOptions (68-88)
  • ServerContactChannel (133-142)
  • ServerContactChannelCreateOptions (169-175)
packages/stack-shared/src/utils/oauth.tsx (1)
  • ProviderType (6-6)
packages/template/src/lib/stack-app/connected-accounts/index.ts (1)
  • OAuthConnection (7-10)
packages/template/src/lib/stack-app/teams/index.ts (2)
  • Team (36-63)
  • TeamCreateOptions (78-81)
packages/template/src/lib/stack-app/permissions/index.ts (1)
  • TeamPermission (5-7)
🪛 ast-grep (0.40.4)
docs/src/components/sdk/hook-documentation.tsx

[warning] 89-89: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

docs/src/components/mdx/base-codeblock.tsx

[warning] 217-217: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

docs/src/components/sdk/type-documentation.tsx

[warning] 346-346: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
docs/src/components/sdk/hook-documentation.tsx

[error] 90-90: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

docs/src/components/mdx/base-codeblock.tsx

[error] 218-218: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

docs/src/components/sdk/type-documentation.tsx

[error] 347-347: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🪛 LanguageTool
docs/content/docs/sdk/types/api-key.mdx

[uncategorized] ~40-~40: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...UserApiKeyFirstView User API key with full value visible (returned bycreateApiKey()`)....

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[uncategorized] ~56-~56: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...TeamApiKeyFirstView Team API key with full value visible (returned bycreateApiKey()`)....

(EN_COMPOUND_ADJECTIVE_INTERNAL)

⏰ 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: Vercel Agent Review
  • GitHub Check: build (22.x)
  • GitHub Check: E2E Tests (Node 22.x, Freestyle mock)
  • GitHub Check: E2E Tests (Node 22.x, Freestyle prod)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: setup-tests
  • GitHub Check: restart-dev-and-test
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: setup-tests-with-custom-base-port
  • GitHub Check: all-good
  • GitHub Check: build (22.x)
  • GitHub Check: docker
🔇 Additional comments (51)
packages/template/src/lib/stack-app/common.ts (3)

121-124: Hook documentation is clear and consistent.

The JSDoc comment for useAccessToken accurately describes the hook's behavior and follows a consistent pattern with the async method documentation.


133-136: Hook documentation is clear and consistent.

The JSDoc comment for useRefreshToken is well-written and maintains consistency with the other hook documentation.


176-179: Hook documentation is accurate and concise.

The JSDoc comment for useAuthHeaders appropriately summarizes the hook's purpose while the full documentation is available on the async method above.

docs/src/components/ui/method-layout.tsx (1)

297-298: LGTM!

The isReactHook prop is correctly typed as optional with a sensible default value of false, ensuring backward compatibility with existing usage.

Also applies to: 306-306

docs/.gitignore (1)

34-34: LGTM!

Correctly ignores generated SDK documentation, preventing it from being committed to version control.

docs/src/components/mdx/clickable-code-styles.css (1)

8-12: LGTM!

The smooth scrolling styles enhance touch device UX without impacting interaction responsiveness.

packages/template/src/lib/hooks.tsx (2)

11-11: LGTM!

Documentation tag enables SDK documentation generation for this hook.


32-32: LGTM!

Documentation tag enables SDK documentation generation for this hook.

docs/content/docs/sdk/meta.json (1)

21-26: LGTM!

The new navigation structure logically organizes SDK documentation with separate sections for mixins and shared types.

docs/src/components/mdx/base-codeblock.tsx (2)

53-81: LGTM!

The scroll detection implementation is solid:

  • Properly uses useCallback for the check function
  • Correctly calculates scrollability with a reasonable 20px threshold
  • Includes both scroll listener and ResizeObserver to handle content changes
  • Properly cleans up listeners in the effect's return function
  • Dependencies are correct (including highlightedCode to recheck when content changes)

215-219: Verify that this component never receives untrusted user input.

The dangerouslySetInnerHTML receives HTML from Shiki's codeToHtml, which processes the code prop without sanitization. While this is typically safe in documentation contexts where code comes from trusted MDX files, it would be an XSS vulnerability if user-provided code could ever reach this component.

docs/content/docs/sdk/types/team-profile.mdx (1)

9-30: Documentation structure looks good.

The TOC anchors correctly link to the new type names, and the TypeFromJson components properly reference TeamMemberProfile and ServerTeamMemberProfile with appropriate parent type inheritance for the server variant.

packages/template/src/lib/stack-app/api-keys/index.ts (3)

29-32: Verify intent: optional + nullable creates three states.

manuallyRevokedAt?: Date | null allows three states: undefined, null, and Date. The JSDoc says "or null if not revoked" suggesting it should always be present. If null means "not revoked", consider removing the ?:

-      manuallyRevokedAt?: Date | null,
+      manuallyRevokedAt: Date | null,

If the undefined state is intentional (e.g., for backward compatibility or partial updates), please disregard.


8-68: Well-documented API key type with comprehensive JSDoc.

The generic ApiKey type with IsFirstView discriminator elegantly handles the first-view vs. subsequent-view scenarios. The conditional union for userId/teamId based on Type is a clean pattern for type-safe discrimination.


70-88: Concrete type exports are clear and well-documented.

The four exported types (UserApiKeyFirstView, UserApiKey, TeamApiKeyFirstView, TeamApiKey) with PrettifyType wrapper provide a clean public API surface with helpful JSDoc descriptions.

package.json (2)

17-17: SDK docs generation integrated into build pipeline.

The build:docs script now properly sequences SDK doc generation before OpenAPI docs. The docs:generate-sdk script handles CJS generation and file copying appropriately.

Also applies to: 65-65


62-62: Script references non-existent build:packages-only.

The generate-docs script calls pnpm run build:packages-only, but only build:packages is defined. This will cause the script to fail when executed.

🐛 Proposed fix
-    "generate-docs": "pnpm run build:packages-only && turbo run generate-openapi-fumadocs && pnpm run --filter=@stackframe/stack-docs generate-docs && pnpm run --filter=@stackframe/stack-docs generate-openapi-docs",
+    "generate-docs": "pnpm run build:packages && turbo run generate-openapi-fumadocs && pnpm run --filter=@stackframe/stack-docs generate-docs && pnpm run --filter=@stackframe/stack-docs generate-openapi-docs",
packages/template/src/lib/stack-app/customers/index.ts (2)

7-50: Well-structured Item and ServerItem types.

The Item type cleanly represents quantifiable resources with appropriate documentation. The ServerItem extension adds server-only quantity management methods with clear JSDoc explaining the race-condition-safe tryDecreaseQuantity pattern.


75-109: Customer type properly parameterized for server/client contexts.

The generic IsServer parameter elegantly controls which features are available, and the AsyncStoreProperty composition provides consistent patterns for items and products. The inline product conditional for server-only checkout is a clean approach.

packages/template/src/lib/stack-app/index.ts (1)

44-59: Public API exports properly consolidated.

The new type exports for API keys (ApiKey, TeamApiKey, TeamApiKeyFirstView, UserApiKey, UserApiKeyFirstView) and customer-related types (Customer, Item, ServerItem) are correctly re-exported, following the established pattern in this index file.

packages/template/src/lib/stack-app/teams/index.ts (1)

36-63: Expanded Team API surface is well-structured.

The new properties and methods with JSDoc comments provide a comprehensive API for team management. The composition with AsyncStoreProperty and Customer follows established patterns.

docs/content/docs/sdk/hooks/use-user.mdx (1)

8-11: API Reference section properly integrated.

The HookFromJson component follows the established pattern for rendering hook documentation from the generated JSON source, consistent with the PR's SDK documentation generation approach.

docs/content/docs/sdk/hooks/use-stack-app.mdx (2)

7-7: LGTM! Good documentation structure.

The addition of separate "Usage Example" and "API Reference" sections improves documentation clarity and makes it easier for users to find what they need.

Also applies to: 18-20


20-20: Verify HookFromJson component registration and hook name.

Ensure that:

  1. The HookFromJson component is properly registered in the MDX components configuration
  2. The hook name "useStackApp" matches exactly what's generated in the SDK docs JSON output
docs/content/docs/sdk/types/connected-account.mdx (2)

2-8: LGTM! Improved title readability and added helpful context.

The title change from "ConnectedAccount" to "Connected Account" improves readability, and the added introductory content provides clear context about OAuth connections and links users to the OAuth guide for more details.


12-14: Verify OAuthConnection type name and method signatures.

Unable to access the repository to verify:

  1. Whether the type name "OAuthConnection" matches the generated SDK docs
  2. Whether the methods getConnectedAccount(providerId) and useConnectedAccount(providerId) exist on the user object with these exact signatures

This requires manual verification of the SDK type definitions and method implementations.

docs/content/docs/sdk/mixins/auth.mdx (1)

10-10: Verify type name matches generated SDK docs.

Ensure the type name "Auth" matches exactly what's generated in the SDK docs JSON output.

docs/content/docs/sdk/mixins/connection.mdx (1)

10-10: Verify TypeFromJson component registration and type name.

Ensure that:

  1. The TypeFromJson component is properly registered in the MDX components configuration
  2. The type name "Connection" matches exactly what's generated in the SDK docs JSON output

Since this is part of an automated documentation generation system, any mismatch will cause the documentation to fail rendering or display incorrectly.

docs/content/docs/sdk/mixins/customer.mdx (1)

10-10: Verify type name matches generated SDK docs.

Ensure the type name "Customer" matches exactly what's generated in the SDK docs JSON output.

docs/src/mdx-components.tsx (1)

22-25: LGTM! Clean integration of SDK documentation components.

The new TypeDocumentation, HookDocumentation, and ObjectDocumentation components (plus their *FromJson variants) are properly imported and exported, following the existing pattern established by SDKOverview.

Also applies to: 95-100

docs/content/docs/sdk/types/team-user.mdx (1)

18-18: LGTM! Successful migration to dynamic type rendering.

The TypeFromJson components properly replace the inline type definitions. The parentTypes prop on ServerTeamUser correctly reflects the inheritance structure.

Also applies to: 28-28

docs/content/docs/sdk/types/item.mdx (1)

22-22: LGTM! Consistent migration to TypeFromJson rendering.

The Item and ServerItem types are now dynamically rendered, with ServerItem properly inheriting from Item via the parentTypes prop.

Also applies to: 30-30

packages/template/src/lib/stack-app/contact-channels/index.ts (6)

3-63: LGTM! Comprehensive type definition with excellent documentation.

The ContactChannel type is well-structured with detailed JSDoc comments for all properties and methods. The method signatures appropriately use Promise for async operations.


65-98: LGTM! Correct CRUD mapping for contact channel creation.

The ContactChannelCreateOptions type and its CRUD conversion function correctly map camelCase properties to snake_case and properly include the userId in the CRUD object.


100-126: LGTM! Proper update options with correct CRUD mapping.

The ContactChannelUpdateOptions type correctly makes all fields optional for partial updates, and the CRUD mapping is consistent with the creation mapping.


128-142: LGTM! Correct server-side extension of ContactChannel.

ServerContactChannel properly extends ContactChannel and overrides the update method to accept ServerContactChannelUpdateOptions, which allows server-only operations.


144-163: LGTM! Server update options correctly extend client options.

ServerContactChannelUpdateOptions properly adds the server-only isVerified field, and the CRUD mapping correctly includes all properties with proper snake_case conversion.


165-185: LGTM! Server creation options follow consistent pattern.

ServerContactChannelCreateOptions properly extends the client options with the server-only isVerified field, and the CRUD mapping is complete and correct.

docs/content/docs/sdk/types/email.mdx (1)

6-66: LGTM! Excellent restructure to usage-oriented documentation.

The documentation has been effectively restructured from type definitions to practical usage guidance. The parameter documentation is clear, examples are provided for both HTML and template-based emails, and the Info note helpfully clarifies that SendEmailOptions is not a standalone importable type. This aligns well with the PR's goal of keeping SDK documentation up-to-date and user-friendly.

docs/content/docs/sdk/types/user.mdx (1)

17-33: LGTM!

The migration to TypeFromJson components is clean and consistent. The parentTypes prop correctly represents the inheritance relationships between user types.

docs/content/docs/sdk/types/team.mdx (1)

18-28: LGTM!

Consistent use of TypeFromJson with proper inheritance via parentTypes for ServerTeam.

docs/src/components/sdk/object-documentation.tsx (1)

68-72: Questionable appType derivation logic.

The mapping of kind === 'class' to StackClientApp and everything else to StackServerApp appears arbitrary. This doesn't seem to reflect the actual client/server context of the object being documented. Consider whether this styling distinction is meaningful or if a different approach (e.g., a dedicated field in ObjectInfo) would be more appropriate.

docs/src/components/mdx/platform-codeblock.tsx (1)

278-278: LGTM! Well-implemented staged selection pattern.

The pendingPlatform state elegantly solves the UX problem of UI elements disappearing during platform selection. The flow correctly:

  • Stores pending selection without immediate broadcast
  • Derives activePlatform for framework options display
  • Applies both platform and framework changes atomically on final selection
  • Clears pending state on dropdown close or back navigation

Also applies to: 365-368, 507-521

docs/content/docs/sdk/types/api-key.mdx (1)

6-58: LGTM!

The restructured documentation clearly explains the API key access patterns and the distinction between masked and full-value views. The TypeFromJson components with parentTypes correctly represent the inheritance relationships.

Note: The static analysis suggestions about hyphenating "full value" are false positives—"full value" here is a noun phrase, not a compound adjective.

packages/template/scripts/generate-sdk-docs-json.cjs (1)

859-869: LGTM on the main function structure.

The script correctly:

  • Parses TypeScript configuration
  • Collects documentation from exports
  • Outputs categorized JSON files (objects, types, hooks, mixins)
  • Creates output directory recursively

The overall architecture is sound for SDK documentation generation.

docs/src/components/sdk/hook-documentation.tsx (1)

442-502: Good use of runAsynchronously and proper loading/error states.

The component correctly:

  • Uses runAsynchronously per coding guidelines
  • Shows loading indicator while fetching
  • Displays meaningful error messages (with available hooks list)
  • Handles the null case gracefully
docs/src/components/sdk/type-documentation.tsx (3)

606-668: Acceptable use of any with explanatory comment.

The eslint-disable comment at line 611 with the inline explanation (// eslint-disable-next-line @typescript-eslint/no-explicit-any) is acceptable since it's handling dynamically parsed content from descriptions. The parts array holds heterogeneous items (text vs code blocks) that are processed immediately.


903-1027: Well-structured component with proper async handling and inheritance display.

The TypeDocumentation component properly:

  • Uses runAsynchronously for async operations (line 962)
  • Shows loading state while fetching parent types
  • Filters members based on inheritance with clear logic
  • Provides informative UI about inherited members count

The logic for determining which members to show (lines 973-988) is well-organized with clear priority: ownMemberNames → signature comparison → all members.


1030-1106: Good implementation of TypeFromJson with fallback to mixins.json.

The component correctly handles:

  • Loading from types.json first, then mixins.json as fallback
  • Proper error states and messages
  • Passing through parentTypes prop to TypeDocumentation
packages/template/src/lib/stack-app/users/index.ts (2)

73-80: New currentSession API looks well-designed.

The currentSession property with getTokens() and useTokens() (React hook) follows the established pattern in the codebase for async/hook pairs. The THIS_LINE_PLATFORM react-like annotation correctly marks the hook as React-specific.


106-189: Comprehensive JSDoc documentation additions — LGTM.

The documentation improvements across BaseUser, UserExtra, and ServerBaseUser types are thorough and follow a consistent style:

  • Clear descriptions for each property and method
  • Proper @deprecated annotations with migration guidance
  • Platform markers (THIS_LINE_PLATFORM) for React-specific hooks

This significantly improves the developer experience for SDK consumers.

Also applies to: 191-362, 435-548

Comment thread docs/content/docs/sdk/types/team-permission.mdx Outdated
Comment thread docs/src/components/mdx/sdk-components.tsx
Comment thread docs/src/components/sdk/object-documentation.tsx
Comment thread packages/template/scripts/generate-sdk-type-reference.cjs
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jan 11, 2026

Greptile Overview

Greptile Summary

This PR implements an automated SDK documentation generation system that transforms TypeScript source code into interactive documentation. The implementation includes:

What Changed

Core Documentation Generator (generate-sdk-docs-json.cjs):

  • New 869-line script that uses the TypeScript compiler API to parse source code
  • Extracts types, interfaces, methods, and JSDoc comments from the SDK codebase
  • Generates structured JSON files categorized as objects, types, hooks, and mixins
  • Supports tag-based filtering (@stackdoc/@internal) and platform-specific documentation

React Documentation Components:

  • TypeFromJson component dynamically renders type documentation from generated JSON
  • Interactive table of contents with clickable navigation to methods/properties
  • Support for inheritance display (e.g., ServerUser extends CurrentUser)
  • Platform-specific filtering (React hooks vs. server-only methods)
  • Collapsible sections for better UX

New "Mixins" Category:

  • Introduced conceptual separation for reusable type building blocks (Auth, Customer, Connection)
  • Updated navigation structure in meta.json
  • Created dedicated MDX files for mixin documentation

Build Pipeline Integration:

  • Added docs:generate-sdk script to package.json
  • Integrated into build:docs workflow
  • Generated JSON files placed in docs/public/sdk-docs/ (gitignored)

Issues Found

  1. Security concern: window.location.hash assignment without validation in clickable code navigation (low severity - upstream sanitization exists but defense-in-depth recommended)

  2. Error handling gaps: File write operations and fetch requests lack proper error handling, which could cause silent failures or hung loading states

  3. Accessibility improvement: Clickable code areas changed from nested anchor tags to divs with onClick/onKeyDown (good change for standards compliance)

Architecture Assessment

The solution is well-architected with clear separation of concerns:

  • Generation phase (build-time) vs. rendering phase (run-time)
  • TypeScript AST analysis produces clean, structured JSON
  • React components consume JSON independently
  • No runtime dependency on TypeScript compiler

The type expansion logic is sophisticated, intelligently deciding whether to expand inline (Options types) or keep as references (domain entities).

Overall Quality

This is a substantial feature that will keep SDK documentation synchronized with code. The core logic is sound, but production readiness requires better error handling. The 40 files changed are mostly documentation updates and new MDX files - the critical changes are concentrated in the generator script and React components.

Confidence Score: 3/5

  • This PR has good architecture and logic, but requires error handling improvements before merging to production. The identified issues are not critical but should be addressed.
  • Score of 3 reflects that while the core functionality is well-designed and the code changes are logical, there are multiple areas needing improvement: (1) missing error handling in file operations could cause silent build failures, (2) fetch error handling could leave UI in loading state, (3) security best practice of validating redirect URLs should be followed even with upstream sanitization. None of these are critical bugs, but they reduce production readiness. The vast majority of the 40 files are documentation updates which are low-risk.
  • Pay close attention to packages/template/scripts/generate-sdk-docs-json.cjs (needs error handling for file writes) and docs/src/components/sdk/type-documentation.tsx (needs fetch error handling). The clickable navigation in docs/src/components/mdx/sdk-components.tsx should validate hash values for defense-in-depth security.

Important Files Changed

File Analysis

Filename Score Overview
packages/template/scripts/generate-sdk-docs-json.cjs 3/5 New TypeScript documentation generator script - transforms TypeScript AST into JSON documentation. Missing error handling for file operations and could provide better error messages. Overall logic is sound but needs production-grade error handling.
docs/src/components/mdx/sdk-components.tsx 3/5 Modified to improve clickable code navigation - changed from nested anchor tags to div with onClick/onKeyDown handlers (better accessibility). Has potential XSS concern with window.location.hash assignment that should be validated despite upstream sanitization.
docs/src/components/sdk/type-documentation.tsx 4/5 New comprehensive TypeScript type documentation component - handles rendering types, members, inheritance, platform-specific content. Uses dangerouslySetInnerHTML safely with shiki. Missing error handling for fetch operations could cause loading state to hang.
package.json 4/5 Added new npm script "docs:generate-sdk" to build pipeline. Script generates SDK docs from TypeScript and copies JSON to public folder. Integration looks correct.
docs/content/docs/sdk/meta.json 5/5 Reorganized SDK documentation navigation - added new "Mixins" section for reusable type building blocks (Auth, Customer, Connection). Clean organizational improvement.
docs/src/components/mdx/base-codeblock.tsx 5/5 No issues found - uses dangerouslySetInnerHTML safely with shiki syntax highlighter output. Good error handling and progressive enhancement.
packages/template/src/lib/stack-app/common.ts 5/5 Added JSDoc comments to AuthLike mixin type for better documentation generation. Pure documentation change, no logic modifications.
docs/content/docs/sdk/types/user.mdx 5/5 Documentation file using new TypeFromJson component to render user types. No issues found.
docs/content/docs/sdk/mixins/auth.mdx 5/5 New documentation file for Auth mixin type. Simple and correct usage of TypeFromJson component.
docs/.gitignore 5/5 Added /public/sdk-docs/ to gitignore as it contains generated files. Correct approach.

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant TS as TypeScript Source<br/>(packages/template/src)
    participant Script as generate-sdk-docs-json.cjs
    participant JSON as JSON Files<br/>(dist/sdk-docs/*.json)
    participant Build as Build Script<br/>(package.json)
    participant Docs as Docs Public Dir<br/>(docs/public/sdk-docs)
    participant React as React Components<br/>(TypeFromJson, etc.)
    participant Browser as User's Browser

    Note over Dev,TS: 1. Development Phase
    Dev->>TS: Write JSDoc comments in SDK code
    Dev->>TS: Add @stackdoc tags (if opt-in mode)

    Note over Script,JSON: 2. Documentation Generation (Build Time)
    Build->>Script: Run docs:generate-sdk
    Script->>TS: Parse TypeScript AST
    Script->>Script: Extract types, interfaces, functions
    Script->>Script: Extract JSDoc comments & signatures
    Script->>Script: Categorize into objects/types/hooks/mixins
    Script->>JSON: Write JSON files (types.json, hooks.json, etc.)
    Build->>Docs: Copy JSON files to public folder

    Note over React,Browser: 3. Documentation Rendering (Runtime)
    Browser->>Docs: Request /sdk-docs/types.json
    Docs-->>Browser: Return JSON documentation
    Browser->>React: Render <TypeFromJson typeName="User" />
    React->>React: Parse JSON, build component tree
    React->>React: Generate clickable table of contents
    React->>React: Create collapsible sections for members
    React->>Browser: Display interactive documentation
    
    Note over Browser: 4. User Interaction
    Browser->>Browser: User clicks method in TOC
    Browser->>Browser: window.location.hash = anchor
    Browser->>React: Hash change triggers section expand
    React->>Browser: Scroll to and show method details
Loading

Copy link
Copy Markdown
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.

6 files reviewed, 6 comments

Edit Code Review Agent Settings | Greptile

Comment thread docs/src/components/mdx/sdk-components.tsx
Comment thread packages/template/scripts/generate-sdk-type-reference.cjs
Comment thread packages/template/scripts/generate-sdk-type-reference.cjs
Comment thread docs/src/components/sdk/type-documentation.tsx
Comment thread docs/src/components/sdk/type-documentation.tsx
Comment thread package.json Outdated
@cmux-agent
Copy link
Copy Markdown

cmux-agent Bot commented Jan 11, 2026

Preview Screenshots

Open Diff Heatmap

Preview screenshots are being captured...

Workspace and dev browser links will appear here once the preview environment is ready.


Generated by cmux preview system

Copy link
Copy Markdown
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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/src/components/mdx/platform-codeblock.tsx (1)

651-660: Platform/framework mismatch in variant rendering.

When pendingPlatform is set (after selecting a platform but before selecting a framework), currentFramework is derived from activePlatform (line 368), but the variant rendering uses it with selectedPlatform. This causes a mismatch where a framework from one platform is used to look up variants in a different platform.

For example:

  • activePlatform = "react" (pending)
  • selectedPlatform = "nextjs" (current)
  • currentFramework = "vite" (framework for react)
  • Line 656: getVariantKeys("nextjs", "vite") → incorrect lookup
  • Line 658: platforms["nextjs"]["vite"] → undefined
🔧 Proposed fix

Use the framework that matches selectedPlatform in the variant rendering section:

-          hasVariants(selectedPlatform, selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]) ? (
+          (() => {
+            const variantFramework = selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0];
+            return hasVariants(selectedPlatform, variantFramework) ? (
             <div className="mb-3 flex">
               <div className="inline-flex items-center gap-1 rounded-full border border-fd-border/60 bg-fd-muted/20 p-1">
-                {getVariantKeys(selectedPlatform, currentFramework).map((variant) => {
+                {getVariantKeys(selectedPlatform, variantFramework).map((variant) => {
                   // Get the filename for this variant to use as label
-                  const config = platforms[selectedPlatform][currentFramework] as { [key: string]: VariantConfig } | undefined;
+                  const config = platforms[selectedPlatform][variantFramework] as { [key: string]: VariantConfig } | undefined;
                   const variantConfig = config?.[variant];
                   const label = variantConfig?.filename || variant.charAt(0).toUpperCase() + variant.slice(1);
 
                   return (
                     <button
                       key={variant}
                       onClick={() => handleVariantChange(variant)}
                       className={cn(
                         "inline-flex items-center justify-center whitespace-nowrap rounded-full px-3 py-1 text-xs font-medium transition-colors duration-150",
                         getCurrentVariant() === variant
                           ? "bg-fd-background text-fd-foreground shadow-sm border border-fd-border"
                           : "border border-transparent text-fd-muted-foreground hover:text-fd-foreground hover:bg-fd-muted/40"
                       )}
                     >
                       {label}
                     </button>
                   );
                 })}
               </div>
             </div>
-          ) : undefined
+          ) : undefined;
+          })()
         }

Alternatively, compute the correct framework inline:

-          hasVariants(selectedPlatform, selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]) ? (
+          hasVariants(selectedPlatform, selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]) ? (
             <div className="mb-3 flex">
               <div className="inline-flex items-center gap-1 rounded-full border border-fd-border/60 bg-fd-muted/20 p-1">
-                {getVariantKeys(selectedPlatform, currentFramework).map((variant) => {
+                {getVariantKeys(selectedPlatform, selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]).map((variant) => {
                   // Get the filename for this variant to use as label
-                  const config = platforms[selectedPlatform][currentFramework] as { [key: string]: VariantConfig } | undefined;
+                  const config = platforms[selectedPlatform][selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]] as { [key: string]: VariantConfig } | undefined;
🤖 Fix all issues with AI agents
In @docs/src/components/sdk/hook-documentation.tsx:
- Around line 379-391: Replace the unstable index key in the parameters map with
a stable identifier: use param.name as the key when rendering ParamField inside
the parsedSignature.parameters.map callback (where simplifyOptionsType is used
and getParameterDescription(hookInfo.name, param.name, ...) provides children).
Ensure key={param.name} is unique/stable for each ParamField to avoid remounting
when parameter order changes.
- Around line 441-474: HookFromJson's loadHookInfo can set state after unmount,
returns untyped JSON and builds an unbounded error string; fix by using an
AbortController and passing its signal to fetch, typing the parsed JSON as
Record<string, HookInfo> (or appropriate interface) before accessing
hooksData[hookName], and bounding the error message length when listing
available hooks (e.g. show first N keys with an ellipsis). Also add a cleanup in
the useEffect that aborts the controller (and/or track mounted state) so
setHookInfo/setError/setLoading are not called after unmount, and treat abort
exceptions specially so they don't set an error.
- Around line 414-433: The GitHub URL template hardcodes the wrong repo slug and
the UI uses a forbidden hover-enter animation class; update the href template
that concatenates hookInfo.sourcePath (and the analogous typeInfo.sourcePath in
the TypeDocumentation component) to use "stack-auth/stack-auth" instead of
"stack-auth/stack", and replace any "transition-all" class in the anchor and
related SVGs with "transition-colors hover:transition-none" so only color
transitions occur and hover-exit rules are respected.
- Around line 31-91: The current implementation of SyntaxHighlightedCode catches
all errors and logs them with console.error and also builds an unsafe HTML
fallback using the raw `code` string; remove the try/catch block inside the
`updateHighlightedCode` async function (and eliminate the console.error call) so
errors bubble, and instead pass an onError handler to both
`runAsynchronously(updateHighlightedCode)` calls that sets the `highlightedCode`
state to an empty string (use setHighlightedCode('')), relying on the existing
React-rendered fallback (<pre><code>{code}</code></pre>) for safe plain-text
output; reference the SyntaxHighlightedCode component, the updateHighlightedCode
function, the runAsynchronously invocations, and the highlightedCode state when
making these edits.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab71c40 and a4c5072.

📒 Files selected for processing (3)
  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/hook-documentation.tsx
  • package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

For blocking alerts and errors, never use toast; instead, use alerts as toasts are easily missed by the user

Files:

  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/hook-documentation.tsx
**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{tsx,css}: Keep hover/click animations snappy and fast; don't delay actions with pre-transitions (e.g., no fade-in on button hover) as it makes UI feel sluggish; instead apply transitions after the action like smooth fade-out when hover ends
When creating hover transitions, avoid hover-enter transitions and use only hover-exit transitions (e.g., transition-colors hover:transition-none)

Files:

  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/hook-documentation.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

NEVER use Next.js dynamic functions if avoidable; prefer using client components instead to keep pages static (e.g., use usePathname instead of await params)

Files:

  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/hook-documentation.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: NEVER try-catch-all, NEVER void a promise, and NEVER use .catch(console.error) or similar; use loading indicators instead; if asynchronous handling is necessary, use runAsynchronously or runAsynchronouslyWithAlert instead
Use ES6 maps instead of records wherever possible

Files:

  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/hook-documentation.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Code defensively; prefer ?? throwErr(...) over non-null assertions with good error messages explicitly stating violated assumptions
Avoid the any type; when necessary, leave a comment explaining why it's used, why the type system fails, and how errors would be caught at compile-, test-, or runtime

Files:

  • docs/src/components/mdx/platform-codeblock.tsx
  • docs/src/components/sdk/hook-documentation.tsx
🧬 Code graph analysis (2)
docs/src/components/mdx/platform-codeblock.tsx (1)
docs/src/components/icons.tsx (1)
  • ChevronDown (67-69)
docs/src/components/sdk/hook-documentation.tsx (4)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
packages/template/scripts/generate-sdk-docs-json.cjs (9)
  • paramType (560-560)
  • returnType (592-592)
  • type (755-755)
  • i (675-675)
  • signatures (766-768)
  • sig (676-676)
  • parsed (786-786)
  • parameters (557-586)
  • param (573-577)
docs/src/components/ui/method-layout.tsx (3)
  • CollapsibleMethodSection (181-289)
  • MethodLayout (79-88)
  • AsideSection (120-137)
docs/src/components/mdx/sdk-components.tsx (1)
  • ParamField (266-297)
🪛 ast-grep (0.40.4)
docs/src/components/sdk/hook-documentation.tsx

[warning] 89-89: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 Biome (2.1.2)
docs/src/components/sdk/hook-documentation.tsx

[error] 90-90: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

⏰ 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: Vercel Agent Review
  • GitHub Check: all-good
  • GitHub Check: setup-tests-with-custom-base-port
  • GitHub Check: E2E Tests (Node 22.x, Freestyle prod)
  • GitHub Check: build (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: E2E Tests (Node 22.x, Freestyle mock)
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: build (22.x)
  • GitHub Check: setup-tests
  • GitHub Check: check_prisma_migrations (22.x)
🔇 Additional comments (5)
docs/src/components/mdx/platform-codeblock.tsx (5)

278-278: LGTM!

The pendingPlatform state is appropriately initialized and typed for staging platform selections.


365-368: Derivation logic is correct for dropdown display.

The activePlatform correctly uses the pending selection to populate framework options while the dropdown is open.


484-491: LGTM!

Correctly clears the pending platform when the user dismisses the dropdown by clicking outside.


501-534: LGTM!

The staged selection flow is well-implemented:

  • Platform selection stages the choice without immediate broadcast
  • Framework selection commits both platform and framework changes atomically
  • Closing the dropdown or clicking outside properly clears any uncommitted pending state

608-620: LGTM!

The back button correctly clears the pending platform, and the framework view header appropriately displays the pending (or current) platform being configured.

Comment thread docs/src/components/sdk/hook-documentation.tsx
Comment thread docs/src/components/sdk/hook-documentation.tsx
Comment thread docs/src/components/sdk/hook-documentation.tsx
Comment thread docs/src/components/sdk/hook-documentation.tsx
Comment thread docs/src/components/sdk/hook-documentation.tsx
Copy link
Copy Markdown

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

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

Additional Suggestion:

State inconsistency: The variant buttons use currentFramework (derived from pending platform) with selectedPlatform, which can cause incorrect or missing variant labels during platform selection transitions.

View Details
📝 Patch Details
diff --git a/docs/src/components/mdx/platform-codeblock.tsx b/docs/src/components/mdx/platform-codeblock.tsx
index e16e6d87..8bd8a5bd 100644
--- a/docs/src/components/mdx/platform-codeblock.tsx
+++ b/docs/src/components/mdx/platform-codeblock.tsx
@@ -653,9 +653,10 @@ export function PlatformCodeblock({
           hasVariants(selectedPlatform, selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]) ? (
             <div className="mb-3 flex">
               <div className="inline-flex items-center gap-1 rounded-full border border-fd-border/60 bg-fd-muted/20 p-1">
-                {getVariantKeys(selectedPlatform, currentFramework).map((variant) => {
+                {getVariantKeys(selectedPlatform, selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0]).map((variant) => {
                   // Get the filename for this variant to use as label
-                  const config = platforms[selectedPlatform][currentFramework] as { [key: string]: VariantConfig } | undefined;
+                  const displayFramework = selectedFrameworks[selectedPlatform] || Object.keys(platforms[selectedPlatform] ?? {})[0];
+                  const config = platforms[selectedPlatform][displayFramework] as { [key: string]: VariantConfig } | undefined;
                   const variantConfig = config?.[variant];
                   const label = variantConfig?.filename || variant.charAt(0).toUpperCase() + variant.slice(1);
 

Analysis

Variant button labels disappear during platform selection transitions

What fails: During platform transitions in PlatformCodeblock, variant button labels (e.g., "server"/"client") become missing or incorrect when a user switches platforms in the dropdown. The component renders an empty variant section momentarily before the platform change completes.

How to reproduce:

  1. Navigate to a documentation page with code examples that have variants (e.g., the "setup" examples with Next.js server/client variants)
  2. Open the platform/framework selector dropdown
  3. Click to select a different platform (e.g., Python)
  4. During the framework selection step (before finalizing the platform switch), observe the variant buttons disappear

What happens: While in the framework selection dropdown for the new platform, currentFramework becomes the framework for the pending platform (via activePlatform = pendingPlatform || selectedPlatform). The variant rendering then mixes this pending-platform framework with the displayed-platform in the lookup:

  • Line 656: getVariantKeys(selectedPlatform, currentFramework) where currentFramework is from the pending platform
  • Line 658: platforms[selectedPlatform][currentFramework] tries to access a framework that doesn't exist in the current platform

If the pending platform's framework doesn't exist in the currently displayed platform, the lookup fails and config becomes undefined, causing variant button labels to not render.

Expected behavior: Variant buttons should consistently use the currently displayed platform's framework throughout the selection transition, maintaining visible and correct labels until the platform change completes.

Root cause: State inconsistency between line 651's check using selectedFrameworks[selectedPlatform] (displayed platform framework) and lines 656-658 using currentFramework (pending platform framework).

Fix: Use selectedFrameworks[selectedPlatform] consistently in the variant rendering section instead of currentFramework to ensure both the variant key lookup and config access use the displayed platform's framework.

Reference implementation: Changed lines 656-658 to consistently reference the displayed platform's selected framework, creating displayFramework variable for clarity and reuse.

Made-with: Cursor

# Conflicts:
#	docs/content/docs/sdk/types/connected-account.mdx
#	docs/content/docs/sdk/types/user.mdx
#	packages/template/src/lib/stack-app/teams/index.ts
#	packages/template/src/lib/stack-app/users/index.ts
Comment thread docs/src/components/mdx/platform-codeblock.tsx
@N2D4 N2D4 closed this Apr 8, 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.

2 participants