Skip to content

POC: Cookbook style listing in the docs#397

Open
saif-at-scalekit wants to merge 5 commits intomainfrom
poc-blog-as-cookbooks
Open

POC: Cookbook style listing in the docs#397
saif-at-scalekit wants to merge 5 commits intomainfrom
poc-blog-as-cookbooks

Conversation

@saif-at-scalekit
Copy link
Collaborator

@saif-at-scalekit saif-at-scalekit commented Jan 21, 2026

State: Proof of Concept

Adds a blog-style content surface to docs.scalekit.com dedicated to P.A.T.-driven technical stories (Problem → Angle → Teach). This space is for problem‑first, opinionated, and educational articles that sit alongside reference docs, helping developers discover real-world use cases, understand Scalekit’s unique point of view, and learn concrete implementation patterns without wading through product‑only documentation.

Example we current have

  • Build a your own organization switcher

Summary by CodeRabbit

  • New Features

    • Blog analytics now include reading-time and total-word metrics for cookbooks content.
    • New Cookbooks section added with its own navigation behavior.
  • Documentation

    • Added a comprehensive guide on building custom organization switchers with examples for Node.js, Python, Go, and Java.

…on switcher

- Integrated the starlight-blog package into the project, enabling blog functionality with metrics for reading time and total words.
- Updated the Astro configuration to include the starlight-blog plugin.
- Added a new blog post titled "Building a Custom Organization Switcher," detailing how to create a custom organization switcher UI for enhanced user experiences in multi-tenant applications.
- Updated sidebar configuration to exclude the blog from navigation and ensure a cleaner user experience.
- Included a new author image for the blog post to enhance visual appeal.
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

Adds a cookbooks blog: registers the starlight-blog plugin and dependency, excludes /cookbooks from topic sidebar, refactors content schema to extend from blogSchema, and adds a new cookbook doc on building a custom organization switcher.

Changes

Cohort / File(s) Summary
Blog plugin & deps
astro.config.mjs, package.json
Imported and registered starlightBlog({ prefix: 'cookbooks', metrics: { readingTime: true, words: 'total' }}) and added dependency "starlight-blog": "^0.25.2".
Navigation
src/configs/sidebar.config.ts
Added '/cookbooks' to the exported exclude array to omit cookbooks from topic-based sidebar navigation.
Content schema
src/content.config.ts
Reworked docs schema composition to start from blogSchema(context) and then merge topicSchema, videosSchema, and custom fields via an extend(context) function.
Documentation content
src/content/docs/cookbooks/building-custom-org-switcher.mdx
New cookbook guide added with multi-language examples (Node.js, Python, Go, Java) demonstrating custom organization switcher patterns and security/selection guidance.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • ravibits
  • amitash1912

Poem

I'm a rabbit in the docs, nibbling new lines, 🐇
Cookbooks planted where the blog now shines,
Schemas hop together, plugins hum a tune,
Switchers crafted beneath a silvery moon,
Hooray for tiny changes that make the site bloom! 🌱

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: introducing a cookbook-style content listing as a proof-of-concept in the documentation site.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ 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 poc-blog-as-cookbooks

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55fd88e and ad5b7c7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • astro.config.mjs
  • package.json
  • src/configs/sidebar.config.ts
  • src/content.config.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • package.json
  • src/configs/sidebar.config.ts
  • astro.config.mjs
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,py,go,java,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

SDK variable names must follow language-specific conventions: Node.js uses scalekit, Python uses scalekit_client, Go uses scalekitClient, Java uses scalekitClient

Files:

  • src/content.config.ts
**/*.{js,ts,tsx,jsx,py,java,cs,go,cpp,c,rb,php,swift,kt,scala,rs,m,mm,groovy,gradle,xml,json}

📄 CodeRabbit inference engine (.cursor/rules/comment-standards.mdc)

Comments should not duplicate the code - avoid comments that simply restate what the code does; comments should add value beyond what's obvious from reading the code

Files:

  • src/content.config.ts
**/*.{js,ts,tsx,jsx,py,java,cs,go,cpp,c,rb,php,swift,kt,scala,rs,m,mm,groovy}

📄 CodeRabbit inference engine (.cursor/rules/comment-standards.mdc)

