Skip to content

[Docs][Site] + [Dashboard][UI] - Adds docs to Stack Companion#869

Merged
madster456 merged 86 commits intodevfrom
stack-companion-docs
Oct 31, 2025
Merged

[Docs][Site] + [Dashboard][UI] - Adds docs to Stack Companion#869
madster456 merged 86 commits intodevfrom
stack-companion-docs

Conversation

@madster456
Copy link
Collaborator

@madster456 madster456 commented Aug 29, 2025


Important

Adds a unified documentation widget to the dashboard, enabling in-app viewing and switching of documentation types with platform-specific adaptations.

  • Behavior:
    • Adds UnifiedDocsWidget to stack-companion.tsx for viewing docs within the dashboard.
    • Supports platform switching, back navigation, sidebar toggle, loading/error states, and external opening.
    • Adapts content based on current page across dashboard, docs, and API.
  • Documentation:
    • Adds embedded routes/layouts in docs/src/app for api-embed, dashboard-embed, and docs-embed.
    • Implements EmbeddedLinkInterceptor and PlatformChangeNotifier for link handling and platform change notifications.
    • Updates generate-docs.js to include dashboard docs generation.
  • Configuration:
    • Adds NEXT_PUBLIC_STACK_DOCS_BASE_URL to .env.development and env.tsx.
    • Configures CORS headers in next.config.mjs for dashboard embedding.
  • Misc:
    • Updates styling in global.css to support embedded content.
    • Adds EmbeddedLink component for MDX link handling in mdx-components.tsx.

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


Summary by CodeRabbit

  • New Features

    • Unified embedded docs viewer added to the dashboard with multi-type support, navigation controls, back navigation, and external-open behavior
    • In-iframe link interception and MDX embedded-link support for seamless embedded navigation
  • Style

    • Improved CSS for embedded content: scrollbar hiding, overflow handling, responsive media and code blocks
  • Chores

    • Added dashboard docs collection, embed routes/layouts, CORS headers, and env config for docs embedding
  • UX

    • Consolidated account UI in mobile header; improved auth panel open/close animations

@vercel
Copy link

vercel bot commented Aug 29, 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 Oct 31, 2025 0:47am
stack-dashboard Ready Ready Preview Comment Oct 31, 2025 0:47am
stack-demo Ready Ready Preview Comment Oct 31, 2025 0:47am
stack-docs Ready Ready Preview Comment Oct 31, 2025 0:47am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 29, 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 new UnifiedDocsWidget and embeds docs/api/dashboard content via iframe; adds embed routes/layouts, message bridge, link interception, CORS headers, dashboard docs source, styling, and an env var NEXT_PUBLIC_STACK_DOCS_BASE_URL; integrates the widget into the dashboard companion UI.

Changes

Cohort / File(s) Summary
Dashboard UI Integration
apps/dashboard/src/components/stack-companion.tsx
Replaced inline docs UI with <UnifiedDocsWidget isActive={true} /> when expanded and activeItem === 'docs'.
Unified Docs Widget
apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx
New exported React component UnifiedDocsWidget({ isActive }) that renders an iframe-based viewer for docs/api/dashboard, derives base URL from env, maps dashboard routes to docs pages, manages loading/error state, listens for postMessage history events, and supports back navigation and external links.
Env wiring (dashboard)
apps/dashboard/.env, apps/dashboard/.env.development, apps/dashboard/src/lib/env.tsx
Added NEXT_PUBLIC_STACK_DOCS_BASE_URL and wired it into inline/post-build env handling.
Docs content source
docs/source.config.ts, docs/lib/source.ts, docs/.gitignore
Added dashboard docs collection, exported dashboardSource loader for /dashboard, and ignored generated /content/dashboard/.
Next.js CORS headers
docs/next.config.mjs
Added headers() to set Access-Control-Allow-Origin/Methods/Headers for /dashboard/:path* and /dashboard-embed/:path* (uses dashboardUrl).
Embedded routes & layouts
docs/src/app/docs-embed/..., docs/src/app/api-embed/..., docs/src/app/dashboard-embed/...
New app-route pages and embed-optimized layouts that render MDX via embedded MDX components, omit standard chrome, and are iframe-friendly.
Embedded message bridge
docs/src/components/embedded-docs-message-bridge.tsx
New client component exposing postMessage protocol (DOCS_HISTORY_STATE / NAVIGATE_BACK), maintains local navigation history, and notifies parent windows.
Link interception & MDX embedded links
docs/src/components/embedded-link-interceptor.tsx, docs/src/components/mdx/embedded-link.tsx, docs/src/mdx-components.tsx
Added EmbeddedLink and EmbeddedLinkInterceptor to rewrite internal links to embed routes, resolve relative paths, verify targets via HEAD, and getEmbeddedMDXComponents() to render embedded anchors.
Embedded content styling
docs/src/app/global.css
Added .scrollbar-hide and prose overflow/word-wrap/table/image/code rules to improve embed display and scrolling.
Shared header adjustments
docs/src/components/layouts/shared-header.tsx
Introduced DocsAccountMenu using useUser and consolidated account UI into an Account block in mobile navigation.
Exports & minor UI tweaks
docs/src/components/layouts/docs.tsx, docs/src/components/api/auth-panel.tsx
Exported AccordionProvider and useAccordionState; adjusted mobile auth panel animation/accessibility classes.
New manifest / package entries
manifest_file, package.json
Project manifest/package updates included in the diff.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User as Dashboard UI
  participant Widget as UnifiedDocsWidget
  participant Iframe as Docs Iframe
  participant DocsApp as Docs Server App
  participant Bridge as EmbeddedDocsMessageBridge

  User->>Widget: Open docs tab
  Widget->>Widget: Resolve embed URL (env + route map)
  Widget->>Iframe: Render iframe src="https://github.com/...-embed/..."
  Iframe->>DocsApp: Request embedded page
  DocsApp->>Iframe: Serve embed page (MDX with EmbeddedLinkInterceptor & Bridge)
  Iframe->>Bridge: Mount & post initial DOCS_HISTORY_STATE
  Bridge->>Widget: postMessage(DOCS_HISTORY_STATE, { canGoBack })
  Widget->>Widget: Update canGoBack

  User->>Iframe: Click internal link
  Iframe->>Iframe: EmbeddedLinkInterceptor rewrites → /...-embed/...
  Iframe->>Iframe: HEAD-check and navigate

  User->>Widget: Click Back
  Widget->>Iframe.contentWindow: postMessage(NAVIGATE_BACK)
  Bridge->>Iframe: Navigate back, post updated DOCS_HISTORY_STATE
  Bridge->>Widget: postMessage(DOCS_HISTORY_STATE, { canGoBack })
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Areas needing extra attention:

  • CORS header correctness and origin values in docs/next.config.mjs.
  • Env var fallback logic and runtime resolution in unified-docs-widget and apps/dashboard/src/lib/env.tsx.
  • PostMessage protocol shape, origin validation, and race conditions between iframe load and message handling (embedded-docs-message-bridgeunified-docs-widget).
  • Relative path resolution and HEAD verification in EmbeddedLinkInterceptor / EmbeddedLink.
  • Embed MDX components/layout integration for consistent styling and link behavior.

Possibly related PRs

Suggested reviewers

  • N2D4

Poem

🐇 I hop through frames and windows wide,

I stitch the docs where routes reside,
I whisper back with messages light,
Links rewritten, embed delight,
A tiny rabbit nudges docs to glide.

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 pull request title "[Docs][Site] + [Dashboard][UI] - Adds docs to Stack Companion" directly and clearly summarizes the main objective of the changeset. The title accurately reflects that the PR adds documentation capabilities to the Stack Companion component in the dashboard, which aligns with the primary changes across multiple files including the new UnifiedDocsWidget component, embedded routes/layouts, and supporting infrastructure. The title is concise, specific, and clearly communicates the purpose to developers reviewing the git history.
Description Check ✅ Passed The PR description includes the required template element (the CONTRIBUTING.md guidelines reminder comment) and goes significantly beyond the minimal template by providing comprehensive, well-organized information about the changes. The description is structured with clear sections covering Behavior, Documentation, Configuration, and Misc updates, with detailed bullet points explaining each component added or modified. This level of completeness far exceeds the minimal template requirements and provides developers with clear understanding of the PR's scope and impact.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stack-companion-docs

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7db958 and 7d738f5.

📒 Files selected for processing (1)
  • apps/dashboard/.env (1 hunks)
🧰 Additional context used
🪛 dotenv-linter (4.0.0)
apps/dashboard/.env

[warning] 6-6: [UnorderedKey] The NEXT_PUBLIC_STACK_DOCS_BASE_URL key should go before the NEXT_PUBLIC_STACK_PROJECT_ID key

(UnorderedKey)


[warning] 6-6: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: build (22.x)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: build (22.x)
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: setup-tests
  • GitHub Check: all-good
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: restart-dev-and-test
  • GitHub Check: Security Check

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 implements the "Stack Companion" documentation system, which embeds contextual documentation directly within the Stack Auth dashboard interface. The changes introduce a comprehensive embedded documentation architecture with three main components:

  1. Documentation Templates and Content: New MDX documentation files are added in docs/templates-dashboard/ covering all major dashboard sections (overview, users, teams, permissions, settings, auth-providers, analytics). These templates provide contextual help content that explains dashboard features and workflows.

  2. Embedded Documentation Infrastructure: The docs application is extended with embedded routes (/docs-embed/, /api-embed/, /dashboard-embed/) that render documentation content optimized for iframe embedding. This includes specialized layouts without navigation elements, embedded link interceptors that rewrite internal links to maintain embedded context, and CORS configuration to allow cross-origin access from the dashboard.

  3. Dashboard Integration: The dashboard's Stack Companion sidebar is enhanced with sophisticated documentation widgets (UnifiedDocsWidget and DashboardDocsWidget) that automatically display relevant documentation based on the current dashboard page. These widgets support multiple documentation types, include navigation controls, and provide seamless switching between different documentation contexts.

The system uses fumadocs for content management, with a new dashboardSource loader that processes dashboard-specific MDX content. The embedded documentation system maintains proper styling with Tailwind CSS classes optimized for constrained iframe spaces, including overflow management and responsive design considerations. The architecture allows users to access comprehensive help without leaving their current workflow, significantly improving the developer experience by reducing context switching between the dashboard and external documentation.

Confidence score: 2/5

  • This PR introduces significant functionality but contains critical production-breaking issues with hardcoded localhost URLs
  • Score reflects major deployment concerns that will cause complete failure in non-development environments
  • Pay close attention to unified-docs-widget.tsx and dashboard-docs-widget.tsx for hardcoded localhost:8104 URLs that must be resolved before deployment

