Skip to content

[Docs][Content][UI] - JWT docs and JWT component#905

Merged
madster456 merged 15 commits intodevfrom
docs/content/jwt
Sep 29, 2025
Merged

[Docs][Content][UI] - JWT docs and JWT component#905
madster456 merged 15 commits intodevfrom
docs/content/jwt

Conversation

@madster456
Copy link
Collaborator

@madster456 madster456 commented Sep 20, 2025

Adds JWT docs and JWT viewer component to docs

image

High-level PR Summary

This PR adds comprehensive JWT (JSON Web Token) documentation and an interactive JWT viewer component to the Stack Auth documentation. The main additions are a new documentation page explaining JWT concepts, structure, and usage within Stack Auth, along with a React component that allows users to decode and inspect JWT tokens. The JWT viewer can automatically load the current user's session token if they are signed in, or accept manually pasted tokens. The documentation provides examples of both client-side and server-side JWT usage, security considerations, troubleshooting guidance, and best practices. The PR also includes necessary updates to metadata files and component exports to integrate the new content into the documentation platform.

⏱️ Estimated Review Time: 15-30 minutes

💡 Review Order Suggestion
Order File Path
1 docs/templates/concepts/jwt.mdx
2 docs/src/components/mdx/jwt-viewer.tsx
3 docs/docs-platform.yml
4 docs/src/components/mdx/index.ts
5 docs/src/mdx-components.tsx
6 docs/templates/meta.json
7 docs/templates-python/meta.json

Important

Adds a new JWT concepts page and an interactive JWTViewer component, integrating it into MDX and navigation, with jose added for decoding.

  • Docs:
    • Add concepts/jwt.mdx with JWT structure, claims, examples, verification, security, and best practices.
    • Include JWT page in navigation: docs-platform.yml, templates/meta.json, and Python templates-python/meta.json.
  • UI Component:
    • Add JWTViewer in docs/src/components/mdx/jwt-viewer.tsx to decode JWTs (header, payload, signature), show time-based indicators, and load current user token via useUser().
    • Export and register in MDX: docs/src/components/mdx/index.ts, docs/src/mdx-components.tsx.
  • Dependencies:
    • Add jose to docs/package.json (lockfile updated).

This description was created by Ellipsis for f25e369. You can customize this summary. It will automatically update as commits are pushed.


Review by RecurseML

🔍 Review performed on ad34cfe..a135bbd

✨ No bugs found, your code is sparkling clean

✅ Files analyzed, no issues (3)

docs/src/components/mdx/jwt-viewer.tsx
docs/src/mdx-components.tsx
docs/src/components/mdx/index.ts

⏭️ Files skipped (trigger manually) (4)
  Locations     Trigger Analysis  
docs/docs-platform.yml Analyze
docs/templates-python/meta.json Analyze
docs/templates/concepts/jwt.mdx Analyze
docs/templates/meta.json Analyze

Need help? Join our Discord

Summary by CodeRabbit

  • New Features

    • Interactive JWT Viewer in the docs: paste or auto-load a token to inspect header, payload, signature with live decoding, validity/time indicators, per-field copy controls, and "load my token".
  • Documentation

    • New "JWT" concept page covering structure, claims, examples, client/server/manual usage, security, troubleshooting, and best practices.
    • JWT page added to site navigation and enabled across Next, React, JS, and Python docs.
  • Chores

    • Added runtime dependency to support JWT decoding in the docs.

Note

Adds a new JWT concepts page and an interactive JWTViewer component, integrating it into MDX and navigation, with jose added for decoding.

  • Docs:
    • Add concepts/jwt.mdx with JWT structure, claims, examples, verification, security, and best practices.
    • Include JWT page in navigation: docs-platform.yml, templates/meta.json, and Python templates-python/meta.json.
  • UI Component:
    • Add JWTViewer in docs/src/components/mdx/jwt-viewer.tsx to decode JWTs (header, payload, signature), show time-based indicators, and load current user token via useUser().
    • Export and register in MDX: docs/src/components/mdx/index.ts, docs/src/mdx-components.tsx.
  • Dependencies:
    • Add jose to docs/package.json (lockfile updated).