**/*.{js,ts,tsx,jsx,py,java,cs,go,cpp,c,rb,php,swift,kt,scala,rs,m,mm,groovy}: Good comments do not excuse unclear code - refactor the code to be self-explanatory instead of using comments to explain poorly written code; use better variable names, function names, and code structure
Comments should dispel confusion, not cause it - ensure comments clarify rather than obscure the code's purpose; avoid cryptic or joke comments
Explain unidiomatic code in comments - comment on code that might seem unnecessary or redundant and document why you chose a specific pattern over more common alternatives, especially when it deviates from team conventions
Provide links to the original source of copied code - always attribute code copied from external sources with URLs to Stack Overflow answers, GitHub repositories, or documentation
Include links to external references where helpful - reference standards, RFCs, and official documentation; link to relevant specifications when implementing protocols
Add comments when fixing bugs - document bug fixes with context about the issue, reference issue trackers and bug reports, and explain workarounds and their limitations
Use comments to mark incomplete implementations - use standard formats for TODO, FIXME, and NOTE comments with context about what needs to be done and reference issue trackers when possible
Always document public APIs with function/class comments - explain the purpose, parameters, return values, and exceptions; include usage examples for complex functions
Include file headers with copyright information, license, and authorship - provide a brief description of the file's purpose and document dependencies and requirements

Files:

  • src/content.config.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/comment-standards.mdc)

Use JSDoc standards for all function, class, and complex logic comments in JavaScript/TypeScript - include parameter descriptions (@param), return values (@returns), types (@type), and descriptions; document exceptions and edge cases

Files:

  • src/content.config.ts
🧠 Learnings (3)
📚 Learning: 2026-01-30T18:20:07.851Z
Learnt from: AkshayParihar33
Repo: scalekit-inc/developer-docs PR: 415
File: src/content/docs/authenticate/fsa/multiapp/native-app.mdx:1-6
Timestamp: 2026-01-30T18:20:07.851Z
Learning: In the scalekit-inc/developer-docs repository, MDX files under `src/content/docs/authenticate/fsa/multiapp/` do not use `order` or `tags` fields in their frontmatter. Ordering and grouping are managed centrally in `src/configs/sidebar.config.ts`.

Applied to files:

  • src/content.config.ts
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.{md,mdx} : Keep documentation synchronized with product changes

Applied to files:

  • src/content.config.ts
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.{md,mdx} : Update code examples when APIs or behaviors change

Applied to files:

  • src/content.config.ts
⏰ 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). (3)
  • GitHub Check: Redirect rules - scalekit-starlight
  • GitHub Check: Header rules - scalekit-starlight
  • GitHub Check: Pages changed - scalekit-starlight
🔇 Additional comments (2)
src/content.config.ts (2)

7-7: LGTM!

The new import for blogSchema from starlight-blog/schema is appropriate for enabling blog-style content features in the cookbooks section.


14-43: Schema composition is working correctly with no field conflicts detected.

The refactored schema composition using blogSchema(context) as the base with chained .merge() calls follows valid Zod patterns. The context is correctly passed to blogSchema (which needs it for image handling), while topicSchema and videosSchema are static schemas that don't require context. The custom fields (overviewTitle, seeAlso, browseCentral) are actively used throughout the codebase (src/utils/examples.ts, src/routeData.ts) without validation errors or conflicts, confirming the schema structure is sound.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@astro.config.mjs`:
- Around line 94-99: Remove the invalid metrics option from the starlightBlog()
call: open the configuration where starlightBlog(...) is invoked and delete the
entire metrics: { readingTime: true, words: 'total' } object so the plugin
options only use supported keys (prefix, title, postCount, recentPostCount,
authors, navigation, frontmatter); ensure no other code relies on that removed
option since reading time and word count are provided automatically via post
metadata/frontmatter.

In `@src/configs/sidebar.config.ts`:
- Around line 511-515: The exclude array (export const exclude) currently lists
'/blog' which may not match nested blog pages; update the pattern in the exclude
array to use a recursive glob (e.g., replace '/blog' with '/blog/**') so the
entire blog subtree is excluded by the glob matcher, and keep the existing
'/apis/**/*' style consistent with other entries.

In `@src/content/docs/blog/building-custom-org-switcher.mdx`:
- Around line 107-116: The "Add domain context" block currently contains only a
JavaScript example; replace it with a Tabs block containing Node.js, Python, Go,
and Java examples that each call the Domains API to list domains for an
organization and show how to display a domain (e.g., "@acme.com") next to the
org name. Specifically, update the block that references scalekit.domains.list
and organizationId: 'org_123' so it includes a Node.js/JavaScript snippet (same
call pattern), a Python snippet calling scalekit.domains.list or equivalent
client method with organization_id='org_123', a Go snippet using the
Domains.List method with OrganizationID: "org_123", and a Java snippet using the
domains().list(...) call with organizationId "org_123"; keep the examples
minimal and consistent (fetch domains, iterate or access first domain, and show
"@acme.com" display note).
- Around line 47-103: Add the required syncKey attribute to the Tabs components
so language selection remains consistent: locate the Tabs elements (the
top-level Tabs component wrapping the TabItem blocks in this file) and add
syncKey="tech-stack" to each Tabs instance (the TabItem components remain
unchanged); ensure both Tabs blocks on the page use the identical syncKey value
"tech-stack" so multi-language examples stay synchronized across pages.
- Around line 1-16: Update the MDX frontmatter: change the Title field to
sentence case (update 'title'), confirm and update the publish `date` to the
intended current date if needed, and add the required navigation metadata by
adding `sidebar_label` (a short label) and `sidebar_position` or `order` to
place it in the docs navigation; also add `tableOfContents: true` to enable TOC
for multi-section pages and ensure the existing `authors`, `tags`, `excerpt`,
`featured`, and `cover` fields remain intact (look for the frontmatter block
beginning with `---` and the keys `title`, `date`, `authors` to locate where to
add these fields).
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19063c3 and 3533e7a.

⛔ Files ignored due to path filters (3)
  • assets/blog/covers/custom-org-switcher.jpg is excluded by !**/*.jpg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • public/images/blog/authors/hashirr-lukmahn.jpg is excluded by !**/*.jpg
📒 Files selected for processing (5)
  • astro.config.mjs
  • package.json
  • src/configs/sidebar.config.ts
  • src/content.config.ts
  • src/content/docs/blog/building-custom-org-switcher.mdx