26 files reviewed, 8 comments

Edit Code Review Bot Settings | Greptile

@recurseml
Copy link

recurseml bot commented Aug 29, 2025

Review by RecurseML

🔍 Review performed on 6a3459e..dde5282

✨ No bugs found, your code is sparkling clean

✅ Files analyzed, no issues (5)

apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx
docs/src/components/embedded-link-interceptor.tsx
apps/dashboard/src/components/stack-companion/dashboard-docs-widget.tsx
docs/scripts/generate-docs.js
docs/src/components/mdx/embedded-link.tsx

⏭️ Files skipped (low suspicion) (21)

apps/dashboard/src/components/stack-companion.tsx
docs/.gitignore
docs/lib/source.ts
docs/next.config.mjs
docs/source.config.ts
docs/src/app/api-embed/[[...slug]]/page.tsx
docs/src/app/api-embed/layout.tsx
docs/src/app/dashboard-embed/[[...slug]]/page.tsx
docs/src/app/dashboard-embed/layout.tsx
docs/src/app/docs-embed/[[...slug]]/page.tsx
docs/src/app/docs-embed/layout.tsx
docs/src/app/global.css
docs/src/mdx-components.tsx
docs/templates-dashboard/analytics.mdx
docs/templates-dashboard/auth-providers.mdx
docs/templates-dashboard/meta.json
docs/templates-dashboard/overview.mdx
docs/templates-dashboard/permissions.mdx
docs/templates-dashboard/settings.mdx
docs/templates-dashboard/teams.mdx
docs/templates-dashboard/users.mdx

Need help? Join our Discord

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

♻️ Duplicate comments (1)
docs/src/app/api-embed/layout.tsx (1)

1-16: Same embed-layout nits as docs-embed.

Mirror the dvh change and verify EmbeddedLinkInterceptor is a client component as noted in docs-embed/layout.tsx.

🧹 Nitpick comments (42)
docs/templates-dashboard/permissions.mdx (1)

48-57: Add a brief best-practices note and link the Companion.

Strengthen the “Permission Validation” section with least-privilege guidance and make “Stack Companion” a clickable link to its entry point.

Apply:

 ## Permission Validation
 Ensure proper access control by:
 - Testing permission assignments
 - Reviewing access logs
 - Validating permission logic
+
+### Best Practices
+- Prefer least-privilege roles; avoid granting broad project-wide permissions by default.
+- Review effective permissions after team/role changes.
+- Periodically audit dormant users and stale teams.
 
 ## Need Help?
 
-Use the Stack Companion for detailed permission configuration guidance.
+Use the [Stack Companion](</dashboard-embed/companion>) for detailed permission configuration guidance.
docs/templates-dashboard/settings.mdx (1)

28-48: Clarify duplicated “Rate limiting” bullets.

“Rate limiting” appears under both Security Settings and API Configuration; clarify scope or deduplicate to avoid confusion.

Option A (clarify scopes):

 ### Security Settings
 Configure security policies:
 - Password requirements
 - Multi-factor authentication
 - Session management
-- Rate limiting
+- Authentication rate limiting (login/signup, OTP attempts)

 ### API Configuration
 Manage API access:
 - API keys
 - Webhook endpoints
 - CORS settings
-- Rate limiting
+- API rate limiting (per-key/per-route quotas)

Option B (deduplicate to Security Settings only and replace API bullet):

- - Rate limiting
+ - SDK configuration (environments, base URLs)
docs/templates-dashboard/users.mdx (2)

2-7: Name consistency: prefer “User Management”.

Use singular form to align with common docs conventions and sidebar patterns (“User Management”).

-title: Users Management
+title: User Management
@@
-# Users Management
+# User Management

29-35: Add privacy/audit guidance when editing user data.

A short caution helps set expectations around PII and compliance.

 ### Managing User Data
 You can update user information including:
 - Profile details
 - Custom metadata
 - Contact preferences
 - Account status
+> Note: Limit access to PII to authorized roles only. Changes should be auditable (record who changed what and when).
docs/templates-dashboard/teams.mdx (1)

2-7: Name consistency: prefer “Team Management”.

Match singular form used elsewhere.

-title: Teams Management
+title: Team Management
@@
-# Teams Management
+# Team Management
docs/templates-dashboard/auth-providers.mdx (5)

21-26: Name the provider consistently as “X (formerly Twitter)”.

Minor branding nit for clarity.

-- **Twitter/X**: Social media integration
+- **X (formerly Twitter)**: Social media integration

27-31: Clarify SAML is a protocol and mention common IdPs.

Prevents confusion vs. OAuth “providers.”

-### Enterprise Providers
-- **Microsoft**: Azure AD and Office 365 integration
-- **SAML**: Enterprise single sign-on
-- **LinkedIn**: Professional network integration
+### Enterprise Providers
+- **Microsoft Entra ID (Azure AD)**: Enterprise Microsoft login
+- **SAML (via IdPs like Okta, OneLogin, Entra ID, Auth0)**: Enterprise single sign‑on
+- **LinkedIn**: Professional network integration

32-38: Add critical OAuth setup steps (security + reliability).

PKCE, exact redirect URIs, and environment-specific callbacks are easy to miss.

  ### Configuration Steps
-1. **Create OAuth Application**: Set up your app with the provider
-2. **Configure Credentials**: Add client ID and secret to Stack Auth
-3. **Set Callback URLs**: Configure redirect URLs for your application
-4. **Test Integration**: Verify the authentication flow works correctly
+1. **Create OAuth Application**: Set up your app with the provider
+2. **Configure Credentials**: Add client ID and secret to Stack Auth (store secrets server-side only)
+3. **Set Callback URLs**: Add exact authorized redirect URIs per environment (e.g., dev, staging, prod)
+4. **Enable PKCE** (recommended) and required grant types per provider
+5. (If supported) **Set post‑logout redirect URIs**
+6. **Test Integration**: Verify success, error, and cancel flows

41-47: Call out post‑logout URIs and least‑privilege scopes.

Keeps deployments secure by default.

  ### OAuth Configuration
  Each provider requires:
  - Client ID
  - Client Secret
  - Authorized redirect URIs
- - Scope permissions
+ - (If supported) Post‑logout redirect URIs
+ - Scope permissions (use least privilege; request only what you need)

54-57: Link to provider‑specific runbooks from Companion.

If you have deep links (Google/GitHub/etc.), adding them here reduces bounce.

I can add Companion deeplinks for top providers if you share their slugs.

docs/src/components/mdx/embedded-link.tsx (3)

9-26: Harden path rewriting and handle “/docs” root, queries, and hashes.

Current replace() misses “/docs” without trailing slash and query/hash forms; also guard against re‑rewriting embedded routes.