Written by Cursor Bugbot for commit 837fffb. This will update automatically on new commits. Configure here.

@vercel
Copy link

vercel bot commented Sep 20, 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 Sep 29, 2025 5:21pm
stack-dashboard Ready Ready Preview Comment Sep 29, 2025 5:21pm
stack-demo Ready Ready Preview Comment Sep 29, 2025 5:21pm
stack-docs Ready Ready Preview Comment Sep 29, 2025 5:21pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 20, 2025

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

Adds a JWT concept doc and navigation entries; introduces a client-side JWTViewer React component, exports it in MDX component index and mdx-components mapping, and adds the "jose" runtime dependency to the docs package. (46 words)

Changes

Cohort / File(s) Summary of changes
Docs navigation updates
docs/docs-platform.yml, docs/templates/meta.json, docs/templates-python/meta.json
Inserted new page entry/path for concepts/jwt into platform and template metadata to expose the JWT documentation in navigation.
New docs content
docs/templates/concepts/jwt.mdx
Added a new JWT concept page covering JWT structure, Stack Auth claims, examples, usage patterns, verification, security, troubleshooting, and an embedded interactive JWTViewer.
MDX component exports
docs/src/components/mdx/index.ts
Exported JWTViewer from the MDX components index, adding it to the module's public exports.
MDX components mapping
docs/src/mdx-components.tsx
Imported and added JWTViewer to the getMDXComponents return mapping so MDX pages can use the component.
New MDX UI component
docs/src/components/mdx/jwt-viewer.tsx
Added JWTViewer (client component) that decodes JWTs (header/payload/signature), handles errors, supports loading current user token via useUser, offers per-field copy controls, and formats time claims.
Docs package dependency
docs/package.json
Added runtime dependency "jose": "^6.1.0" to the docs package dependencies.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant MDX as "MDX Page"
  participant Renderer as "MDX Renderer"
  participant JWT as "JWTViewer"
  participant Auth as "useUser"
  participant Decode as "jose decoder"

  User->>MDX: Open concepts/jwt
  MDX->>Renderer: Render page with <JWTViewer/>
  Renderer->>JWT: mount()

  rect rgba(220,240,255,0.25)
    JWT->>Auth: request current user token
    alt token present
      Auth-->>JWT: user.token
      JWT->>Decode: decode(token)
      Decode-->>JWT: header/payload/signature
      JWT-->>User: render decoded view
    else no token
      JWT-->>User: show textarea + "Load My Token"
    end
  end

  User->>JWT: Paste token / Click Load
  JWT->>Decode: decode(input)
  alt success
    Decode-->>JWT: parsed parts
    JWT-->>User: update UI
  else error
    Decode-->>JWT: error
    JWT-->>User: show error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • N2D4

Poem