🧰 Additional context used
📓 Path-based instructions (8)
astro.config.mjs

📄 CodeRabbit inference engine (.cursorrules)

astro.config.mjs: Expressive Code is configured in astro.config.mjs with themes 'tokyo-night' (dark) and 'light-plus' (light), JetBrains Mono font, and border radius 0.375rem
Expressive Code collapsible sections plugin must be enabled in astro.config.mjs

Files:

  • astro.config.mjs
**/*.{js,ts,tsx,jsx,py,java,cs,go,cpp,c,rb,php,swift,kt,scala,rs,m,mm,groovy,gradle,xml,json}

📄 CodeRabbit inference engine (.cursor/rules/comment-standards.mdc)

Comments should not duplicate the code - avoid comments that simply restate what the code does; comments should add value beyond what's obvious from reading the code

Files:

  • package.json
  • src/configs/sidebar.config.ts
  • src/content.config.ts
**/*.{js,ts,py,go,java,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

SDK variable names must follow language-specific conventions: Node.js uses scalekit, Python uses scalekit_client, Go uses scalekitClient, Java uses scalekitClient

Files:

  • src/configs/sidebar.config.ts
  • src/content.config.ts
**/*.{js,ts,tsx,jsx,py,java,cs,go,cpp,c,rb,php,swift,kt,scala,rs,m,mm,groovy}

📄 CodeRabbit inference engine (.cursor/rules/comment-standards.mdc)

**/*.{js,ts,tsx,jsx,py,java,cs,go,cpp,c,rb,php,swift,kt,scala,rs,m,mm,groovy}: Good comments do not excuse unclear code - refactor the code to be self-explanatory instead of using comments to explain poorly written code; use better variable names, function names, and code structure
Comments should dispel confusion, not cause it - ensure comments clarify rather than obscure the code's purpose; avoid cryptic or joke comments
Explain unidiomatic code in comments - comment on code that might seem unnecessary or redundant and document why you chose a specific pattern over more common alternatives, especially when it deviates from team conventions
Provide links to the original source of copied code - always attribute code copied from external sources with URLs to Stack Overflow answers, GitHub repositories, or documentation
Include links to external references where helpful - reference standards, RFCs, and official documentation; link to relevant specifications when implementing protocols
Add comments when fixing bugs - document bug fixes with context about the issue, reference issue trackers and bug reports, and explain workarounds and their limitations
Use comments to mark incomplete implementations - use standard formats for TODO, FIXME, and NOTE comments with context about what needs to be done and reference issue trackers when possible
Always document public APIs with function/class comments - explain the purpose, parameters, return values, and exceptions; include usage examples for complex functions
Include file headers with copyright information, license, and authorship - provide a brief description of the file's purpose and document dependencies and requirements

Files:

  • src/configs/sidebar.config.ts
  • src/content.config.ts
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/comment-standards.mdc)

Use JSDoc standards for all function, class, and complex logic comments in JavaScript/TypeScript - include parameter descriptions (@param), return values (@returns), types (@type), and descriptions; document exceptions and edge cases

Files:

  • src/configs/sidebar.config.ts
  • src/content.config.ts
**/*.mdx

📄 CodeRabbit inference engine (.cursorrules)

**/*.mdx: Use clear, descriptive titles that explain the purpose of the document
Include comprehensive descriptions in frontmatter metadata
Organize content with logical heading hierarchy (H2, H3, H4)
Use tableOfContents property in frontmatter when content has multiple sections
Set appropriate sidebar labels for navigation in frontmatter
Use direct instruction writing style with phrases like 'This guide shows you how to...' and 'Create an authorization URL to...'
Use second person perspective ('your application', 'you receive', 'you must') in documentation
Keep sentences concise, aiming for under 25 words per sentence
Explain the 'why' in documentation with phrases like 'This prevents CSRF attacks by...' or 'Use this to validate that...'
Use action verbs in section headings: 'Store session tokens securely', 'Validate the state parameter', 'Exchange authorization code for tokens'
Use present tense for descriptions: 'Scalekit handles the complex authentication flow', 'The SDK provides methods to refresh tokens'
Use future tense for results: 'This will redirect users to...', 'You'll receive a JWT containing...', 'Scalekit returns an authorization code'
Use transition phrases between sections: 'After the user authenticates...', 'Once the state is validated...', 'Let's take a look at how to...'
Write 1-3 opening paragraphs that explain what users will accomplish, provide context about when/why, preview key concepts, and use direct instructional language
Begin introduction sections with a clear statement of what the guide covers and explain the problem being solved
Use collapsible sections in introduction for sequence diagrams, video demonstrations, data models, and JSON examples with appropriate icons
Use numbered format within Steps component: 1. ## Title with all step content indented with exactly 3 spaces
Use action-oriented headings in step-by-step guides within Steps components
Include code examples in all 4 languages (Node.js, Python, Go, Java) within Steps co...

Files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{md,mdx}: All code examples must include implementations in all 4 languages: Node.js, Python, Go, and Java
Include security comments in code examples explaining security threats and implications
Code examples must demonstrate both success and error paths
Frontmatter must include: title (≤60 characters), description (≤160 characters), sidebar label, order number, and tags array
Use second person ('you', 'your application') for writing voice in documentation
Use present tense for descriptions and imperative mood for instructions in documentation