-const getEmbeddedUrl = (href: string): string => {
+const getEmbeddedUrl = (href: string): string => {
   // Handle relative links
   if (href.startsWith('/')) {
-    // Convert regular doc routes to embedded routes
-    if (href.startsWith('/docs/')) {
-      return href.replace('/docs/', '/docs-embed/');
-    }
-    if (href.startsWith('/api/')) {
-      return href.replace('/api/', '/api-embed/');
-    }
-    if (href.startsWith('/dashboard/')) {
-      return href.replace('/dashboard/', '/dashboard-embed/');
-    }
+    // Skip if already embedded
+    if (href.startsWith('/docs-embed/') || href.startsWith('/api-embed/') || href.startsWith('/dashboard-embed/')) {
+      return href;
+    }
+    // Convert regular routes to embedded routes (match with or without trailing slash)
+    if (href === '/docs' || href.startsWith('/docs/') || href.startsWith('/docs?') || href.startsWith('/docs#')) {
+      return href.replace(/^\/docs(?=\/|$)/, '/docs-embed');
+    }
+    if (href === '/api' || href.startsWith('/api/') || href.startsWith('/api?') || href.startsWith('/api#')) {
+      return href.replace(/^\/api(?=\/|$)/, '/api-embed');
+    }
+    if (href === '/dashboard' || href.startsWith('/dashboard/') || href.startsWith('/dashboard?') || href.startsWith('/dashboard#')) {
+      return href.replace(/^\/dashboard(?=\/|$)/, '/dashboard-embed');
+    }
   }
   // Return unchanged for external links or already embedded links
   return href;
 };

45-47: Protect target=_blank links against reverse‑tabnabbing.

Add rel when opening new tabs.

-  // For external links, use regular anchor tag
-  return <a href={embeddedHref} {...props}>{children}</a>;
+  // For external links, use regular anchor tag
+  const rel = props.target === '_blank'
+    ? [props.rel, 'noopener', 'noreferrer'].filter(Boolean).join(' ')
+    : props.rel;
+  return <a href={embeddedHref} {...props} rel={rel}>{children}</a>;

8-26: Deduplicate getEmbeddedUrl across the codebase.

If a similar helper exists in embedded-link-interceptor.tsx, consider exporting a shared util to avoid drift.

Would you like me to extract a shared helper (e.g., docs/src/lib/embedded-url.ts) and update both call sites?

docs/templates-dashboard/analytics.mdx (2)

46-51: Verify feature availability (“CSV export”, “PDF generation”, “API access”, “Custom dashboard”).

If any are roadmap-only, mark as “coming soon” or scope by plan to avoid overpromising.

I can update copy once you confirm which features ship today vs. later.


21-37: Tighten metric definitions (time windows, filters).

Add brief definitions (e.g., DAU/MAU timezones, sign‑in “success” criteria) to reduce ambiguity.

docs/src/app/global.css (3)

198-205: Be cautious hiding scrollbars (a11y).

Hidden scrollbars can hurt discoverability and keyboard users. Limit usage to the embed container only, and ensure visible focus/scroll affordances.

Do all elements with .scrollbar-hide still meet WCAG 2.2 focus visibility?


241-249: Avoid aggressive word-break on links/code.

word-break: break-all can shatter readable text. Prefer overflow-wrap:anywhere for long tokens/URLs.

-.prose a[href*="://"] {
-  word-break: break-all;
-}
+.prose a[href*="://"] {
+  overflow-wrap: anywhere;
+  word-break: break-word;
+}
 
 /* Break very long strings that have no spaces (like tokens, hashes, etc.) */
-.prose code:not(pre code) {
-  word-break: break-all;
-}
+.prose code:not(pre code) {
+  overflow-wrap: anywhere;
+  word-break: break-word;
+  hyphens: auto;
+}

227-233: Consider momentum scrolling on narrow tables.

Improves mobile UX inside embeds.

 .prose table {
   /* Make tables responsive */
   display: block;
   overflow-x: auto;
   white-space: nowrap;
   max-width: 100%;
+  -webkit-overflow-scrolling: touch;
 }
apps/dashboard/src/components/stack-companion/dashboard-docs-widget.tsx (7)

16-26: Remove unused ROUTE_TO_DOC_MAP and prefer ES6 Map per guidelines

This constant isn’t referenced; drop it to avoid drift. Also, for future lookups, prefer Map over Record.

-// Map dashboard routes to documentation pages
-const ROUTE_TO_DOC_MAP: Record<string, string> = {
-  '/users': 'users',
-  '/teams': 'teams',
-  '/permissions': 'permissions',
-  '/settings': 'settings',
-  '/auth-providers': 'auth-providers',
-  '/analytics': 'analytics',
-  '/': 'overview',
-  '': 'overview',
-};
+// (removed) Unused; route resolution happens via DASHBOARD_ROUTE_PATTERNS.

29-37: Switch TITLE_MAP to ES6 Map

Aligns with repo guideline and avoids accidental key collisions.

-// Title mapping for pages
-const TITLE_MAP: Record<string, string> = {
-  'overview': 'Dashboard Overview',
-  'users': 'Users Management',
-  'teams': 'Teams Management',
-  'permissions': 'Permissions Management',
-  'settings': 'Project Settings',
-  'auth-providers': 'Authentication Providers',
-  'analytics': 'Analytics & Insights',
-};
+// Title mapping for pages
+const TITLE_MAP = new Map<string, string>([
+  ['overview', 'Dashboard Overview'],
+  ['users', 'Users Management'],
+  ['teams', 'Teams Management'],
+  ['permissions', 'Permissions Management'],
+  ['settings', 'Project Settings'],
+  ['auth-providers', 'Authentication Providers'],
+  ['analytics', 'Analytics & Insights'],
+]);

Follow-ups needed where the map is read; see lines 75 and 212.


39-48: Auth route mapping: handle both /auth-methods and /auth-providers

If the app ever routes to /auth-providers directly, we’ll miss it. Add an explicit pattern.

   { pattern: /\/settings(?:\/.*)?$/, docPage: 'settings' },
   { pattern: /\/auth-methods(?:\/.*)?$/, docPage: 'auth-providers' }, // Route is auth-methods but docs are auth-providers
+  { pattern: /\/auth-providers(?:\/.*)?$/, docPage: 'auth-providers' },
   { pattern: /\/analytics(?:\/.*)?$/, docPage: 'analytics' },

Please confirm actual dashboard paths.


191-199: Harden iframe attrs and improve UX

Add lazy loading, referrer policy, and popup allowances (if embedded links open windows).

-            <iframe
+            <iframe
               src={docContent.url}
               className="w-full h-full border-0 rounded-md bg-white dark:bg-gray-900"
               onLoad={handleIframeLoad}
               onError={handleIframeError}
               title={`Documentation: ${docContent.title}`}
-              sandbox="allow-scripts allow-same-origin"
+              sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox"
+              referrerPolicy="strict-origin-when-cross-origin"
+              loading="lazy"
             />

If popups aren’t desired from inside the embed, drop the allow-popups flags.


75-75: Update title access for Map

Follow-up to Map switch.

-  const title = TITLE_MAP[page] || `Dashboard ${page}`;
+  const title = TITLE_MAP.get(page) ?? `Dashboard ${page}`;

212-213: Update prompt title access for Map

Follow-up to Map switch.

-                    Switch to <span className="font-medium">{TITLE_MAP[getDashboardPage(pathname)] || 'current page'}</span>?
+                    Switch to <span className="font-medium">{TITLE_MAP.get(getDashboardPage(pathname)) ?? 'current page'}</span>?

90-116: Simplify effect logic to avoid extra runs

Current deps (docContent/currentPageDoc) can retrigger the effect; splitting “initial load” and “route change while active” into two effects will reduce state juggling.

I can provide a small refactor if you want it applied here.

apps/dashboard/src/components/stack-companion.tsx (2)

12-12: Lazy-load UnifiedDocsWidget to cut initial bundle

Avoid pulling the docs embed code until the Docs tab is opened.

Example:

import dynamic from 'next/dynamic';
// …
const UnifiedDocsWidget = dynamic(
  () => import('./stack-companion/unified-docs-widget').then(m => m.UnifiedDocsWidget),
  { ssr: false }
);

366-366: Render condition is fine; consider passing isActive=activeItem==='docs' for clarity

No behavior change; slightly clearer intent and future-proof if reused.

-  <UnifiedDocsWidget isActive={true} />
+  <UnifiedDocsWidget isActive={activeItem === 'docs'} />
docs/lib/source.ts (1)

42-50: Confirm /dashboard-embed loader exists (or add it here)

Embeds point to /dashboard-embed/. If that route isn’t defined elsewhere, add a companion loader to mirror /dashboard with embedded components.

Example (add alongside):

export const dashboardEmbedSource = loader({
  baseUrl: '/dashboard-embed',
  source: dashboard.toFumadocsSource(),
  pageTree: { attachFile },
  icon: createIconResolver(),
});
docs/templates-dashboard/overview.mdx (1)

14-19: Link the quick navigation items to their pages

Improves discoverability and verifies routes.

- - **Users**: Manage user accounts, view user details, and handle user-related operations
+ - **[Users](/dashboard/users)**: Manage user accounts, view user details, and handle user-related operations
- - **Teams**: Create and manage teams, handle team memberships and permissions  
+ - **[Teams](/dashboard/teams)**: Create and manage teams, handle team memberships and permissions  
- - **Permissions**: Configure role-based access control and user permissions
+ - **[Permissions](/dashboard/permissions)**: Configure role-based access control and user permissions
- - **Settings**: Configure your project settings, authentication providers, and integrations
+ - **[Settings](/dashboard/settings)**: Configure your project settings, authentication providers, and integrations
- - **Analytics**: View authentication metrics and user engagement data
+ - **[Analytics](/dashboard/analytics)**: View authentication metrics and user engagement data

If the embed uses a custom link component, swap for it as appropriate.

docs/src/app/docs-embed/[[...slug]]/page.tsx (2)

5-11: Fix params typing; Next.js App Router does not pass a Promise for params

params should be a plain object. You don't need await params. This also improves type-safety and consistency with Next types.

-export default async function DocsEmbedPage({
+export default async function DocsEmbedPage({
   params,
 }: {
-  params: Promise<{ slug?: string[] }>,
+  params: { slug?: string[] },
 }) {
-  const { slug } = await params;
+  const { slug } = params;

3-3: Prefer notFound() over redirect("/") for missing pages

Use notFound() to return a proper 404 and avoid unexpected cross-origin redirects inside embeds.

-import { redirect } from 'next/navigation';
+import { notFound } from 'next/navigation';
...
-  if (!page) redirect("/");
+  if (!page) notFound();

Also applies to: 13-13

docs/src/app/api-embed/[[...slug]]/page.tsx (2)

5-11: Align params typing with Next.js conventions

Same as docs-embed: params should not be a Promise; drop await.

-export default async function ApiEmbedPage({
+export default async function ApiEmbedPage({
   params,
 }: {
-  params: Promise<{ slug?: string[] }>,
+  params: { slug?: string[] },
 }) {
-  const { slug } = await params;
+  const { slug } = params;

3-3: Return 404 instead of redirect for missing pages

Prefer notFound() for correct HTTP semantics in embeds.

-import { redirect } from 'next/navigation';
+import { notFound } from 'next/navigation';
...
-  if (!page) redirect("/");
+  if (!page) notFound();

Also applies to: 13-13

docs/src/app/dashboard-embed/layout.tsx (1)

6-14: Use dynamic viewport units to avoid mobile "100vh" issues

Replace h-screen/min-h-screen with 100dvh to prevent overflow under mobile browser UI.

-    <div className="min-h-screen bg-fd-background">
+    <div className="min-h-[100dvh] bg-fd-background">
...
-      <main className="h-screen overflow-hidden">
+      <main className="h-[100dvh] overflow-hidden">
docs/src/app/docs-embed/layout.tsx (1)

9-11: Use dvh to avoid mobile viewport bugs.

Replace h-screen/h-full with h-dvh (and keep the inner overflow-y-auto) to avoid iOS Safari 100vh issues in iframes.

Apply:

-      <main className="h-screen overflow-hidden">
-        <div className="h-full overflow-y-auto overflow-x-hidden scrollbar-hide">
+      <main className="h-dvh overflow-hidden">
+        <div className="h-dvh overflow-y-auto overflow-x-hidden scrollbar-hide">
docs/scripts/generate-docs.js (1)

368-417: Include dashboard static assets (images) alongside MDX.

generateDashboardDocs() copies only .mdx and optional meta.json. If dashboard docs reference images (e.g., imgs), they’ll 404.

Append inside generateDashboardDocs() after writing meta.json:

   console.log('Dashboard documentation generation complete!');
 }
 
+// Copy dashboard asset dirs if present (parity with copyAssets())
+const DASHBOARD_ASSET_DIRS = ['imgs'];
+for (const dir of DASHBOARD_ASSET_DIRS) {
+  const srcDir = path.join(DASHBOARD_TEMPLATE_DIR, dir);
+  if (fs.existsSync(srcDir)) {
+    const files = glob.sync('**/*', { cwd: srcDir, nodir: true });
+    for (const file of files) {
+      const srcFile = path.join(srcDir, file);
+      const destFile = path.join(DASHBOARD_OUTPUT_DIR, dir, file);
+      fs.mkdirSync(path.dirname(destFile), { recursive: true });
+      fs.copyFileSync(srcFile, destFile);
+      console.log(`Copied dashboard asset: ${srcFile} -> ${destFile}`);
+    }
+  }
+}
apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (2)

20-29: Prefer ES6 Map over Record for title map (per repo guideline).

Use Map for key lookups; adjust call site accordingly.

Apply:

-const DASHBOARD_TITLE_MAP: Record<string, string> = {
-  'overview': 'Dashboard Overview',
-  'users': 'Users Management',
-  'teams': 'Teams Management',
-  'permissions': 'Permissions Management',
-  'settings': 'Project Settings',
-  'auth-providers': 'Authentication Providers',
-  'analytics': 'Analytics & Insights',
-};
+const DASHBOARD_TITLE_MAP = new Map<string, string>([
+  ['overview', 'Dashboard Overview'],
+  ['users', 'Users Management'],
+  ['teams', 'Teams Management'],
+  ['permissions', 'Permissions Management'],
+  ['settings', 'Project Settings'],
+  ['auth-providers', 'Authentication Providers'],
+  ['analytics', 'Analytics & Insights'],
+]);
-      const title = DASHBOARD_TITLE_MAP[page] || `Dashboard ${page}`;
+      const title = DASHBOARD_TITLE_MAP.get(page) ?? `Dashboard ${page}`;

Also applies to: 88-89


58-75: Remove unused DOC_TYPE_OPTIONS or wire it to UI.

It’s currently unused; trim to reduce dead code or integrate into a selector.

Apply:

-// Navigation options for different doc types
-const DOC_TYPE_OPTIONS: Array<{ type: DocType, label: string, description: string }> = [
-  {
-    type: 'dashboard',
-    label: 'Dashboard Docs',
-    description: 'Documentation for this dashboard page'
-  },
-  {
-    type: 'docs',
-    label: 'Main Docs',
-    description: 'Complete Stack Auth documentation'
-  },
-  {
-    type: 'api',
-    label: 'API Reference',
-    description: 'API endpoints and reference'
-  },
-];
docs/src/components/embedded-link-interceptor.tsx (4)

80-86: Remove unused navigation history state.

setNavigationHistory is write-only and not rendered. Trim for clarity.

-  const [, setNavigationHistory] = useState<string[]>([]);
-
-  // Initialize navigation history with current URL
-  useEffect(() => {
-    setNavigationHistory([window.location.pathname]);
-  }, []);
+  // (removed) navigation history state
-            // Add to navigation history
-            setNavigationHistory(prev => [...prev, embeddedHref]);
+            // navigation history removed

Also applies to: 140-142


127-133: Guard console logging or remove.

Avoid noisy logs in production.

-        // Debug logging
-        console.log('Link Debug:', {
-          originalHref: href,
-          currentPath,
-          resolvedHref: embeddedHref
-        });
+        // Debug logging (guarded)
+        if (process.env.NEXT_PUBLIC_EMBED_DEBUG === '1') {
+          console.debug('Link Debug:', { originalHref: href, currentPath, resolvedHref: embeddedHref });
+        }

171-181: Hide the debug UI behind an env flag to avoid exposing it to end users.

Gate the toggle/window with NEXT_PUBLIC_EMBED_DEBUG === '1'.

-      {/* Debug Toggle Button */}
-      <div className="fixed top-4 right-4 z-50">
+      {process.env.NEXT_PUBLIC_EMBED_DEBUG === '1' && (
+      {/* Debug Toggle Button */}
+      <div className="fixed top-4 right-4 z-50">
         <button
           onClick={() => setShowDebug(!showDebug)}
           className="px-3 py-2 bg-gray-800 hover:bg-gray-700 text-white text-xs font-medium rounded-md shadow-lg transition-colors"
           title="Toggle debug window"
         >
           Debug {showDebug ? '▼' : '▲'}
         </button>
       </div>
 
-      {/* Debug Window */}
-      {showDebug && (
+      {/* Debug Window */}
+      {showDebug && (
         <div className="fixed top-16 right-4 w-96 max-h-96 bg-gray-900 text-white text-xs rounded-lg shadow-2xl z-50 overflow-hidden">
           ...
         </div>
-      )}
+      )}
+      )}

Also applies to: 183-257


5-67: Extract shared URL‐rewriting helper. Both embedded-link-interceptor.tsx and mdx/embedded-link.tsx duplicate the /docs/, /api/, and /dashboard/-embed/ mappings—pull that logic into a common util to keep them in sync.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6a3459e and ca42d6c.

📒 Files selected for processing (26)
  • apps/dashboard/src/components/stack-companion.tsx (2 hunks)
  • apps/dashboard/src/components/stack-companion/dashboard-docs-widget.tsx (1 hunks)
  • apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (1 hunks)
  • docs/.gitignore (1 hunks)
  • docs/lib/source.ts (2 hunks)
  • docs/next.config.mjs (1 hunks)
  • docs/scripts/generate-docs.js (3 hunks)
  • docs/source.config.ts (1 hunks)
  • docs/src/app/api-embed/[[...slug]]/page.tsx (1 hunks)
  • docs/src/app/api-embed/layout.tsx (1 hunks)
  • docs/src/app/dashboard-embed/[[...slug]]/page.tsx (1 hunks)
  • docs/src/app/dashboard-embed/layout.tsx (1 hunks)
  • docs/src/app/docs-embed/[[...slug]]/page.tsx (1 hunks)
  • docs/src/app/docs-embed/layout.tsx (1 hunks)
  • docs/src/app/global.css (1 hunks)
  • docs/src/components/embedded-link-interceptor.tsx (1 hunks)
  • docs/src/components/mdx/embedded-link.tsx (1 hunks)
  • docs/src/mdx-components.tsx (3 hunks)
  • docs/templates-dashboard/analytics.mdx (1 hunks)
  • docs/templates-dashboard/auth-providers.mdx (1 hunks)
  • docs/templates-dashboard/meta.json (1 hunks)
  • docs/templates-dashboard/overview.mdx (1 hunks)
  • docs/templates-dashboard/permissions.mdx (1 hunks)
  • docs/templates-dashboard/settings.mdx (1 hunks)
  • docs/templates-dashboard/teams.mdx (1 hunks)
  • docs/templates-dashboard/users.mdx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer ES6 Map over Record where feasible

Files:

  • docs/src/app/dashboard-embed/layout.tsx
  • apps/dashboard/src/components/stack-companion.tsx
  • docs/source.config.ts
  • docs/lib/source.ts
  • docs/src/mdx-components.tsx
  • docs/src/components/mdx/embedded-link.tsx
  • docs/src/app/docs-embed/layout.tsx
  • docs/src/app/api-embed/layout.tsx
  • docs/src/app/dashboard-embed/[[...slug]]/page.tsx
  • docs/src/app/api-embed/[[...slug]]/page.tsx
  • docs/src/app/docs-embed/[[...slug]]/page.tsx
  • docs/src/components/embedded-link-interceptor.tsx
  • apps/dashboard/src/components/stack-companion/dashboard-docs-widget.tsx
  • apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx
🧬 Code graph analysis (8)
docs/src/app/dashboard-embed/layout.tsx (1)
docs/src/components/embedded-link-interceptor.tsx (1)
  • EmbeddedLinkInterceptor (77-260)
docs/src/mdx-components.tsx (1)
docs/src/components/mdx/embedded-link.tsx (1)
  • EmbeddedLink (28-47)
docs/src/app/docs-embed/layout.tsx (1)
docs/src/components/embedded-link-interceptor.tsx (1)
  • EmbeddedLinkInterceptor (77-260)
docs/src/app/api-embed/layout.tsx (1)
docs/src/components/embedded-link-interceptor.tsx (1)
  • EmbeddedLinkInterceptor (77-260)
docs/src/app/dashboard-embed/[[...slug]]/page.tsx (1)
docs/src/mdx-components.tsx (1)
  • getEmbeddedMDXComponents (88-94)
docs/src/app/api-embed/[[...slug]]/page.tsx (1)
docs/src/mdx-components.tsx (1)
  • getEmbeddedMDXComponents (88-94)
docs/src/app/docs-embed/[[...slug]]/page.tsx (1)
docs/src/mdx-components.tsx (1)
  • getEmbeddedMDXComponents (88-94)
docs/next.config.mjs (1)
apps/dashboard/next.config.mjs (1)
  • async headers() { (94-127)
🪛 LanguageTool
docs/templates-dashboard/settings.mdx

[grammar] ~14-~14: There might be a mistake here.
Context: ...c.) - Security policies and requirements - Email templates and branding - API keys ...

(QB_NEW_EN)


[grammar] ~15-~15: There might be a mistake here.
Context: ...uirements - Email templates and branding - API keys and webhooks - Project integrat...

(QB_NEW_EN)


[grammar] ~16-~16: There might be a mistake here.
Context: ...tes and branding - API keys and webhooks - Project integrations ## Configuration A...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ...Microsoft, etc. - Custom OAuth providers - Provider-specific settings - Callback UR...

(QB_NEW_EN)


[grammar] ~25-~25: There might be a mistake here.
Context: ...h providers - Provider-specific settings - Callback URL configuration ### Security...

(QB_NEW_EN)


[grammar] ~28-~28: There might be a mistake here.
Context: ...URL configuration ### Security Settings Configure security policies: - Password ...

(QB_NEW_EN)


[grammar] ~29-~29: There might be a mistake here.
Context: ...ty Settings Configure security policies: - Password requirements - Multi-factor aut...

(QB_NEW_EN)


[grammar] ~30-~30: There might be a mistake here.
Context: ...curity policies: - Password requirements - Multi-factor authentication - Session ma...

(QB_NEW_EN)


[grammar] ~31-~31: There might be a mistake here.
Context: ...quirements - Multi-factor authentication - Session management - Rate limiting ### ...

(QB_NEW_EN)


[grammar] ~32-~32: There might be a mistake here.
Context: ...ctor authentication - Session management - Rate limiting ### Branding & Templates ...

(QB_NEW_EN)


[grammar] ~35-~35: There might be a mistake here.
Context: ... Rate limiting ### Branding & Templates Customize the user experience: - Email t...

(QB_NEW_EN)


[grammar] ~36-~36: There might be a mistake here.
Context: ...Templates Customize the user experience: - Email templates - Login page branding - ...

(QB_NEW_EN)


[grammar] ~37-~37: There might be a mistake here.
Context: ...e the user experience: - Email templates - Login page branding - Custom domains - T...

(QB_NEW_EN)


[grammar] ~38-~38: There might be a mistake here.
Context: ... - Email templates - Login page branding - Custom domains - Theme configuration ##...

(QB_NEW_EN)


[grammar] ~39-~39: There might be a mistake here.
Context: ...s - Login page branding - Custom domains - Theme configuration ### API Configurati...

(QB_NEW_EN)


[grammar] ~42-~42: There might be a mistake here.
Context: ...eme configuration ### API Configuration Manage API access: - API keys - Webhook ...

(QB_NEW_EN)


[grammar] ~43-~43: There might be a mistake here.
Context: ...### API Configuration Manage API access: - API keys - Webhook endpoints - CORS sett...

(QB_NEW_EN)


[grammar] ~44-~44: There might be a mistake here.
Context: ...figuration Manage API access: - API keys - Webhook endpoints - CORS settings - Rate...

(QB_NEW_EN)


[grammar] ~45-~45: There might be a mistake here.
Context: ...I access: - API keys - Webhook endpoints - CORS settings - Rate limiting ## Need H...

(QB_NEW_EN)


[grammar] ~46-~46: There might be a mistake here.
Context: ...keys - Webhook endpoints - CORS settings - Rate limiting ## Need Help? Consult th...

(QB_NEW_EN)

docs/templates-dashboard/analytics.mdx

[grammar] ~12-~12: There might be a mistake here.
Context: ...erview Track key metrics to understand: - User authentication patterns - Sign-up a...

(QB_NEW_EN)


[grammar] ~13-~13: There might be a mistake here.
Context: ...derstand: - User authentication patterns - Sign-up and conversion rates - Popular a...

(QB_NEW_EN)


[grammar] ~14-~14: There might be a mistake here.
Context: ... patterns - Sign-up and conversion rates - Popular authentication methods - User en...

(QB_NEW_EN)


[grammar] ~15-~15: There might be a mistake here.
Context: ...n rates - Popular authentication methods - User engagement trends - System performa...

(QB_NEW_EN)


[grammar] ~16-~16: There might be a mistake here.
Context: ...ication methods - User engagement trends - System performance metrics ## Key Metri...

(QB_NEW_EN)


[grammar] ~21-~21: There might be a mistake here.
Context: ...ey Metrics ### Authentication Analytics - Daily/Monthly Active Users: Track user...

(QB_NEW_EN)


[grammar] ~27-~27: There might be a mistake here.
Context: ...ders are most popular ### User Behavior - Session Duration: Understand user enga...

(QB_NEW_EN)


[grammar] ~33-~33: There might be a mistake here.
Context: ...users' platforms ### System Performance - API Response Times: Monitor system per...

(QB_NEW_EN)


[grammar] ~40-~40: There might be a mistake here.
Context: ...ata Visualization ### Charts and Graphs - Time series data for trends - Pie charts...

(QB_NEW_EN)


[grammar] ~41-~41: There might be a mistake here.
Context: ...and Graphs - Time series data for trends - Pie charts for distribution analysis - B...

(QB_NEW_EN)


[grammar] ~42-~42: There might be a mistake here.
Context: ...s - Pie charts for distribution analysis - Bar charts for comparative metrics - Hea...

(QB_NEW_EN)


[grammar] ~43-~43: There might be a mistake here.
Context: ...sis - Bar charts for comparative metrics - Heatmaps for geographic data ### Export...

(QB_NEW_EN)


[grammar] ~46-~46: There might be a mistake here.
Context: ... for geographic data ### Export Options - CSV data export - PDF report generation ...

(QB_NEW_EN)


[grammar] ~47-~47: There might be a mistake here.
Context: ...ta ### Export Options - CSV data export - PDF report generation - API access to an...

(QB_NEW_EN)


[grammar] ~48-~48: There might be a mistake here.
Context: ... CSV data export - PDF report generation - API access to analytics data - Custom da...

(QB_NEW_EN)


[grammar] ~49-~49: There might be a mistake here.
Context: ...eneration - API access to analytics data - Custom dashboard creation ## Need Help?...

(QB_NEW_EN)

docs/templates-dashboard/permissions.mdx

[grammar] ~12-~12: There might be a mistake here.
Context: ...access to your application resources by: - Defining custom permissions - Creating r...

(QB_NEW_EN)


[grammar] ~13-~13: There might be a mistake here.
Context: ...ources by: - Defining custom permissions - Creating roles and permission sets - Ass...

(QB_NEW_EN)


[grammar] ~14-~14: There might be a mistake here.
Context: ...ons - Creating roles and permission sets - Assigning permissions to users and teams...

(QB_NEW_EN)


[grammar] ~15-~15: There might be a mistake here.
Context: ...Assigning permissions to users and teams - Managing permission inheritance ## Perm...

(QB_NEW_EN)


[grammar] ~20-~20: There might be a mistake here.
Context: ...ermission Types ### Project Permissions Global permissions that apply across you...

(QB_NEW_EN)


[grammar] ~21-~21: There might be a mistake here.
Context: ...s that apply across your entire project: - Admin access - User management - Team ma...

(QB_NEW_EN)


[grammar] ~22-~22: There might be a mistake here.
Context: ...ross your entire project: - Admin access - User management - Team management - Sett...

(QB_NEW_EN)


[grammar] ~23-~23: There might be a mistake here.
Context: ...roject: - Admin access - User management - Team management - Settings configuration...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ...cess - User management - Team management - Settings configuration ### Team Permiss...

(QB_NEW_EN)


[grammar] ~27-~27: There might be a mistake here.
Context: ...ings configuration ### Team Permissions Permissions specific to team contexts: -...

(QB_NEW_EN)


[grammar] ~28-~28: There might be a mistake here.
Context: ...s Permissions specific to team contexts: - Team membership management - Team resour...

(QB_NEW_EN)


[grammar] ~29-~29: There might be a mistake here.
Context: ...m contexts: - Team membership management - Team resource access - Team-specific ope...

(QB_NEW_EN)


[grammar] ~30-~30: There might be a mistake here.
Context: ...ership management - Team resource access - Team-specific operations ### Custom Per...

(QB_NEW_EN)


[grammar] ~33-~33: There might be a mistake here.
Context: ...cific operations ### Custom Permissions Define your own permissions for: - Appli...

(QB_NEW_EN)


[grammar] ~34-~34: There might be a mistake here.
Context: ...issions Define your own permissions for: - Application-specific features - Resource...

(QB_NEW_EN)


[grammar] ~35-~35: There might be a mistake here.
Context: ...ons for: - Application-specific features - Resource-level access control - Custom b...

(QB_NEW_EN)


[grammar] ~36-~36: There might be a mistake here.
Context: ...features - Resource-level access control - Custom business logic ## Managing Permi...

(QB_NEW_EN)


[grammar] ~41-~41: There might be a mistake here.
Context: ...g Permissions ### Assigning Permissions Grant permissions through: - Direct user...

(QB_NEW_EN)


[grammar] ~42-~42: There might be a mistake here.
Context: ...g Permissions Grant permissions through: - Direct user assignment - Team membership...

(QB_NEW_EN)


[grammar] ~43-~43: There might be a mistake here.
Context: ...ssions through: - Direct user assignment - Team membership - Role-based assignment ...

(QB_NEW_EN)


[grammar] ~44-~44: There might be a mistake here.
Context: ...Direct user assignment - Team membership - Role-based assignment - Permission inher...

(QB_NEW_EN)


[grammar] ~45-~45: There might be a mistake here.
Context: ... Team membership - Role-based assignment - Permission inheritance ### Permission V...

(QB_NEW_EN)


[grammar] ~48-~48: There might be a mistake here.
Context: ...n inheritance ### Permission Validation Ensure proper access control by: - Testi...

(QB_NEW_EN)


[grammar] ~49-~49: There might be a mistake here.
Context: ...idation Ensure proper access control by: - Testing permission assignments - Reviewi...

(QB_NEW_EN)

docs/templates-dashboard/teams.mdx

[grammar] ~12-~12: There might be a mistake here.
Context: ...ontrol at scale. From this page you can: - Create new teams - Manage team membershi...

(QB_NEW_EN)


[grammar] ~20-~20: There might be a mistake here.
Context: ... ## Team Operations ### Creating Teams Set up new teams with: - Team name and d...

(QB_NEW_EN)


[grammar] ~21-~21: There might be a mistake here.
Context: ...## Creating Teams Set up new teams with: - Team name and description - Initial memb...

(QB_NEW_EN)


[grammar] ~22-~22: There might be a mistake here.
Context: ... teams with: - Team name and description - Initial members - Default permissions - ...

(QB_NEW_EN)


[grammar] ~23-~23: There might be a mistake here.
Context: ...m name and description - Initial members - Default permissions - Team settings ###...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ... - Initial members - Default permissions - Team settings ### Managing Members Cont...

(QB_NEW_EN)


[grammar] ~27-~27: There might be a mistake here.
Context: ...ns - Team settings ### Managing Members Control team membership by: - Adding new...

(QB_NEW_EN)


[grammar] ~28-~28: There might be a mistake here.
Context: ...ging Members Control team membership by: - Adding new members - Removing members - ...

(QB_NEW_EN)


[grammar] ~29-~29: There might be a mistake here.
Context: ...team membership by: - Adding new members - Removing members - Changing member roles...

(QB_NEW_EN)


[grammar] ~30-~30: There might be a mistake here.
Context: ... - Adding new members - Removing members - Changing member roles - Setting team-spe...

(QB_NEW_EN)


[grammar] ~31-~31: There might be a mistake here.
Context: ...Removing members - Changing member roles - Setting team-specific permissions ### T...

(QB_NEW_EN)


[grammar] ~34-~34: There might be a mistake here.
Context: ...ecific permissions ### Team Permissions Configure what team members can access: ...

(QB_NEW_EN)


[grammar] ~35-~35: There might be a mistake here.
Context: ... Configure what team members can access: - Team-level permissions - Resource access...

(QB_NEW_EN)


[grammar] ~36-~36: There might be a mistake here.
Context: ...ers can access: - Team-level permissions - Resource access control - Role-based res...

(QB_NEW_EN)


[grammar] ~37-~37: There might be a mistake here.
Context: ...el permissions - Resource access control - Role-based restrictions ## Need Help? ...

(QB_NEW_EN)

docs/templates-dashboard/users.mdx

[grammar] ~12-~12: There might be a mistake here.
Context: ...n. ## Overview From this page you can: - View all registered users - Search and f...

(QB_NEW_EN)


[grammar] ~25-~25: There might be a mistake here.
Context: ...uthentication methods - Team memberships - Permission assignments - Recent activity...

(QB_NEW_EN)


[grammar] ~26-~26: There might be a mistake here.
Context: ...eam memberships - Permission assignments - Recent activity ### Managing User Data ...

(QB_NEW_EN)


[grammar] ~29-~29: There might be a mistake here.
Context: ... Recent activity ### Managing User Data You can update user information includin...

(QB_NEW_EN)


[grammar] ~30-~30: There might be a mistake here.
Context: ...u can update user information including: - Profile details - Custom metadata - Cont...

(QB_NEW_EN)


[grammar] ~31-~31: There might be a mistake here.
Context: ...information including: - Profile details - Custom metadata - Contact preferences - ...

(QB_NEW_EN)


[grammar] ~32-~32: There might be a mistake here.
Context: ...ing: - Profile details - Custom metadata - Contact preferences - Account status ##...

(QB_NEW_EN)


[grammar] ~33-~33: There might be a mistake here.
Context: ... - Custom metadata - Contact preferences - Account status ### User Permissions Con...

(QB_NEW_EN)


[grammar] ~36-~36: There might be a mistake here.
Context: ...s - Account status ### User Permissions Control what users can access by: - Assi...

(QB_NEW_EN)


[grammar] ~37-~37: There might be a mistake here.
Context: ...ssions Control what users can access by: - Assigning roles - Setting specific permi...

(QB_NEW_EN)


[grammar] ~38-~38: There might be a mistake here.
Context: ...t users can access by: - Assigning roles - Setting specific permissions - Managing ...

(QB_NEW_EN)


[grammar] ~39-~39: There might be a mistake here.
Context: ...ing roles - Setting specific permissions - Managing team memberships ## Need Help?...

(QB_NEW_EN)

docs/templates-dashboard/auth-providers.mdx

[grammar] ~13-~13: There might be a mistake here.
Context: ...oviders (Google, GitHub, Facebook, etc.) - Enterprise providers (Microsoft, SAML, e...

(QB_NEW_EN)


[grammar] ~15-~15: There might be a mistake here.
Context: ...ft, SAML, etc.) - Custom OAuth providers - Passwordless options ## Supported Provi...

(QB_NEW_EN)


[grammar] ~20-~20: There might be a mistake here.
Context: ... Providers ### Popular Social Providers - Google: OAuth 2.0 integration with Goo...

(QB_NEW_EN)


[grammar] ~21-~21: There might be a mistake here.
Context: ...uth 2.0 integration with Google accounts - GitHub: Perfect for developer-focused ...

(QB_NEW_EN)


[grammar] ~22-~22: There might be a mistake here.
Context: ...rfect for developer-focused applications - Facebook: Social login for consumer ap...

(QB_NEW_EN)


[grammar] ~23-~23: There might be a mistake here.
Context: ...: Social login for consumer applications - Discord: Great for gaming and communit...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ...d**: Great for gaming and community apps - Twitter/X: Social media integration #...

(QB_NEW_EN)


[grammar] ~27-~27: There might be a mistake here.
Context: ...ia integration ### Enterprise Providers - Microsoft: Azure AD and Office 365 int...

(QB_NEW_EN)


[grammar] ~28-~28: There might be a mistake here.
Context: ...t**: Azure AD and Office 365 integration - SAML: Enterprise single sign-on - **Li...

(QB_NEW_EN)


[grammar] ~29-~29: There might be a mistake here.
Context: ...on - SAML: Enterprise single sign-on - LinkedIn: Professional network integra...

(QB_NEW_EN)


[grammar] ~41-~41: There might be a mistake here.
Context: ...ovider Settings ### OAuth Configuration Each provider requires: - Client ID - Cl...

(QB_NEW_EN)


[grammar] ~42-~42: There might be a mistake here.
Context: ...th Configuration Each provider requires: - Client ID - Client Secret - Authorized r...

(QB_NEW_EN)


[grammar] ~43-~43: There might be a mistake here.
Context: ...tion Each provider requires: - Client ID - Client Secret - Authorized redirect URIs...

(QB_NEW_EN)


[grammar] ~44-~44: There might be a mistake here.
Context: ...er requires: - Client ID - Client Secret - Authorized redirect URIs - Scope permiss...

(QB_NEW_EN)


[grammar] ~45-~45: There might be a mistake here.
Context: ...Client Secret - Authorized redirect URIs - Scope permissions ### Advanced Options ...

(QB_NEW_EN)


[grammar] ~48-~48: There might be a mistake here.
Context: ... Scope permissions ### Advanced Options - Custom button styling - Provider-specifi...

(QB_NEW_EN)


[grammar] ~49-~49: There might be a mistake here.
Context: ...Advanced Options - Custom button styling - Provider-specific settings - User data m...

(QB_NEW_EN)


[grammar] ~50-~50: There might be a mistake here.
Context: ...ton styling - Provider-specific settings - User data mapping - Permission scopes #...

(QB_NEW_EN)


[grammar] ~51-~51: There might be a mistake here.
Context: ...er-specific settings - User data mapping - Permission scopes ## Need Help? Use th...

(QB_NEW_EN)

🪛 Biome (2.1.2)
apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx

[error] 220-220: src is assigned to itself.

This is where is assigned.

Self assignments have no effect and can be removed.

(lint/correctness/noSelfAssign)

⏰ 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: lint_and_build (latest)
  • GitHub Check: docker
  • GitHub Check: setup-tests
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: Security Check
🔇 Additional comments (14)
docs/.gitignore (1)

30-35: Good addition: ignore generated dashboard docs output.

Adding /content/dashboard/ aligns with existing generated content ignores and prevents noisy diffs. No action needed.

docs/templates-dashboard/teams.mdx (1)

12-17: Verify “team analytics” availability or rephrase.

If analytics aren’t yet in the Teams section, reword to avoid overpromising (e.g., “View team activity”).

Would you confirm the current dashboard includes team-level analytics in this view? If not, I can propose precise wording.

docs/next.config.mjs (1)

12-51: Scope CORS headers to development, use dynamic origin, restrict methods, add Vary and caching, and verify credentials

  • Wrap the existing headers() return in a if (process.env.NODE_ENV === 'development') guard in docs/next.config.mjs.
  • Replace hard-coded origin with process.env.DASHBOARD_APP_ORIGIN ?? 'http://localhost:8101'.
  • Change Access-Control-Allow-Methods to only GET, OPTIONS.
  • Add Vary: Origin and Access-Control-Max-Age: 600 to each route.
  • Confirm whether cookies are sent; if so, also add Access-Control-Allow-Credentials: true and echo the exact origin.
docs/templates-dashboard/meta.json (1)

4-15: Validate slugs and group markers with generator

Ensure the generator supports section dividers like "---General---" and that each slug matches the corresponding MDX filename (users, teams, permissions, settings, auth-providers, analytics).

If needed, I can script-check for missing/extra pages against content/dashboard.

docs/lib/source.ts (1)

1-1: Import looks good

Extending to include dashboard is consistent with the loaders below.

docs/src/app/docs-embed/[[...slug]]/page.tsx (1)

15-23: MDX render path looks correct

Using page.data.body with getEmbeddedMDXComponents() aligns with the embed strategy.

docs/source.config.ts (1)

30-39: Dashboard collection wiring LGTM

defineDocs({ dir: './content/dashboard', ... }) mirrors the API collection. No issues spotted.

docs/src/app/api-embed/[[...slug]]/page.tsx (1)

15-23: MDX embed rendering looks good

Consistent with the embedded MDX components strategy.

docs/src/app/dashboard-embed/layout.tsx (2)

1-8: EmbeddedLinkInterceptor includes 'use client' directive; no changes required


10-10: scrollbar-hide utility confirmed in global.css; no changes needed.

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

5-5: Imports look correct

ComponentProps typing and EmbeddedLink import are appropriate.

Also applies to: 17-17


87-94: Embedded MDX components override is solid

Overriding a to EmbeddedLink with isEmbedded enforces embedded URL rewriting as intended.

docs/src/app/docs-embed/layout.tsx (1)

1-8: No action needed—EmbeddedLinkInterceptor already declares "use client" at the top.

apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (1)

330-331: Minimize iframe sandbox permissions (verify necessity of allow-same-origin).

allow-same-origin significantly increases the embedded page’s capabilities. If not required, drop it to harden the sandbox.

Proposed tightened sandbox (pending validation with embedded link behavior):

-              sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox"
+              sandbox="allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox"

Please confirm embedded navigation and external links still function as expected.

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

Caution

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

⚠️ Outside diff range comments (2)
docs/src/components/layouts/docs.tsx (2)

96-108: Prefer Map over Record for accordion state (guideline) and avoid object churn

Switch to Map to align with project guideline and reduce spread-copy churn on updates.

Apply this diff:

-export function AccordionProvider({ children }: { children: ReactNode }) {
-  const [accordionState, setAccordionStateInternal] = useState<Record<string, boolean>>({});
+export function AccordionProvider({ children }: { children: ReactNode }) {
+  const [accordionState, setAccordionStateInternal] = useState<Map<string, boolean>>(new Map());
@@
-  const setAccordionState = (key: string, isOpen: boolean) => {
-    setAccordionStateInternal(prev => ({ ...prev, [key]: isOpen }));
-  };
+  const setAccordionState = (key: string, isOpen: boolean) => {
+    setAccordionStateInternal((prev) => {
+      const next = new Map(prev);
+      next.set(key, isOpen);
+      return next;
+    });
+  };

And update the context type accordingly (outside this hunk):

type AccordionContextType = {
  accordionState: Map<string, boolean>;
  setAccordionState: (key: string, isOpen: boolean) => void;
};

268-294: Avoid substring matches that can mis-route platforms (e.g., “react” matching “preact”); also prefer Map over Record

Drop the includes() check and use a Map. This prevents accidental matches and follows the Map guideline.

Apply this diff:

-export function findPlatformContent(tree: PageTree.Root, platform: string): PageTree.Node[] {
-  // Platform folder name mappings
-  const platformMappings: Record<string, string[]> = {
-    'next': ['next.js', 'nextjs'],
-    'react': ['react'],
-    'js': ['javascript'],
-    'python': ['python']
-  };
+export function findPlatformContent(tree: PageTree.Root, platform: string): PageTree.Node[] {
+  // Platform folder name mappings
+  const platformMappings = new Map<string, string[]>([
+    ['next', ['next.js', 'nextjs']],
+    ['react', ['react']],
+    ['js', ['javascript']],
+    ['python', ['python']],
+  ]);
@@
-  const possibleNames = platformKey in platformMappings ? platformMappings[platformKey] : [platformKey];
+  const possibleNames = platformMappings.get(platformKey) ?? [platformKey];
@@
-      if (possibleNames.some(name => {
-        const normalizedName = name.trim().toLowerCase();
-        return itemName === normalizedName || itemName.includes(normalizedName);
-      })) {
+      if (possibleNames.some((name) => itemName === name.trim().toLowerCase())) {
         return item.children;
       }
♻️ Duplicate comments (2)
apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (2)

99-113: Remove hardcoded localhost; parameterize docs origin (avoids mixed-content and non-prod breakage).

Build embed URLs from a configurable origin (e.g., NEXT_PUBLIC_DOCS_ORIGIN) or current origin; stop hardcoding http://localhost:8104.

Apply:

-      const url = `http://localhost:8104/docs-embed/${docMapping.path}`;
+      const url = joinDocUrl(`/docs-embed/${docMapping.path}`);
-      const url = `http://localhost:8104/docs-embed/${platform}/getting-started/setup`;
+      const url = joinDocUrl(`/docs-embed/${platform}/getting-started/setup`);
-      const url = `http://localhost:8104/api-embed/overview`;
+      const url = joinDocUrl(`/api-embed/overview`);

Add near the top (after types):

+const DOCS_ORIGIN = process.env.NEXT_PUBLIC_DOCS_ORIGIN ?? '';
+const joinDocUrl = (p: string) => {
+  const base =
+    DOCS_ORIGIN.trim() ||
+    (typeof window !== 'undefined' ? window.location.origin : '');
+  return `${base.replace(/\/$/, '')}${p.startsWith('/') ? p : `/${p}`}`;
+};

241-255: Fix iframe reload fallback (no-op self-assign + Biome error).

Replace self-assign with cache-busting URL update to actually trigger reload.

-    } catch (error) {
-      // If we can't access iframe history, try to reload the previous page
-      // This is a fallback that at least resets the iframe
-      console.warn('Cannot access iframe history, reloading current page');
-      if (iframeRef) {
-        iframeRef.src = iframeRef.src;
-      }
-    }
+    } catch (error) {
+      console.warn('Cannot access iframe history, forcing reload via cache-buster');
+      if (iframeRef?.src) {
+        try {
+          const u = new URL(iframeRef.src, window.location.origin);
+          u.searchParams.set('_r', Date.now().toString());
+          setDocContent(prev => (prev ? { ...prev, url: u.toString() } : prev));
+        } catch {
+          setDocContent(prev => (prev ? { ...prev } : prev)); // react remount fallback
+        }
+      }
+    }
🧹 Nitpick comments (12)
docs/src/components/layouts/docs.tsx (3)

110-124: Use Map accessors in the hook; expose stable tuple

If you adopt Map in the provider, read via get().

Apply this diff:

-export function useAccordionState(key: string, defaultValue: boolean) {
+export function useAccordionState(key: string, defaultValue: boolean) {
@@
-  const { accordionState, setAccordionState } = context;
-  const isOpen = accordionState[key] ?? defaultValue;
+  const { accordionState, setAccordionState } = context;
+  const isOpen = (accordionState instanceof Map
+    ? accordionState.get(key)
+    : // backward-compat if context not yet migrated
+      (accordionState as Record<string, boolean>)[key]) ?? defaultValue;

297-344: Use stable React keys; avoid index to prevent reorder bugs

Keys using index can cause state leakage on reordering. Prefer semantic keys.

Apply this diff:

-          {item.children.map((child, index) => (
-            <PageTreeItem key={child.type === 'page' ? child.url : index} item={child} currentPlatform={currentPlatform} />
-          ))}
+          {item.children.map((child) => (
+            <PageTreeItem
+              key={`${child.type}:${child.type === 'page' ? child.url : String(child.name ?? '')}`}
+              item={child}
+              currentPlatform={currentPlatform}
+            />
+          ))}
@@
-        {item.children.map((child, index) => (
-          <PageTreeItem key={child.type === 'page' ? child.url : index} item={child} currentPlatform={currentPlatform} />
-        ))}
+        {item.children.map((child) => (
+          <PageTreeItem
+            key={`${child.type}:${child.type === 'page' ? child.url : String(child.name ?? '')}`}
+            item={child}
+            currentPlatform={currentPlatform}
+          />
+        ))}

346-376: LGTM on making renderSidebarContent public; just one key nit

Approach looks good. Mirror the stable-key change here too.

Apply this diff:

-      {tree.children.map((item, index) => (
-        <PageTreeItem key={item.type === 'page' ? item.url : index} item={item} currentPlatform={currentPlatform} />
-      ))}
+      {tree.children.map((item) => (
+        <PageTreeItem
+          key={`${item.type}:${item.type === 'page' ? item.url : String(item.name ?? '')}`}
+          item={item}
+          currentPlatform={currentPlatform}
+        />
+      ))}
docs/src/app/docs-embed/[[...slug]]/page.tsx (1)

18-23: Consider 404 for unknown pages (optional)

Redirecting unknown slugs to overview can mask broken links. Using notFound() yields a proper 404.

Apply this diff:

-  if (!page) {
-    // Try to redirect to a sensible default if page not found
-    redirect('/docs-embed/next/overview');
-  }
+  if (!page) {
+    // Unknown page → 404 (keeps bad links visible)
+    // import { notFound } from 'next/navigation'
+    // notFound();
+    redirect('/docs-embed/next/overview');
+  }
docs/src/components/embedded-docs-with-sidebar.tsx (3)

24-34: Harden postMessage handling with a simple channel guard

Anyone can postMessage into the iframe; add a shared “source” token check (keeps cross-origin support without origin allowlists).

Apply this diff:

-  useEffect(() => {
+  useEffect(() => {
     const handleMessage = (event: MessageEvent) => {
-      if (event.data?.type === 'TOGGLE_SIDEBAR') {
+      if (event.data?.source === 'STACK_EMBED' && event.data?.type === 'TOGGLE_SIDEBAR') {
         setIsSidebarVisible(event.data.visible);
       }
     };

Parent should send: window.postMessage({ source: 'STACK_EMBED', type: 'TOGGLE_SIDEBAR', visible: true }, '*').


56-74: Add dialog semantics for accessibility on the Drawer

Mark the drawer as a modal dialog for AT users.

Apply this diff:

-                <div className="fixed left-0 top-0 bottom-0 w-[268px] z-50 bg-fd-background/95 backdrop-blur-md border-r border-fd-border shadow-lg">
+                <div
+                  className="fixed left-0 top-0 bottom-0 w-[268px] z-50 bg-fd-background/95 backdrop-blur-md border-r border-fd-border shadow-lg"
+                  role="dialog"
+                  aria-modal="true"
+                  aria-label="Documentation navigation"
+                >

11-15: Remove unused currentSlug prop (keeps API tight)

The prop isn’t used; drop it here and at the call site.

Apply this diff:

 type EmbeddedDocsWithSidebarProps = {
   pageTree: PageTree.Root,
-  currentSlug: string[],
   children: React.ReactNode,
 }
 
-export function EmbeddedDocsWithSidebar({ pageTree, currentSlug, children }: EmbeddedDocsWithSidebarProps) {
+export function EmbeddedDocsWithSidebar({ pageTree, children }: EmbeddedDocsWithSidebarProps) {

And in docs/src/app/docs-embed/[[...slug]]/page.tsx remove the prop:

-    <EmbeddedDocsWithSidebar
-      pageTree={source.pageTree}
-      currentSlug={slug}
-    >
+    <EmbeddedDocsWithSidebar pageTree={source.pageTree}>

Also applies to: 17-18

apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (5)

85-101: Prefer Map over Record for key–value collections (repo guideline).

Use Map and safe fallback for unknown pages.

-      const dashboardToDocsMap: Record<string, { path: string, title: string }> = {
-        'overview': { path: `${platform}/overview`, title: 'Stack Auth Overview' },
-        'users': { path: `${platform}/getting-started/users`, title: 'User Management' },
-        'auth-methods': { path: `${platform}/concepts/auth-providers`, title: 'Authentication Providers' },
-        'orgs-and-teams': { path: `${platform}/concepts/orgs-and-teams`, title: 'Teams & Organizations' },
-        'team-permissions': { path: `${platform}/concepts/permissions#team-permissions`, title: 'Team Permissions' },
-        'emails': { path: `${platform}/concepts/emails`, title: 'Emails' },
-        'domains': { path: `${platform}/getting-started/production#domains`, title: 'Domains' },
-        'webhooks': { path: `${platform}/concepts/webhooks`, title: 'Webhooks' },
-        'stack-auth-keys': { path: `${platform}/getting-started/setup#update-api-keys`, title: 'Stack Auth Keys' },
-        'project-settings': { path: `${platform}/getting-started/production#enabling-production-mode`, title: 'Project Configuration' },
-      };
-
-      const docMapping = dashboardToDocsMap[page];
+      const dashboardToDocsMap = new Map<string, { path: string; title: string }>([
+        ['overview', { path: `${platform}/overview`, title: 'Stack Auth Overview' }],
+        ['users', { path: `${platform}/getting-started/users`, title: 'User Management' }],
+        ['auth-methods', { path: `${platform}/concepts/auth-providers`, title: 'Authentication Providers' }],
+        ['orgs-and-teams', { path: `${platform}/concepts/orgs-and-teams`, title: 'Teams & Organizations' }],
+        ['team-permissions', { path: `${platform}/concepts/permissions#team-permissions`, title: 'Team Permissions' }],
+        ['emails', { path: `${platform}/concepts/emails`, title: 'Emails' }],
+        ['domains', { path: `${platform}/getting-started/production#domains`, title: 'Domains' }],
+        ['webhooks', { path: `${platform}/concepts/webhooks`, title: 'Webhooks' }],
+        ['stack-auth-keys', { path: `${platform}/getting-started/setup#update-api-keys`, title: 'Stack Auth Keys' }],
+        ['project-settings', { path: `${platform}/getting-started/production#enabling-production-mode`, title: 'Project Configuration' }],
+      ]);
+
+      const docMapping =
+        dashboardToDocsMap.get(page) ?? dashboardToDocsMap.get('overview')!;

136-147: Reset back-button state on new loads.

Avoid stale “Back” visibility after reloads.

         setLoading(true);
         setError(null);
         setIframeLoaded(false);
+        setCanGoBack(false);
         setCurrentPageDoc(newPageDoc);

149-158: Guard debug logs for production.

Keep console noise out of prod.

-          console.log('Debug mapping:', {
+          if (process.env.NODE_ENV !== 'production') console.log('Debug mapping:', {
             pathname,
             normalizedPath: pathname.replace(/^\/projects\/[^/]+/, ''),
             detectedPage: page,
             platform: selectedPlatform
           });
-          const content = getDocContentForPath(pathname, selectedDocType, selectedPlatform);
-          console.log('Loading docs:', { page, platform: selectedPlatform, url: content.url });
+          const content = getDocContentForPath(pathname, selectedDocType, selectedPlatform);
+          if (process.env.NODE_ENV !== 'production') console.log('Loading docs:', { page, platform: selectedPlatform, url: content.url });

149-149: Avoid recomputing getDashboardPage.

Use the already computed value.

-          const page = getDashboardPage(pathname);
+          const page = newPageDoc;

224-230: Hide sidebar in the embed when switching doc types.

Mirror local state to the iframe.

       setSelectedDocType(docType);
       setShowSwitchPrompt(false);
       setIsSidebarVisible(false); // Hide sidebar when switching doc types
+      if (iframeRef) toggleEmbeddedSidebar(iframeRef, false);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ca42d6c and 2e83268.

📒 Files selected for processing (4)
  • apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (1 hunks)
  • docs/src/app/docs-embed/[[...slug]]/page.tsx (1 hunks)
  • docs/src/components/embedded-docs-with-sidebar.tsx (1 hunks)
  • docs/src/components/layouts/docs.tsx (5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer ES6 Map over Record when representing key–value collections

Files:

  • docs/src/components/embedded-docs-with-sidebar.tsx
  • docs/src/app/docs-embed/[[...slug]]/page.tsx
  • docs/src/components/layouts/docs.tsx
  • apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx
{apps/dashboard,apps/dev-launchpad,packages/stack-ui,packages/react}/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

For blocking alerts and errors in UI, do not use toast notifications; use alerts instead

Files:

  • apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx
{apps/dashboard,apps/dev-launchpad,packages/stack-ui,packages/react}/**/*.{tsx,jsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Keep hover/click animations snappy; avoid pre-transition delays on hover and apply transitions after the action (e.g., fade-out on hover end)

Files:

  • apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx
🧬 Code graph analysis (3)
docs/src/components/embedded-docs-with-sidebar.tsx (2)
docs/src/components/layouts/docs.tsx (2)
  • AccordionProvider (96-108)
  • renderSidebarContent (346-376)
docs/src/components/layouts/sidebar-context.tsx (1)
  • SidebarProvider (51-184)
docs/src/app/docs-embed/[[...slug]]/page.tsx (3)
docs/lib/source.ts (1)
  • source (23-30)
docs/src/components/embedded-docs-with-sidebar.tsx (1)
  • EmbeddedDocsWithSidebar (17-91)
docs/src/mdx-components.tsx (1)
  • getEmbeddedMDXComponents (88-94)
apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (1)
docs/src/components/icons.tsx (2)
  • Menu (137-141)
  • ExternalLink (98-108)
🪛 Biome (2.1.2)
apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx

[error] 252-252: src is assigned to itself.

This is where is assigned.

Self assignments have no effect and can be removed.

(lint/correctness/noSelfAssign)

⏰ 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: lint_and_build (latest)
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: docker
  • GitHub Check: setup-tests
  • GitHub Check: restart-dev-and-test
  • GitHub Check: Security Check
🔇 Additional comments (3)
docs/src/app/docs-embed/[[...slug]]/page.tsx (1)

1-5: Import 'lib/source' resolves correctly via baseUrl
docs/tsconfig.json sets baseUrl to "." so non-relative imports map to project root (docs/lib/source.ts exists and is already used via relative paths); no changes needed.

apps/dashboard/src/components/stack-companion/unified-docs-widget.tsx (2)

398-406: Revisit sandbox allowances; narrow if possible.

If not strictly required, drop allow-same-origin and/or allow-popups-to-escape-sandbox to reduce risk. PostMessage doesn’t need same-origin.

Do you know if the embedded docs require same-origin APIs (e.g., localStorage)? If not, I can propose a tightened sandbox string.


286-313: Good: inline alert for errors (no toasts).

Complies with the repo’s UI guideline for blocking errors.

cursor[bot]

This comment was marked as outdated.

@stack-auth stack-auth deleted a comment from cursor bot Oct 29, 2025
@stack-auth stack-auth deleted a comment from cursor bot Oct 29, 2025
@stack-auth stack-auth deleted a comment from cursor bot Oct 29, 2025
@stack-auth stack-auth deleted a comment from cursor bot Oct 29, 2025
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 (2)
docs/src/components/embedded-link-interceptor.tsx (2)

92-99: Consider making URL existence check optional via feature flag.

The checkUrlExists HEAD request is now non-blocking (navigation proceeds regardless), but still adds latency and can fail on hosts that return 405/308 for HEAD. Since multiple previous reviewers flagged HEAD requests as unreliable and the check is purely advisory, consider gating it behind an environment variable (e.g., NEXT_PUBLIC_ENABLE_LINK_VALIDATION) or removing it entirely.

Apply this diff to gate the check behind a feature flag:

+const ENABLE_LINK_VALIDATION = process.env.NEXT_PUBLIC_ENABLE_LINK_VALIDATION === 'true';
+
 export function EmbeddedLinkInterceptor() {
   const router = useRouter();
 
   // Function to check if a URL exists
   const checkUrlExists = useCallback(async (url: string): Promise<boolean> => {
+    if (!ENABLE_LINK_VALIDATION) return true;
     try {
       const response = await fetch(url, { method: 'HEAD' });
       return response.ok;

131-144: Optionally prevent duplicate in-flight navigations.

Rapid repeated clicks on the same link will queue multiple navigations. While router.push should handle this gracefully, you could add deduplication by tracking in-flight URLs to improve UX consistency.

Apply this diff to add deduplication:

   useEffect(() => {
+    const inFlightUrls = new Set<string>();
+
     const handleClick = (event: MouseEvent) => {
       if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
         return;
       }
 
       const target = event.target as HTMLElement;
 
       // Find the closest anchor tag
       const anchor = target.closest('a');
       if (!anchor) return;
 
       const href = anchor.getAttribute('href');
       if (!href) return;
 
       if (anchor.target === '_blank' || anchor.hasAttribute('download')) {
         return;
       }
 
       if (href.startsWith('javascript:') || href.startsWith('data:') || href.startsWith('blob:')) {
         return;
       }
 
       // Intercept internal links that need to be rewritten OR relative links
       if (
         href.startsWith('/docs/') ||
         href.startsWith('/api/') ||
         href.startsWith('/dashboard/') ||
         (!/^[a-zA-Z][a-zA-Z+\-.]*:/.test(href) && !href.startsWith('#'))
       ) {
         event.preventDefault();
 
         const currentPath = window.location.pathname;
         const embeddedHref = getEmbeddedUrl(href, currentPath);
+        
+        if (inFlightUrls.has(embeddedHref)) {
+          return; // Skip if already navigating to this URL
+        }
+        
         const navigate = () => router.push(embeddedHref);
 
         // Check if the URL exists before navigating (async operation)
         runAsynchronously(async () => {
+          inFlightUrls.add(embeddedHref);
+          try {
             const urlExists = await checkUrlExists(embeddedHref);
             if (!urlExists) {
               console.warn(`Embedded link not found, navigating anyway: ${embeddedHref}`);
             }
             navigate();
+          } finally {
+            inFlightUrls.delete(embeddedHref);
+          }
         });
       }
     };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2289f2e and a7db958.

📒 Files selected for processing (5)
  • apps/dashboard/.env (1 hunks)
  • apps/dashboard/.env.development (1 hunks)
  • docs/src/components/embedded-docs-message-bridge.tsx (1 hunks)
  • docs/src/components/embedded-link-interceptor.tsx (1 hunks)
  • docs/src/components/mdx/embedded-link.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/src/components/mdx/embedded-link.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use ES6 Maps instead of Records wherever possible in TypeScript code

Files:

  • docs/src/components/embedded-docs-message-bridge.tsx
  • docs/src/components/embedded-link-interceptor.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-20T22:25:40.427Z
Learnt from: CR
PR: stack-auth/stack-auth#0
File: AGENTS.md:0-0
Timestamp: 2025-10-20T22:25:40.427Z
Learning: Applies to apps/{dashboard,dev-launchpad}/**/*.{css,tsx,jsx} : Animations: keep hover/click transitions snappy; do not delay actions with pre-hover transitions; apply transitions after the action (e.g., fade-out on hover end)

Applied to files:

  • docs/src/components/embedded-link-interceptor.tsx
🧬 Code graph analysis (1)
docs/src/components/embedded-link-interceptor.tsx (1)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
🪛 dotenv-linter (4.0.0)
apps/dashboard/.env

[warning] 8-8: [UnorderedKey] The NEXT_PUBLIC_STACK_DOCS_BASE_URL key should go before the NEXT_PUBLIC_STACK_EXTRA_REQUEST_HEADERS key

(UnorderedKey)


[warning] 8-8: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

apps/dashboard/.env.development

[warning] 2-2: [SubstitutionKey] The NEXT_PUBLIC_STACK_DOCS_BASE_URL key is not assigned properly

(SubstitutionKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: setup-tests
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: restart-dev-and-test
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: Security Check
🔇 Additional comments (9)
apps/dashboard/.env.development (1)

2-2: New environment variable follows established patterns correctly.

The NEXT_PUBLIC_STACK_DOCS_BASE_URL is positioned logically with NEXT_PUBLIC_STACK_API_URL and uses the same port-prefix substitution pattern as other infrastructure variables (NEXT_PUBLIC_STACK_SVIX_SERVER_URL on line 8). The port assignment (8104) fits the existing scheme.

docs/src/components/embedded-docs-message-bridge.tsx (7)

1-4: LGTM! Proper client component setup.

The 'use client' directive and imports are appropriate for a component that uses hooks and browser APIs like window and postMessage.


6-14: LGTM! Well-defined message types.

The type definitions are clear and the ParentMessage union type allows for future extensibility with the { type: string } fallback.


16-22: LGTM! Appropriate origin allowlist for postMessage security.

The environment-based origin allowlist properly restricts cross-origin communication to trusted parent windows.


24-37: LGTM! Robust parent origin resolution.

The function safely resolves the parent origin from the referrer with appropriate fallback and error handling.


39-71: LGTM! Well-structured state management and notification logic.

The component setup uses appropriate hooks and refs. The notifyParent callback has proper guards, constructs correct messages, and uses postMessage with a target origin for security.


73-98: LGTM! Correct navigation history tracking.

The effect properly maintains a browser-like history stack, handling initial state, same-path navigation, and forward navigation after going back. The history splice at line 92 correctly clears forward entries when navigating to a new path.


100-131: LGTM! Correct back navigation handling with proper security.

The message listener properly validates origin and source, and the NAVIGATE_BACK handling is now correct:

  • Updates the index before calling router.push (line 121-122)
  • Removes the immediate notifyParent call after router.push (as noted in past reviews)
  • Lets the pathname effect (lines 74-98) handle notification, preventing duplicate messages

The guards on lines 116-119 correctly handle edge cases where history entries might be missing.

docs/src/components/embedded-link-interceptor.tsx (1)

101-155: Previous concerns addressed effectively.

The click handler now properly:

  • Respects user intent by checking for modified clicks and special link attributes (lines 103, 116-118, 120-122)
  • Uses router.push for client-side navigation instead of full page reload
  • Navigates even when URL existence check fails, preventing broken links
  • Filters unsafe schemes before interception

These changes address the major concerns raised in previous reviews.

@madster456 madster456 merged commit 3538638 into dev Oct 31, 2025
23 checks passed
@madster456 madster456 deleted the stack-companion-docs branch October 31, 2025 01:01
@coderabbitai coderabbitai bot mentioned this pull request Nov 26, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jan 14, 2026
@vercel
Copy link

vercel bot commented Jan 16, 2026

Deployment failed with the following error:

Creating the Deployment Timed Out.

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