[Docs][Content][UI] - JWT docs and JWT component#905
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughAdds 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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
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. Comment |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
josefor 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
joselibrary, I recommend using it for more robust JWT parsing instead of the custom implementation.Consider replacing the custom JWT decoding with the
joselibrary'sdecodeJwtfunction:-// 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 ofany.The
decodedstate usesanytype 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
📒 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.tsxdocs/src/components/mdx/index.tsdocs/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.
There was a problem hiding this comment.
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: Handlenullexplicitly; 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
📒 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 requiredSignature 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.
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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.
|
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 Reply to this PR with |
There was a problem hiding this comment.
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
📒 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 fromdistpaths; verify that@stackframe/stack-shared’spackage.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.
There was a problem hiding this comment.
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
📒 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’spackage.jsonexportsincludes"./utils/promises"(so you can import from@stackframe/stack-shared/utils/promisesinstead of the deepdistpath`), or add that export entry.
Adds JWT docs and JWT viewer component to docs
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
docs/templates/concepts/jwt.mdxdocs/src/components/mdx/jwt-viewer.tsxdocs/docs-platform.ymldocs/src/components/mdx/index.tsdocs/src/mdx-components.tsxdocs/templates/meta.jsondocs/templates-python/meta.jsonImportant
Adds a new JWT concepts page and an interactive
JWTViewercomponent, integrating it into MDX and navigation, withjoseadded for decoding.concepts/jwt.mdxwith JWT structure, claims, examples, verification, security, and best practices.docs-platform.yml,templates/meta.json, and Pythontemplates-python/meta.json.JWTViewerindocs/src/components/mdx/jwt-viewer.tsxto decode JWTs (header, payload, signature), show time-based indicators, and load current user token viauseUser().docs/src/components/mdx/index.ts,docs/src/mdx-components.tsx.josetodocs/package.json(lockfile updated).This description was created by
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)
docs/docs-platform.ymldocs/templates-python/meta.jsondocs/templates/concepts/jwt.mdxdocs/templates/meta.jsonSummary by CodeRabbit
New Features
Documentation
Chores
Note
Adds a new JWT concepts page and an interactive
JWTViewercomponent, integrating it into MDX and navigation, withjoseadded for decoding.concepts/jwt.mdxwith JWT structure, claims, examples, verification, security, and best practices.docs-platform.yml,templates/meta.json, and Pythontemplates-python/meta.json.JWTViewerindocs/src/components/mdx/jwt-viewer.tsxto decode JWTs (header, payload, signature), show time-based indicators, and load current user token viauseUser().docs/src/components/mdx/index.ts,docs/src/mdx-components.tsx.josetodocs/package.json(lockfile updated).Written by Cursor Bugbot for commit 837fffb. This will update automatically on new commits. Configure here.