**/*.{md,mdx}: Use sentence case for all titles and headings in MD/MDX documentation
Keep page titles short and descriptive (3–7 words when possible) in MD/MDX documentation
Use outcome-focused headings that describe results, not categories (e.g., 'Run a script' not 'Scripts')
Avoid gerunds in headings when an imperative works - prefer 'Configure proxies' over 'Configuring proxies'
Keep sidebar labels concise (1–3 words), use sentence case, and focus on outcomes or objects
Use sentence case in sidebar labels without punctuation
Set frontmatter title in sentence case with a clear outcome; description in one sentence (≤160 chars); sidebar.label as shorter form of title; enable tableOfContents on longer pages
Start documentation pages with a one-paragraph overview explaining what the page covers and when to use it
Present the primary use case (80% path) first in documentation, with edge cases later
Use numbered steps for task-focused sections in documentation, with each step beginning with a verb
Break up long documentation sections with subheadings every 3–6 paragraphs
Use asides for important notes, tips, cautions, and references in documentation
Provide runnable, minimal code examples that work as-is in documentation
Prefer CLI-first examples and show file layout when helpful in documentation
Label code blocks with titles for context (e.g., 'Terminal', 'main.ts') in documentation
Keep code block annotations brief and...

Files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
**/*.{yml,yaml,md,mdx}

📄 CodeRabbit inference engine (.cursor/rules/browsecentral-labels.mdc)

**/*.{yml,yaml,md,mdx}: BrowseCentral labels should be maximum 3-5 words - keep concise but add context when needed
BrowseCentral labels should be action-oriented - start with verbs when possible
BrowseCentral labels should be specific and clear - add context when simple labels are ambiguous
BrowseCentral labels should be outcome-focused - describe what users accomplish and the context
BrowseCentral labels should use 'Action + Object' pattern (e.g., 'Invite users', 'Restrict sign-up', 'Set up SCIM')
BrowseCentral labels should use feature names (e.g., 'Enterprise SSO', 'Passwordless quickstart')
BrowseCentral labels should describe task completion (e.g., 'Run migrations', 'Migrate auth', 'Merge identities')
BrowseCentral labels should include specific context when needed (e.g., 'Configure Scalekit MCP server', 'Validate incoming API requests')
BrowseCentral labels should use integration context when applicable (e.g., 'Build MCP auth with your existing auth system')
BrowseCentral labels should avoid instructional prefixes: 'How to', 'Guide to', 'Implement', 'Configure', 'Learn', 'Understand'
BrowseCentral labels should avoid verbose phrases: 'Step-by-step guide', 'Complete tutorial', 'Detailed documentation'
BrowseCentral labels should avoid weak verbs: 'Enable', 'Allow', 'Provide', 'Support'

Files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursorrules:0-0
Timestamp: 2026-01-13T12:46:55.260Z
Learning: Applies to astro.config.mjs : Expressive Code collapsible sections plugin must be enabled in `astro.config.mjs`
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursorrules:0-0
Timestamp: 2026-01-13T12:46:55.260Z
Learning: Applies to astro.config.mjs : Expressive Code is configured in `astro.config.mjs` with themes 'tokyo-night' (dark) and 'light-plus' (light), JetBrains Mono font, and border radius 0.375rem
📚 Learning: 2026-01-13T12:46:55.260Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursorrules:0-0
Timestamp: 2026-01-13T12:46:55.260Z
Learning: Applies to astro.config.mjs : Expressive Code collapsible sections plugin must be enabled in `astro.config.mjs`

Applied to files:

  • astro.config.mjs
📚 Learning: 2026-01-13T12:46:55.260Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursorrules:0-0
Timestamp: 2026-01-13T12:46:55.260Z
Learning: Applies to astro.config.mjs : Expressive Code is configured in `astro.config.mjs` with themes 'tokyo-night' (dark) and 'light-plus' (light), JetBrains Mono font, and border radius 0.375rem

Applied to files:

  • astro.config.mjs
📚 Learning: 2026-01-13T12:48:19.565Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/expressive-code.mdc:0-0
Timestamp: 2026-01-13T12:48:19.565Z
Learning: Applies to **/*.mdx : Import `{ Code }` from `astrojs/starlight/components` once per `.mdx` file, placing the import below frontmatter

Applied to files:

  • astro.config.mjs
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.{md,mdx} : Set concise sidebar labels that match user vocabulary in navigation metadata

Applied to files:

  • src/configs/sidebar.config.ts
📚 Learning: 2026-01-13T12:46:55.260Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursorrules:0-0
Timestamp: 2026-01-13T12:46:55.260Z
Learning: Applies to **/*.mdx : Set appropriate sidebar labels for navigation in frontmatter

Applied to files:

  • src/configs/sidebar.config.ts
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.{md,mdx} : Keep documentation synchronized with product changes

Applied to files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
📚 Learning: 2026-01-13T12:46:55.260Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursorrules:0-0
Timestamp: 2026-01-13T12:46:55.260Z
Learning: Applies to **/*.mdx : Use `<Tabs syncKey="tech-stack">` to synchronize multi-language code selection across documentation pages