(_/)
(•ᴥ•) I hopped through docs to find a key,
JWT crumbs tucked beneath a tree.
Header, payload, signature — peek and pry,
Decode, copy, refresh as tokens fly.
🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
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 (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "[Docs][Content][UI] - JWT docs and JWT component" clearly summarizes the primary changes by indicating both the addition of JWT documentation and a JWT viewer component while using concise and relevant tags for context, making it easy for teammates to understand the pull request’s focus at a glance.
Description Check ✅ Passed The pull request description begins with the required contributing guidelines header and includes a clear summary line, an illustrative screenshot, a detailed overview of changes, review order suggestions, and a concise recap of docs, UI component, and dependency updates, fulfilling and even exceeding the repository’s minimal description template requirements.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch docs/content/jwt

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
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 Summary

This PR adds comprehensive JWT documentation and an interactive JWT viewer component to the Stack Auth documentation platform. The changes introduce a new "concepts/jwt.mdx" documentation page that covers JWT fundamentals, Stack Auth-specific claims, usage examples, security considerations, and troubleshooting guidance.

The core addition is a JWTViewer React component that provides interactive JWT decoding functionality. Users can either paste JWT tokens manually or automatically load their current session token to examine the decoded header, payload, and signature sections. The component includes proper error handling for malformed JWTs, base64url decoding, timestamp formatting for standard claims, and visual indicators for token expiration status.

The documentation is integrated across all supported platforms (Next.js, React, JavaScript, and Python) through updates to the navigation metadata files (meta.json and docs-platform.yml). The JWT viewer component is properly exported through the MDX components system, making it available for use within markdown documentation files.

This enhancement addresses a documentation gap around JWT understanding in Stack Auth's authentication system, providing developers with both theoretical knowledge and practical tools for working with JWT tokens. The timing aligns with Stack Auth's goal of providing comprehensive, developer-friendly authentication documentation.

Confidence score: 4/5

  • This PR is safe to merge with minimal risk as it only adds documentation content and a viewer component without touching core authentication logic
  • Score reflects the addition of new documentation features with proper integration but involves client-side JWT decoding that should be reviewed for security best practices
  • Pay close attention to the JWT viewer component's use of atob() for base64 decoding and ensure the security recommendations in the documentation are accurate

7 files reviewed, no comments

Edit Code Review Bot 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: 0

🧹 Nitpick comments (2)
docs/src/components/mdx/jwt-viewer.tsx (2)

8-17: Enhance JWT parsing with proper error handling and validation.

The current implementation could be improved:

  • Consider using a dedicated JWT library like jose for more robust parsing (I see it's already used elsewhere in the codebase)
  • Add validation for malformed base64 padding
  • Handle edge cases where base64 decoding might failSince the codebase already uses the jose library, I recommend using it for more robust JWT parsing instead of the custom implementation.

Consider replacing the custom JWT decoding with the jose library's decodeJwt function:

-// Simple JWT decoding
-const decodeJWT = (jwt: string) => {
-  const parts = jwt.split('.');
-  if (parts.length !== 3) throw new Error('Invalid JWT format');
-  
-  return {
-    header: JSON.parse(atob(parts[0].replace(/-/g, '+').replace(/_/g, '/'))),
-    payload: JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))),
-    signature: parts[2]
-  };
-};
+import { decodeJwt } from 'jose';
+
+const decodeJWT = (jwt: string) => {
+  const payload = decodeJwt(jwt);
+  // For header, we can decode it separately since jose doesn't expose header decoding directly
+  const parts = jwt.split('.');
+  if (parts.length !== 3) throw new Error('Invalid JWT format');
+  
+  const header = JSON.parse(atob(parts[0].replace(/-/g, '+').replace(/_/g, '/')));
+  
+  return {
+    header,
+    payload,
+    signature: parts[2]
+  };
+};

This provides better error handling and is consistent with the existing codebase that already uses jose.


26-26: Consider using proper TypeScript types instead of any.

The decoded state uses any type which reduces type safety. Consider defining a proper interface for the decoded JWT structure.

+interface DecodedJWT {
+  header: Record<string, any>;
+  payload: Record<string, any>;
+  signature: string;
+}

-  const [decoded, setDecoded] = useState<any>(null);
+  const [decoded, setDecoded] = useState<DecodedJWT | null>(null);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad34cfe and a135bbd.

📒 Files selected for processing (7)
  • docs/docs-platform.yml (1 hunks)
  • docs/src/components/mdx/index.ts (1 hunks)
  • docs/src/components/mdx/jwt-viewer.tsx (1 hunks)
  • docs/src/mdx-components.tsx (2 hunks)
  • docs/templates-python/meta.json (1 hunks)
  • docs/templates/concepts/jwt.mdx (1 hunks)
  • docs/templates/meta.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • docs/src/mdx-components.tsx
  • docs/src/components/mdx/index.ts
  • docs/src/components/mdx/jwt-viewer.tsx
🧬 Code graph analysis (1)
docs/src/components/mdx/jwt-viewer.tsx (1)
packages/stack-shared/src/sessions.ts (1)
  • decoded (14-16)