Applied to files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.mdx : Use Tabs/TabItem components for multi-language or multi-framework examples in MDX documentation

Applied to files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.{md,mdx} : Structure documentation content with clear headings for better search understanding

Applied to files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
📚 Learning: 2026-01-13T12:48:11.566Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/documentation-guide.mdc:0-0
Timestamp: 2026-01-13T12:48:11.566Z
Learning: Applies to **/*.{md,mdx} : Update code examples when APIs or behaviors change

Applied to files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
📚 Learning: 2026-01-13T12:47:52.148Z
Learnt from: CR
Repo: scalekit-inc/developer-docs PR: 0
File: .cursor/rules/deno-docs-style.mdc:0-0
Timestamp: 2026-01-13T12:47:52.148Z
Learning: Applies to **/*.{md,mdx} : Start documentation pages with a one-paragraph overview explaining what the page covers and when to use it

Applied to files:

  • src/content/docs/blog/building-custom-org-switcher.mdx
🔇 Additional comments (2)
package.json (1)

51-51: No issues found. The dependency starlight-blog at version ^0.25.2 is the current release on npm and is designed as a Starlight plugin for Astro. Compatibility is appropriate for standard Astro/Starlight setups.

src/content.config.ts (1)

12-42: No validation concern: blogSchema fields are optional by design.

blogSchema(context) returns a .partial() schema from starlight-blog, making all blog-specific fields (date, authors, excerpt, cover, tags, featured) optional by default. Regular docs will validate correctly without providing blog metadata.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines 94 to 99
starlightBlog({
metrics: {
readingTime: true,
words: 'total',
},
}),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

starlight-blog plugin metrics options readingTime words configuration

💡 Result:

Do you want (A) how to enable/configure reading-time & word-count in the starlight-blog plugin, (B) the frontmatter fields the plugin exposes (e.g., readingTime / words), or (C) an example astro.config.mjs snippet?


🌐 Web query:

starlight-blog plugin documentation github npm metrics configuration

💡 Result:

Found the main resources and basic metrics/config notes for the starlight-blog plugin:

  • GitHub repo (source, README, issues): HiDeoo/starlight-blog. [1]
  • Official plugin docs / getting‑started (installation, usage, configuration notes — e.g. add starlightBlog to your Starlight plugins and configure in astro.config.mjs): Starlight Blog docs. [2]
  • Starlight ecosystem pages that list/describe the plugin and show example configuration behavior. [3][4]
  • npm / package metrics and versions: package published on npm (seen on CDN/registry listings); recent published versions reported (examples: 0.24.x → 0.25.x across registries); weekly download counts shown on registry/analysis pages. Use the npm/jsDelivr/registry pages for exact current version and download numbers. [5][6]

If you want, I can:

  • paste the exact installation + astro.config.mjs example from the docs,
  • fetch the current npm version and weekly downloads,
  • or open the GitHub README/issue list and extract configuration options (frontmatter fields, sidebar settings, authors/tags, RSS). Which would you like?

🌐 Web query:

starlight-blog astro.config.mjs configuration example metrics readingTime words

💡 Result:

Below is a concise astro.config.mjs example that enables Starlight with the starlight-blog plugin. The plugin automatically adds blog features (including UI labels like "Reading time" and word/reading-time metadata exposed by the blog components). Replace values as needed.

astro.config.mjs example

import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import starlightBlog from 'starlight-blog';

export default defineConfig({
  site: 'https://example.com', // required for RSS / feeds
  integrations: [
    starlight({
      title: 'My Docs + Blog',
      plugins: [
        starlightBlog({
          // optional blog options (authors, prefix, etc.)
          // authors: { alice: { name: 'Alice', picture:'/a.png' } },
          // prefix: '/blog'
        }),
      ],
      // other starlight options (sidebar, social, i18n, ...)
    }),
  ],
});

Notes

  • The plugin registers blog pages under your content folder (e.g. src/content/docs/blog/) and exposes post metadata such as word count and reading time through the blog components and localized UI strings (e.g. starlight-blog.readingTime). See the Starlight Blog docs and Starlight configuration reference for details and available plugin options. [1][2]

Sources

  • Starlight Blog docs (plugin usage & config). [1]
  • Starlight configuration / project structure reference. [2]

References
[1] Starlight Blog docs — starlight-blog.
[2] Starlight — Configuration & Project Structure.


🌐 Web query:

starlight-blog HiDeoo github plugin options configuration schema metrics

💡 Result:

Here are the authoritative places for starlight-blog plugin options, configuration schema (blogSchema) and related details (including RSS/metrics-related behavior):

  • GitHub repository (source, code, package): HiDeoo/starlight-blog. [1]
  • Official plugin docs — Getting Started (shows installation, how to configure in astro.config.mjs and how to use blogSchema in src/content.config.ts). [2]
  • RSS guide (explains RSS generation and the prefix/site options that affect feeds). [3]
  • HiDeoo Starlight plugin notes — guides on adding user configuration and extending Starlight frontmatter schema (Zod-based schemas) which the plugin uses (how to expose/extend blogSchema and validate options). [4][5]

References

  1. HiDeoo/starlight-blog (GitHub). [1]
  2. Starlight Blog — Getting Started (starlight-blog docs). [2]
  3. Starlight Blog — RSS guide. [3]
  4. HiDeoo — Add support for user configuration in a Starlight plugin. [4]
  5. HiDeoo — Extend Starlight’s frontmatter schema in a Starlight plugin. [5]

If you want, I can fetch the exact option names and the blogSchema shape from the repo/docs and show the configuration example and available metric-related options (RSS, pagination, sidebar settings, etc.). Which would you prefer?


🌐 Web query:

"starlight-blog" plugin configuration options "metrics" OR "readingTime" OR "words"

💡 Result:

Short answer: starlight-blog exposes/uses a readingTime value (with words) for posts; there’s an i18n key "starlight-blog.readingTime" and the plugin/page data includes readingTime/words (as typical reading-time plugins do). See the starlight-blog docs and repo. [1][2]

Sources:

  • starlight-blog docs / repo (plugin overview). [1]
  • Example i18n / component references showing "starlight-blog.readingTime" and words label. [2]

🌐 Web query:

starlight-blog plugin configuration options authors prefix site complete list

💡 Result:

Main starlight-blog plugin config options (common/explicitly documented):

  • title — blog title shown in UI. [1][2]
  • postCount — number of posts per blog page (pagination). [3]
  • recentPostCount — number of recent posts shown in sidebar. [3]
  • authors — object of author profiles (keyed IDs with name, title, picture, url, etc.). [3][4]
  • prefix — path prefix used for RSS/blog assets (RSS feed path can be customized with this). [2]
  • RSS/site integration — plugin generates RSS when Astro site is set; RSS placed at /blog/rss.xml by default (overridable via prefix). [2]

Sources / docs: Starlight Blog docs and examples, Starlight Starter reference, and the starlight-blog GitHub repo. [1][2][3][4]

Would you like the exact TypeScript/schema for every option (I can fetch and paste the plugin’s schema file)?

References:
[1] https://starlight-blog-docs.vercel.app/
[2] https://starlight-blog-docs.vercel.app/guides/rss/
[3] https://30daysof.github.io/astro-starlight-ghpages/ (example usage / config snippets)
[4] https://github.com/HiDeoo/starlight-blog


🌐 Web query:

"starlightBlog" configuration plugin options complete list github source code

💡 Result:

Here are the sources with the plugin configuration/options and the plugin source code:

  • GitHub repository (source code): HiDeoo/starlight-blog. [1]
  • Official plugin documentation (configuration/options reference and examples): Starlight Blog docs. [2]