⏰ 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). (9)
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: restart-dev-and-test
  • GitHub Check: build (22.x)
  • GitHub Check: setup-tests
  • GitHub Check: docker
  • GitHub Check: build (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: Security Check
🔇 Additional comments (11)
docs/src/components/mdx/index.ts (1)

5-5: LGTM!

The export is correctly added, maintaining alphabetical order and follows the established pattern in the file.

docs/templates-python/meta.json (1)

13-13: LGTM!

The JWT concept page is correctly added to the Python documentation navigation, maintaining the logical flow of concepts.

docs/docs-platform.yml (1)

114-115: LGTM!

The JWT documentation page is correctly configured for all platforms and positioned logically after backend integration concepts.

docs/templates/meta.json (1)

18-18: LGTM!

The JWT concept page is properly added to the navigation structure in the correct location within the Concepts section.

docs/templates/concepts/jwt.mdx (1)

1-184: Excellent JWT documentation with comprehensive coverage!

The documentation is well-structured, covering all essential aspects of JWT usage with Stack Auth including:

  • Clear JWT structure explanation
  • Interactive component integration
  • Practical code examples for client/server usage
  • Security best practices
  • Troubleshooting guidance
  • Proper cross-references to related concepts

The content is technically accurate and provides great value for developers.

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

21-21: LGTM!

The import is correctly placed and follows the existing import pattern.


82-83: LGTM!

The JWTViewer component is properly added to the MDX components mapping alongside other components, making it available for use in MDX documentation.

docs/src/components/mdx/jwt-viewer.tsx (4)

49-65: LGTM! Well-implemented auto-loading logic.

The auto-loading functionality properly checks conditions and handles errors gracefully. The dependency array is correct and prevents unnecessary re-runs.


82-103: Excellent time formatting with proper status indicators.

The time formatting function correctly handles different JWT time claims (exp, iat, nbf) and provides clear visual feedback for expiration and validity states.


105-120: LGTM! Good value rendering with special handling for timestamps.

The value rendering function appropriately handles different data types and provides special formatting for JWT timestamp fields.


122-259: Excellent UI implementation with comprehensive features!

The component provides a complete JWT viewer experience with:

  • Clean, accessible interface with proper labeling
  • Auto-loading of user tokens with clear status indicators
  • Live token editing with immediate decoding
  • Proper error handling and display
  • Well-structured sections for header, payload, and signature
  • Good visual feedback with color coding
  • Responsive design considerations

The implementation follows React best practices and provides excellent user experience.

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: 2

🧹 Nitpick comments (5)
docs/src/components/mdx/jwt-viewer.tsx (5)

8-12: Consider Map over Record for key–value collections.

Guidelines prefer ES6 Map for KV collections. Here JSON parsing returns plain objects; switching to Map adds conversion overhead. If you adopt Map, adjust render loops accordingly.

-type DecodedJWT = {
-  header: Record<string, unknown>,
-  payload: Record<string, unknown>,
-  signature: string,
-};
+type DecodedJWT = {
+  header: Map<string, unknown>;
+  payload: Map<string, unknown>;
+  signature: string;
+};

And later:

-{Object.entries(decoded.header).map(([key, value]) => (
+{Array.from(decoded.header.entries()).map(([key, value]) => (
...
-{Object.entries(decoded.payload).map(([key, value]) => (
+{Array.from(decoded.payload.entries()).map(([key, value]) => (

If you keep Record (reasonable for JSON), please note the intentional deviation from the guideline.


133-135: Associate label with textarea and disable text helpers.

Improve a11y and avoid token mutations by IME/spellcheck/autocorrect.

-          <label className="text-sm font-medium text-fd-foreground">JWT Token</label>
+          <label htmlFor="jwt-token-input" className="text-sm font-medium text-fd-foreground">JWT Token</label>
@@
-          <textarea
+          <textarea
+            id="jwt-token-input"
             value={token}
             onChange={(e) => {
               setToken(e.target.value);
               handleDecode(e.target.value);
               setUserTokenLoaded(false);
             }}
             placeholder={user ? "Your token loads automatically, or paste another here..." : "Paste JWT token here..."}
+            autoComplete="off"
+            autoCorrect="off"
+            spellCheck={false}
             className={cn(

Also applies to: 150-165


177-191: Use an alert region for error messages.

Enable screen readers to announce decode errors.

-      {error && (
-        <div className={cn(
+      {error && (
+        <div role="alert" aria-live="assertive" className={cn(
           "p-3 rounded-lg border border-dashed",

112-127: Handle null explicitly; add ISO tooltip for time claims.

Minor robustness/readability.

-  const renderValue = (key: string, value: unknown) => {
+  const renderValue = (key: string, value: unknown) => {
     if (key === 'exp' || key === 'iat' || key === 'nbf') {
       return (
         <div className="space-y-1">
           <code className="text-fd-foreground">{String(value)}</code>
           {typeof value === 'number' && (
             <div>{formatTime(value, key)}</div>
           )}
         </div>
       );
     }
-    if (typeof value === 'object') {
+    if (value === null) {
+      return <code className="text-fd-foreground">null</code>;
+    }
+    if (typeof value === 'object') {
       return <code className="text-fd-foreground break-all">{JSON.stringify(value)}</code>;
     }
     return <code className="text-fd-foreground">{String(value)}</code>;
   };

89-110: Add ISO timestamp in title attribute for time claims.

Keeps UI locale-friendly while preserving precise value on hover.

-    return (
-      <span className={cn(
+    return (
+      <span
+        title={date.toISOString()}
+        className={cn(
         "text-xs",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a135bbd and 7092ac5.

📒 Files selected for processing (1)
  • docs/src/components/mdx/jwt-viewer.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • docs/src/components/mdx/jwt-viewer.tsx
🧬 Code graph analysis (1)
docs/src/components/mdx/jwt-viewer.tsx (2)
packages/stack-shared/src/sessions.ts (1)
  • decoded (14-16)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
⏰ 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: restart-dev-and-test
  • GitHub Check: setup-tests
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: Security Check
🔇 Additional comments (2)
docs/src/components/mdx/jwt-viewer.tsx (2)

74-87: Resolved — getAuthJson() returns accessToken; no change required

Signature and implementation confirm { accessToken, refreshToken } is returned (packages/template/src/lib/stack-app/users/index.ts:127; implementation in packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts:894–909). jwt-viewer usages in docs/src/components/mdx/jwt-viewer.tsx are correct.


4-4: Do not change to '@stackframe/stack-shared/utils/promises' — it's not exported.

packages/stack-shared/package.json only exposes "." and "./dist/*"; runAsynchronously is defined at packages/stack-shared/src/utils/promises.tsx but is not re-exported from the package root, so importing '@stackframe/stack-shared/utils/promises' will break consumers.

  • Options: add export { runAsynchronously } from './utils/promises' to packages/stack-shared/src/index.ts (allow import from '@stackframe/stack-shared'); or add a subpath export (e.g. "./utils/*") in packages/stack-shared/package.json to permit '@stackframe/stack-shared/utils/promises'; otherwise keep the existing deep import from the package's ./dist path (works with current exports but is brittle).

Likely an incorrect or invalid review comment.

cursor[bot]

This comment was marked as outdated.

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: 2

🧹 Nitpick comments (4)
docs/src/components/mdx/jwt-viewer.tsx (4)

4-4: Avoid deep-importing from dist; use a public export.

Deep paths are brittle across builds. Import runAsynchronously from a stable public path or re-export it.

Apply if available:

-import { runAsynchronously } from '@stackframe/stack-shared/dist/utils/promises';
+import { runAsynchronously } from '@stackframe/stack-shared/utils/promises';

If not exported, please add a re-export at @stackframe/stack-shared and switch to it here.


119-121: Pass the function to runAsynchronously instead of invoking it.

This lets the helper wrap the call and errors consistently.

-              onClick={() => runAsynchronously(loadCurrentUserToken())}
+              onClick={() => runAsynchronously(loadCurrentUserToken)}

132-148: Minor privacy UX: disable spellcheck/autocomplete for token textarea.

Prevents accidental leakage via spellcheck/autofill and reduces noise.

           <textarea
             value={token}
             onChange={(e) => {
               setToken(e.target.value);
               handleDecode(e.target.value);
               setUserTokenLoaded(false);
             }}
             placeholder={user ? "Click 'Load My Token' to use your session token, or paste another here..." : "Paste JWT token here..."}
             className={cn(
               "w-full h-24 p-3 text-xs font-mono rounded-lg resize-vertical",
               "bg-fd-background border border-fd-border",
               "text-fd-foreground placeholder:text-fd-muted-foreground",
               "focus:outline-none focus:ring-2 focus:ring-fd-primary/20 focus:border-fd-primary",
               "transition-colors"
             )}
+            autoComplete="off"
+            spellCheck={false}
           />

176-246: Optional: sort claims for stable rendering.

Sorting header/payload keys improves readability across renders.

-              {Object.entries(decoded.header).map(([key, value]) => (
+              {Object.entries(decoded.header).sort(([a],[b]) => a.localeCompare(b)).map(([key, value]) => (
                 ...
               ))}
-              {Object.entries(decoded.payload).map(([key, value]) => (
+              {Object.entries(decoded.payload).sort(([a],[b]) => a.localeCompare(b)).map(([key, value]) => (
                 ...
               ))}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7092ac5 and 9e8f137.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • docs/docs-platform.yml (1 hunks)
  • docs/package.json (1 hunks)
  • docs/src/components/mdx/jwt-viewer.tsx (1 hunks)
  • docs/templates/meta.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/templates/meta.json
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • docs/src/components/mdx/jwt-viewer.tsx
🧬 Code graph analysis (1)
docs/src/components/mdx/jwt-viewer.tsx (1)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
⏰ 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). (9)
  • GitHub Check: all-good
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: setup-tests
  • GitHub Check: docker
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test
  • GitHub Check: Security Check
🔇 Additional comments (2)
docs/src/components/mdx/jwt-viewer.tsx (1)

15-24: LGTM: robust decoding via jose.

Using decodeProtectedHeader and decodeJwt addresses base64url padding and UTF‑8 issues.

docs/docs-platform.yml (1)

114-116: Approve JWT docs entry Template exists at docs/templates/concepts/jwt.mdx and the entry’s placement and platform list align with adjacent concept pages.

@zeropath-ai
Copy link

zeropath-ai bot commented Sep 29, 2025

Some new issue(s) might be present. Please use the following link(s) to view them:

https://zeropath.com/app/issues/fa92fb5a-045f-4177-9605-6996d2915558
https://zeropath.com/app/issues/3e5185fb-c669-4e19-a1e4-ffe6cf89e6c8
https://zeropath.com/app/issues/7a7178dc-0507-49f8-9c09-4b1c7307aa54

Reply to this PR with @zeropath-ai followed by a description of what change you want and we'll auto-submit a change to this PR to implement it.

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

🧹 Nitpick comments (3)
docs/src/components/mdx/jwt-viewer.tsx (3)

288-289: Improve a11y: associate label with textarea and announce errors.

Link the label to the textarea (htmlFor/id) and make the error region an alert with aria-live.

-          <label className="text-sm font-medium text-fd-foreground">JWT Token</label>
+          <label htmlFor="jwt-token-input" className="text-sm font-medium text-fd-foreground">JWT Token</label>
@@
-          <textarea
+          <textarea
+            id="jwt-token-input"
             value={token}
@@
-      {error && (
-        <div className={cn(
+      {error && (
+        <div role="alert" aria-live="polite" className={cn(
           "p-3 rounded-lg border border-dashed",

Also applies to: 320-335, 376-383


114-135: Handle ms vs s epoch values and show timezone explicitly.

Some JWTs emit ms epochs; add a heuristic and clarify timezone to reduce confusion.

-  const formatTime = (timestamp: number, field: string) => {
-    const date = new Date(timestamp * 1000);
+  const formatTime = (timestamp: number, field: string) => {
+    // Heuristic: treat large values as ms
+    const seconds = timestamp > 1_000_000_000_0 ? Math.floor(timestamp / 1000) : timestamp;
+    const date = new Date(seconds * 1000);
     const now = Date.now() / 1000;
@@
-        {date.toLocaleString()}
+        {date.toLocaleString(undefined, { timeZoneName: 'short' })}

If your tokens always use seconds, feel free to drop the heuristic.


5-5: Tighten types using jose’s JWTPayload/JWSHeaderParameters.

Reduces casting and improves editor hints.

-import { decodeProtectedHeader, decodeJwt as joseDecodeJwt } from 'jose';
+import { decodeProtectedHeader, decodeJwt as joseDecodeJwt, type JWTPayload, type JWSHeaderParameters } from 'jose';
@@
 type DecodedJWT = {
-  header: Record<string, unknown>,
-  payload: Record<string, unknown>,
+  header: JWSHeaderParameters,
+  payload: JWTPayload,
   signature: string,
 };
@@
   return {
-    header: decodeProtectedHeader(jwt) as Record<string, unknown>,
-    payload: joseDecodeJwt(jwt) as Record<string, unknown>,
+    header: decodeProtectedHeader(jwt),
+    payload: joseDecodeJwt(jwt),
     signature: parts[2]!,
   };

Also applies to: 9-13, 20-23

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02fc2a9 and a540e04.

📒 Files selected for processing (2)
  • docs/src/components/mdx/jwt-viewer.tsx (1 hunks)
  • docs/templates/concepts/jwt.mdx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/templates/concepts/jwt.mdx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • docs/src/components/mdx/jwt-viewer.tsx
🧬 Code graph analysis (1)
docs/src/components/mdx/jwt-viewer.tsx (1)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
⏰ 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). (9)
  • GitHub Check: build (22.x)
  • GitHub Check: all-good
  • GitHub Check: docker
  • GitHub Check: build (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: setup-tests
  • GitHub Check: restart-dev-and-test
  • GitHub Check: docker
  • GitHub Check: Security Check
🔇 Additional comments (2)
docs/src/components/mdx/jwt-viewer.tsx (2)

32-38: Decode defaultToken on mount and when the prop changes.

Currently defaultToken is set in state but not decoded until user edits. Add an effect to sync/decode. This was flagged earlier and still outstanding.

 export function JWTViewer({ defaultToken = '', className = '' }: JWTViewerProps) {
   const [token, setToken] = useState(defaultToken);
   const [decoded, setDecoded] = useState<DecodedJWT | null>(null);
   const [error, setError] = useState<string>('');
   const [userTokenLoaded, setUserTokenLoaded] = useState(false);
   const [copiedKey, setCopiedKey] = useState<string | null>(null);
@@
   const handleDecode = useCallback((jwtString: string) => {
@@
   }, []);
+
+  // Initialize/sync from defaultToken
+  useEffect(() => {
+    if (defaultToken) {
+      setToken(defaultToken);
+      handleDecode(defaultToken);
+      setUserTokenLoaded(false);
+    }
+  }, [defaultToken, handleDecode]);

Also applies to: 51-66


4-4: Confirm public export for runAsynchronously
Avoid importing from dist paths; verify that @stackframe/stack-shared’s package.json “exports” map includes ./utils/promises (or appropriate entry). If it doesn’t, add a public export or update the import to the correct stable entrypoint.

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: 0

🧹 Nitpick comments (4)
docs/src/components/mdx/jwt-viewer.tsx (4)

9-13: Use jose’s types for stronger safety; drop the casts.

Type payload/header as JWTPayload/JWSHeaderParameters and remove the Record<...> casts.

 import { decodeProtectedHeader, decodeJwt as joseDecodeJwt } from 'jose';
+import type { JWTPayload, JWSHeaderParameters } from 'jose';

 type DecodedJWT = {
-  header: Record<string, unknown>,
-  payload: Record<string, unknown>,
+  header: JWSHeaderParameters,
+  payload: JWTPayload,
   signature: string,
 };

   return {
-    header: decodeProtectedHeader(jwt) as Record<string, unknown>,
-    payload: joseDecodeJwt(jwt) as Record<string, unknown>,
+    header: decodeProtectedHeader(jwt),
+    payload: joseDecodeJwt(jwt),
     signature: parts[2]!,
   };

Also applies to: 20-22


51-66: Be lenient with inputs: strip “Bearer ” prefix before decoding.

This helps when users paste Authorization headers.

-  const handleDecode = useCallback((jwtString: string) => {
-    if (!jwtString.trim()) {
+  const handleDecode = useCallback((jwtString: string) => {
+    const trimmed = jwtString.trim();
+    if (!trimmed) {
       setDecoded(null);
       setError('');
       return;
     }
 
     try {
-      setDecoded(decodeJWT(jwtString));
+      const cleaned = trimmed.replace(/^Bearer\s+/i, '');
+      setDecoded(decodeJWT(cleaned));
       setError('');
     } catch (err) {
       setError(err instanceof Error ? err.message : 'Invalid JWT');
       setDecoded(null);
     }
   }, []);

286-317: Add a quick “Clear” action for privacy.

Let users wipe the token from the UI in one click.

           <div className="flex flex-wrap items-center gap-2">
             {token && (
               <button
                 type="button"
                 onClick={() => runAsynchronously(() => handleCopy(token, 'token'))}
                 className={cn(
                   "px-3 py-1.5 text-xs font-medium rounded-md border",
                   "border-fd-border bg-fd-muted/40 text-fd-muted-foreground hover:bg-fd-muted/60",
                   "transition-colors"
                 )}
               >
                 {copiedKey === 'token' ? 'Copied' : 'Copy Token'}
               </button>
             )}
+            {token && (
+              <button
+                type="button"
+                onClick={() => { setToken(''); setDecoded(null); setError(''); setUserTokenLoaded(false); }}
+                className={cn(
+                  "px-3 py-1.5 text-xs font-medium rounded-md border",
+                  "border-fd-border bg-fd-muted/20 text-fd-muted-foreground hover:bg-fd-muted/40",
+                  "transition-colors"
+                )}
+              >
+                Clear
+              </button>
+            )}
             {user && (
               <button
                 type="button"
                 onClick={() => runAsynchronously(loadCurrentUserToken)}
                 className={cn(
                   "px-3 py-1.5 text-xs font-medium rounded-md transition-colors",

438-448: Optional: Map over a Map to align with the “prefer Map over Record” guideline.

Not required here, but if you want strict adherence, you could convert header/payload to ReadonlyMap and iterate via map.entries(). This is a larger change and may not be worth it given jose returns plain objects.

As per coding guidelines.

Also applies to: 462-474

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a540e04 and f25e369.

📒 Files selected for processing (1)
  • docs/src/components/mdx/jwt-viewer.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • docs/src/components/mdx/jwt-viewer.tsx
🧬 Code graph analysis (1)
docs/src/components/mdx/jwt-viewer.tsx (1)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
⏰ 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). (9)
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: docker
  • GitHub Check: setup-tests
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: all-good
  • GitHub Check: build (22.x)
  • GitHub Check: Security Check
🔇 Additional comments (2)
docs/src/components/mdx/jwt-viewer.tsx (2)

32-38: Decode defaultToken on mount/prop change.

Currently it won’t decode until user input. Initialize from defaultToken and keep in sync.

   const [userTokenLoaded, setUserTokenLoaded] = useState(false);
   const [copiedKey, setCopiedKey] = useState<string | null>(null);

+  // Initialize from defaultToken and keep in sync if it changes
+  useEffect(() => {
+    if (defaultToken) {
+      setToken(defaultToken);
+      handleDecode(defaultToken);
+      setUserTokenLoaded(false);
+    }
+  }, [defaultToken, handleDecode]);

   const user = useUser();

   const copyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

Also applies to: 43-49


4-4: Verify public export for runAsynchronously
Avoid deep “dist” import; ensure @stackframe/stack-shared’s package.json exports includes "./utils/promises" (so you can import from @stackframe/stack-shared/utils/promises instead of the deep dist path`), or add that export entry.

@madster456 madster456 merged commit f5a3a99 into dev Sep 29, 2025
20 of 22 checks passed
@madster456 madster456 deleted the docs/content/jwt branch September 29, 2025 18:05
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