References

  1. HiDeoo / starlight-blog — GitHub repository. [https://github.com/HiDeoo/starlight-blog]
  2. Starlight Blog documentation — Configuration / Options. [https://www.starlightstarter.com/documentation/options/blog/ ]

🏁 Script executed:

#!/bin/bash
# Search for starlight-blog configuration schema or type definitions
curl -s https://raw.githubusercontent.com/HiDeoo/starlight-blog/main/package.json | head -20

Repository: scalekit-inc/developer-docs

Length of output: 794


🏁 Script executed:

#!/bin/bash
# Search for configuration options in starlight-blog source
curl -s https://raw.githubusercontent.com/HiDeoo/starlight-blog/main/packages/starlight-blog/src/index.ts | head -100

Repository: scalekit-inc/developer-docs

Length of output: 85


🏁 Script executed:

#!/bin/bash
# Try to find the starlight-blog plugin schema from the GitHub repo
curl -s https://api.github.com/repos/HiDeoo/starlight-blog/contents/packages/starlight-blog/src | jq -r '.[] | select(.name | contains("config") or contains("schema")) | .download_url' | head -5

Repository: scalekit-inc/developer-docs

Length of output: 135


🏁 Script executed:

#!/bin/bash
# Search for starlight-blog configuration schema in the repo
curl -s https://api.github.com/repos/HiDeoo/starlight-blog/contents/packages/starlight-blog/src | head -50

Repository: scalekit-inc/developer-docs

Length of output: 211


🌐 Web query:

starlight-blog plugin starlightBlog function parameters options interface

💡 Result:

Summary — API surface

  • Function signature: starlightBlog(userConfig?: StarlightBlogUserConfig): StarlightPlugin. [1][2]

Main user-config (options) you can pass (names used in docs / source):

  • prefix: string — URL prefix for the blog (e.g. "blog"). [1]
  • title: string | Record<string,string> — blog title (string or localized map). [1][2]
  • postCount: number — posts per page (default shown as 5 in docs). [1][4]
  • recentPostCount: number — number of recent posts shown in sidebar. [4]
  • authors: Record<id, { name, title?, picture?, url? }> — global author definitions. [1][4]
  • navigation: 'header-start' | 'header-end' | other — controls where blog modifies header/navigation and whether custom CSS is injected. [2]
  • prefix (RSS/paths) and related path controls are used to generate RSS and routes. [2]
  • frontmatter: object — global defaults / overrides for per-post frontmatter (examples: prev/next booleans to disable prev/next links). [4]
  • featured / featuredPost handling, tags, cover, excerpt, draft — handled via post frontmatter (see schema). [3]

Schema / per-post frontmatter fields (via exported blogSchema / types):

  • authors (string | author object | array), date (Date), excerpt (string), tags (string[]), cover ({ image, alt } or { light, dark, alt }), featured (boolean), draft (boolean). See blogSchema and blogAuthorSchema. [3]

Notes from source code:

  • The plugin validates userConfig via validateConfig and returns a StarlightPlugin that registers routes (Blog, Tags, Authors), RSS (when astro site is set), remark plugin, component overrides and Vite plugin. Exported types StarlightBlogConfig and StarlightBlogUserConfig are re-exported. [2]

Primary references

  • Starlight Blog docs (Getting Started / options). [1]
  • starlight-blog source (index.ts on unpkg) — function signature, route/integration behavior and config handling. [2]
  • starlight-blog schema.ts — blogSchema and frontmatter field types. [3]
  • Community/how-to examples describing postCount, authors, frontmatter usage. [4]

If you want, I can paste the exact TypeScript type for StarlightBlogUserConfig (from the lib/config file) or open the specific version of the package you use and extract the precise interface. Which version are you using?


🌐 Web query:

starlight-blog starlightBlog function parameters do not include metrics configuration

💡 Result:

You're seeing that error because starlightBlog() (the Starlight Blog plugin) does not accept a top-level "metrics" configuration — blog-specific options are handled by the plugin, while site-wide integrations (analytics/metrics) are configured on the Starlight integration or via a separate analytics plugin. See the plugin docs which show starlightBlog is added under starlight(...) plugins, and the Starlight integration docs for global config; PostHog is an example of an analytics option added at the Starlight/integration level. [1][2][3]

What to do

  • Remove any metrics option passed directly to starlightBlog(...). Configure metrics/analytics at the starlight(...) integration level or using a dedicated analytics plugin (e.g., PostHog via Starlight’s integration). [1][2][3]

References

  • Starlight Blog (plugin) docs — installation/config pattern (plugins live inside starlight({... plugins: [starlightBlog()] })). [1]
  • Starlight Blog getting-started / configuration details. [2]
  • Example analytics (PostHog) added via Starlight integration. [3]

Remove invalid metrics configuration from starlightBlog() plugin options.

The starlightBlog() function does not accept a metrics configuration option. Reading time and word count are automatically computed and exposed as post metadata through the plugin's frontmatter schema and blog components. Remove the entire metrics object from the configuration.

The valid starlightBlog() options are: prefix, title, postCount, recentPostCount, authors, navigation, and frontmatter.

🤖 Prompt for AI Agents
In `@astro.config.mjs` around lines 94 - 99, Remove the invalid metrics option
from the starlightBlog() call: open the configuration where starlightBlog(...)
is invoked and delete the entire metrics: { readingTime: true, words: 'total' }
object so the plugin options only use supported keys (prefix, title, postCount,
recentPostCount, authors, navigation, frontmatter); ensure no other code relies
on that removed option since reading time and word count are provided
automatically via post metadata/frontmatter.

Comment on lines 511 to 515
export const exclude = [
'/', // Home page
'/blog',
'/404', // Error page
'/apis/**/*', // REST API reference has Scalar-powered navigation
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Exclude the entire blog subtree, not just /blog.

/blog alone may not match /blog/... pages in glob-based matching. Consider using /blog/** to ensure all blog posts are excluded from topic navigation.

🔧 Suggested fix
 export const exclude = [
   '/', // Home page
-  '/blog',
+  '/blog/**',
   '/404', // Error page
   '/apis/**/*', // REST API reference has Scalar-powered navigation
 ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const exclude = [
'/', // Home page
'/blog',
'/404', // Error page
'/apis/**/*', // REST API reference has Scalar-powered navigation
export const exclude = [
'/', // Home page
'/blog/**',
'/404', // Error page
'/apis/**/*', // REST API reference has Scalar-powered navigation
]
🤖 Prompt for AI Agents
In `@src/configs/sidebar.config.ts` around lines 511 - 515, The exclude array
(export const exclude) currently lists '/blog' which may not match nested blog
pages; update the pattern in the exclude array to use a recursive glob (e.g.,
replace '/blog' with '/blog/**') so the entire blog subtree is excluded by the
glob matcher, and keep the existing '/apis/**/*' style consistent with other
entries.

Comment on lines +1 to +16
---
title: 'Building a Custom Organization Switcher'
description: 'Learn how to build your own organization switcher UI for complete control over multi-tenant user experiences.'
date: 2025-01-21
tags: ['Full stack auth']
excerpt: When users belong to multiple organizations, the default Scalekit organization switcher handles most use cases. However, some applications require deeper integration—a custom switcher embedded directly in your app's navigation, or a specialized UI that matches your design system.
featured: true
cover:
alt: 'Modern desk setup with laptop and workspace accessories'
image: ../../../../assets/blog/covers/custom-org-switcher.jpg
authors:
- name: 'Hashirr'
title: 'Hero developer'
url: 'https://www.linkedin.com/in/hashirr-lukmahn/'
picture: '/images/blog/authors/hashirr-lukmahn.jpg'
---
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add required frontmatter fields and fix title casing/date.

Frontmatter is missing required navigation metadata (sidebar label and order), and the title should be in sentence case. Also, Line 4 uses 2025-01-21; please confirm if this should reflect the current publish date (e.g., 2026-01-21). As per coding guidelines, add tableOfContents since this page has multiple sections. As per coding guidelines, ...

🤖 Prompt for AI Agents
In `@src/content/docs/blog/building-custom-org-switcher.mdx` around lines 1 - 16,
Update the MDX frontmatter: change the Title field to sentence case (update
'title'), confirm and update the publish `date` to the intended current date if
needed, and add the required navigation metadata by adding `sidebar_label` (a
short label) and `sidebar_position` or `order` to place it in the docs
navigation; also add `tableOfContents: true` to enable TOC for multi-section
pages and ensure the existing `authors`, `tags`, `excerpt`, `featured`, and
`cover` fields remain intact (look for the frontmatter block beginning with
`---` and the keys `title`, `date`, `authors` to locate where to add these
fields).

Comment on lines +47 to +103
<Tabs>
<TabItem value="node" label="Node.js">
```javascript title="Express.js"
// Use case: Get user's organizations for your switcher UI
// Security: Always validate session ownership before returning org data
const session = await scalekit.session.getSession(sessionId);

// Extract organizations from the session response
const organizations = session.authenticated_organizations || [];

// Render your organization switcher with this data
res.json({ organizations });
```
</TabItem>
<TabItem value="python" label="Python">
```python title="Flask"
# Use case: Get user's organizations for your switcher UI
# Security: Always validate session ownership before returning org data
session = scalekit_client.session.get_session(session_id)

# Extract organizations from the session response
organizations = session.get('authenticated_organizations', [])

# Render your organization switcher with this data
return jsonify({'organizations': organizations})
```
</TabItem>
<TabItem value="go" label="Go">
```go title="Gin"
// Use case: Get user's organizations for your switcher UI
// Security: Always validate session ownership before returning org data
session, err := scalekitClient.Session().GetSession(ctx, sessionId)
if err != nil {
return err
}

// Extract organizations from the session response
organizations := session.AuthenticatedOrganizations

// Render your organization switcher with this data
c.JSON(http.StatusOK, gin.H{"organizations": organizations})
```
</TabItem>
<TabItem value="java" label="Java">
```java title="Spring"
// Use case: Get user's organizations for your switcher UI
// Security: Always validate session ownership before returning org data
Session session = scalekitClient.sessions().getSession(sessionId);

// Extract organizations from the session response
List<Organization> organizations = session.getAuthenticatedOrganizations();

// Render your organization switcher with this data
return ResponseEntity.ok(Map.of("organizations", organizations));
```
</TabItem>
</Tabs>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use <Tabs syncKey="tech-stack"> for multi-language examples.

Both Tabs blocks should include syncKey="tech-stack" so language selection stays consistent across pages. This is required for MDX multi-language examples. Based on learnings, ...

🔧 Suggested update
-<Tabs>
+<Tabs syncKey="tech-stack">

Also applies to: 124-243

🤖 Prompt for AI Agents
In `@src/content/docs/blog/building-custom-org-switcher.mdx` around lines 47 -
103, Add the required syncKey attribute to the Tabs components so language
selection remains consistent: locate the Tabs elements (the top-level Tabs
component wrapping the TabItem blocks in this file) and add syncKey="tech-stack"
to each Tabs instance (the TabItem components remain unchanged); ensure both
Tabs blocks on the page use the identical syncKey value "tech-stack" so
multi-language examples stay synchronized across pages.

Comment on lines +107 to +116
## Add domain context

Enhance your switcher by displaying which domains are associated with each organization. Use the Domains API to fetch this information.

```javascript
// Example: Fetch domains for an organization
const domains = await scalekit.domains.list({ organizationId: 'org_123' });

// Display "@acme.com" next to the organization name in your UI
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Provide 4-language examples for the Domains API snippet.

The “Add domain context” block is JavaScript-only, but documentation requires Node.js, Python, Go, and Java for all code examples. Please convert this snippet to a Tabs block with all four languages. As per coding guidelines, ...

🤖 Prompt for AI Agents
In `@src/content/docs/blog/building-custom-org-switcher.mdx` around lines 107 -
116, The "Add domain context" block currently contains only a JavaScript
example; replace it with a Tabs block containing Node.js, Python, Go, and Java
examples that each call the Domains API to list domains for an organization and
show how to display a domain (e.g., "@acme.com") next to the org name.
Specifically, update the block that references scalekit.domains.list and
organizationId: 'org_123' so it includes a Node.js/JavaScript snippet (same call
pattern), a Python snippet calling scalekit.domains.list or equivalent client
method with organization_id='org_123', a Go snippet using the Domains.List
method with OrganizationID: "org_123", and a Java snippet using the
domains().list(...) call with organizationId "org_123"; keep the examples
minimal and consistent (fetch domains, iterate or access first domain, and show
"@acme.com" display note).

- Updated the Astro configuration to include a prefix for the starlight-blog integration, enhancing the organization of blog content under the 'cookbooks' category. This change aims to improve navigation and content discoverability for users.
- Changed the sidebar configuration to exclude the '/blog' path and include '/cookbooks' for improved navigation.
- Introduced a new guide titled "Building a Custom Organization Switcher," detailing how to create a custom organization switcher UI using Scalekit's APIs, enhancing user experience for multi-tenant applications.
- The guide includes step-by-step instructions, code examples in multiple languages, and best practices for managing organization context.
@saif-at-scalekit saif-at-scalekit changed the title POC: Blog style listing in the docs POC: Cookbook style listing in the docs Jan 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant