Conversation
- Created new directory structure for documentation under `/docs2`. - Added `.gitignore` to exclude build artifacts and dependencies. - Introduced `package.json`, `next.config.mjs`, and `postcss.config.mjs` for project configuration. - Implemented MDX components in `mdx-components.tsx` for rendering documentation. - Migrated existing documentation content and created new files for auto-updater and other features. - Established compatibility layer for Mintlify components in `mintlify-compat.tsx`. - Set up OpenAPI documentation in `openapi.json`. - Updated README and migration guide to reflect new structure and usage instructions. - Ensured all components and pages are ready for development and deployment with Fumadocs.
- Added server configurations for local and production environments in `main.py`. - Removed outdated authentication and generation API documentation files. - Updated documentation structure to reflect the removal of deprecated API endpoints. - Adjusted links in the quick start and developer setup documentation to point to the new API reference. - Enhanced global CSS styles for improved theming support.
…madocs - Updated `.gitignore` to include new build and generated content directories. - Removed outdated Mintlify configuration files and documentation. - Introduced new `MIGRATION.md` to outline the transition from Mintlify to Fumadocs. - Added `mdx-components.tsx` for MDX component configuration and compatibility. - Updated `package.json` and `next.config.mjs` for new dependencies and Next.js configuration. - Created `source.config.ts` for content source configuration. - Added OpenAPI specification in `openapi.json` for API documentation. - Removed legacy files and adjusted project structure to align with Fumadocs conventions.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (34)
📝 WalkthroughWalkthroughMigrates documentation infrastructure from Mintlify to Fumadocs with Next.js, replacing configuration files, restructuring app routes and layouts, updating documentation content, adding OpenAPI-based API reference generation, and introducing UI components for the new framework. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip CodeRabbit can use oxc to improve the quality of JavaScript and TypeScript code reviews.Add a configuration file to your project to customize how CodeRabbit runs oxc. |
# Conflicts: # backend/main.py # docs/content/docs/plans/ADDING_TTS_ENGINES.md # docs/content/docs/plans/CUDA_BACKEND_SWAP.md # docs/content/docs/plans/CUDA_BACKEND_SWAP_FINAL.md # docs/content/docs/plans/EXTERNAL_PROVIDERS.md # docs/content/docs/plans/MLX_AUDIO.md # docs/content/docs/plans/PROJECT_STATUS.md
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (6)
docs/app/(home)/page.tsx (1)
6-13: Replace placeholder homepage copy before merge.Lines 6–13 still read like scaffolding text. Recommend using Voicebox-specific messaging so the docs landing page feels intentional.
♻️ Suggested content update
- <h1 className="text-2xl font-bold mb-4">Hello World</h1> + <h1 className="text-2xl font-bold mb-4">Voicebox Documentation</h1> <p> - You can open{' '} + Start with{' '} <Link href="/docs" className="font-medium underline"> /docs </Link>{' '} - and see the documentation. + for setup guides, API reference, and troubleshooting. </p>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/app/`(home)/page.tsx around lines 6 - 13, Replace the placeholder homepage copy in the JSX block containing the <h1 className="text-2xl font-bold mb-4">Hello World</h1> and the paragraph with the <Link href="/docs" className="font-medium underline">/docs</Link> link: update the heading and paragraph to Voicebox-specific messaging (concise product value, what users can do, and a clear CTA to the docs) so the docs landing feels intentional and not scaffolding; ensure you keep the existing element structure and classes while swapping the text content only.docs/content/docs/api-reference/meta.json (1)
3-3: Use a user-meaningful group slug instead ofunknown.Line 3 exposes
unknownas the top-level API section, which is confusing in navigation. Prefer tagging operations in the OpenAPI spec so generated groups are domain-based (for example,profiles,health, etc.).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/content/docs/api-reference/meta.json` at line 3, Replace the placeholder value "unknown" in the top-level "pages" array of meta.json with a user-meaningful group slug (e.g., "profiles", "health", "auth") and then regenerate the docs so navigation reflects that domain; if the slug is derived from your OpenAPI sources, add or correct the "tags" array on each OpenAPI operation (the operation objects' "tags" field) to the intended group name so the generator produces the proper page grouping instead of "unknown".docs/content/docs/TROUBLESHOOTING.md (1)
1-6: LGTM with minor observation.The front matter is correctly formatted. Note that Line 6 duplicates the description from the front matter. Consider removing the redundant line or expanding it to provide additional context that differs from the meta description.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/content/docs/TROUBLESHOOTING.md` around lines 1 - 6, The document repeats the description from the YAML front matter in the body — remove or modify the duplicate sentence "Common issues and solutions for Voicebox." in the body to avoid redundancy; locate the front matter at the top (the title/description block) and either delete that repeated line from the content or replace it with expanded contextual content (e.g., a brief intro or summary that adds information beyond the meta description).docs/README.md (1)
1-4: Update README title and description to reflect the project.The README retains template boilerplate from Create Fumadocs. Consider updating the title to "Voicebox Documentation" and adjusting the description to be project-specific rather than referencing the generator template.
📝 Suggested update
-# fumadocs-ui-template +# Voicebox Documentation -This is a Next.js application generated with -[Create Fumadocs](https://github.com/fuma-nama/fumadocs). +This is the documentation site for Voicebox, built with Next.js and +[Fumadocs](https://fumadocs.dev).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/README.md` around lines 1 - 4, Update the README header and intro to remove the Create Fumadocs boilerplate: change the H1 line currently reading "fumadocs-ui-template" to "Voicebox Documentation" and replace the second paragraph that references "This is a Next.js application generated with [Create Fumadocs]" with a project-specific description summarizing Voicebox (what it does, key tech like Next.js if desired, and any quick start or repo purpose). Ensure the new title and description are concise and reflect the Voicebox project instead of the generator.docs/openapi.json (1)
1-1: Security definitions are not necessary for the default local-only deployment.The OpenAPI spec lacks security schemes, but this is intentional for Voicebox's local-first design. The API runs on
localhost:8000by default, and SECURITY.md explicitly documents this architecture. For remote server deployments, security should be handled at the network layer (reverse proxy, firewall, or VPN) rather than in the spec. If the project plans to officially support unsecured remote deployments, consider adding security schemes and documenting authentication requirements.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/openapi.json` at line 1, The OpenAPI spec intentionally omits security schemes for a local-only deployment but the spec should make that explicit; update the root OpenAPI "info.description" (the info.description field) to add a short note stating that no security schemes are defined because the service is local-only by default and refer to SECURITY.md for remote deployment guidance, so reviewers understand the omission without changing endpoints or adding auth components.docs/scripts/generate-openapi.ts (1)
4-7: Resolve the output path from the script location.
output: 'content/docs/api-reference'is cwd-sensitive, so running this script from the repo root would generate intocontent/...instead ofdocs/content/.... Anchoring it toimport.meta.urlmakes the generator deterministic regardless of how it is invoked.📁 Suggested hardening
+import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { generateFiles } from 'fumadocs-openapi'; import { openapi } from '../lib/openapi'; +const outputDir = resolve( + dirname(fileURLToPath(import.meta.url)), + '../content/docs/api-reference', +); + await generateFiles({ input: openapi, - output: 'content/docs/api-reference', + output: outputDir, groupBy: 'tag', });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/scripts/generate-openapi.ts` around lines 4 - 7, The output path passed to generateFiles is cwd-sensitive (output: 'content/docs/api-reference'); update the call in generateFiles to resolve a deterministic absolute path anchored to this script (use import.meta.url) so it always writes to docs/content/... regardless of CWD. Locate the generateFiles invocation and replace the literal output string with a path resolved from import.meta.url (or equivalent URL-to-path helper) so the generator uses the script's directory as the base when producing the output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/main.py`:
- Around line 37-40: The OpenAPI servers list currently hardcodes a "Production
server" URL to "http://localhost:17493", which is invalid outside local dev;
update the servers configuration (the servers=[ ... ] structure) to avoid a
hardcoded localhost production entry by either removing the production entry
entirely or sourcing its URL from an environment/config variable (e.g.,
PROD_SERVER_URL) and only adding it when that variable is present and non-empty;
ensure the descriptive name remains clear (e.g., "Production server") and that
fallback behavior for missing env is to omit the production server so client
defaults won't point to localhost.
In `@docs/app/docs/`[[...slug]]/page.tsx:
- Line 12: Remove the unused APIPage import from the module: delete the import
statement referencing APIPage so the file no longer imports an identifier that
isn't used (remove "APIPage" from the import line shown in the diff). This will
silence the linter/biome warning and avoid failing the build.
In `@docs/app/docs/layout.tsx`:
- Line 5: The Layout component uses the type LayoutProps<'/docs'> but that type
is not imported; add an import for LayoutProps (e.g., import { LayoutProps }
from 'fumadocs-ui') at the top of the file or alternatively define a local prop
type (e.g., using React.PropsWithChildren or a custom interface) and replace
LayoutProps<'/docs'> in the Layout function signature so the TypeScript error is
resolved; update the export default function Layout({ children }:
LayoutProps<'/docs'>) declaration to use the imported or newly defined type.
In `@docs/app/og/docs/`[...slug]/route.tsx:
- Around line 18-22: The OG card currently passes a placeholder site label "My
App" to the DefaultImage component; update the site prop in the DefaultImage
invocation (title={page.data.title} description={page.data.description} site="My
App") to the correct branding (e.g., site="Voicebox" or reference the app's
BRAND_NAME constant) so the generated OG images match the Voicebox branding.
In `@docs/components/mintlify-compat.tsx`:
- Around line 63-67: The description currently only preserves raw string
children, causing MDX-generated element-wrapped text to be dropped; update the
MintlifyCard/description extraction logic to walk React children (using
React.Children.toArray on the children prop) and recursively extract and
concatenate text content from strings and element nodes (inspecting
node.props.children) into a single plain string, then assign that string to the
description variable so element-wrapped MDX text is preserved.
In `@docs/content/docs/README.md`:
- Around line 36-46: Add a language identifier to the fenced code block that
renders the directory tree (the triple-backtick block that begins with the line
"docs/"); change the opening fence from ``` to ```text so the block is
explicitly marked as plain text (this fixes MD040).
- Around line 12-53: The README still instructs Mintlify setup (commands like
"bun add -g mintlify", "bun run install:mintlify", references to mint.json and
Mintlify components) while the project is built with Fumadocs; replace
Mintlify-specific install/run instructions with the Fumadocs/Next.js equivalents
(use "bun install" instead of the global mintlify install and remove the
"install:mintlify" helper), update the "Running Locally" text to state this
starts the Fumadocs/Next.js docs server (keeping the "bun run dev" command), and
replace the mint.json/mintlify structure and component guidance with the
Fumadocs layout (e.g., list app/, content/, components/, lib/, public/,
reference meta.json for navigation and docs/mdx-components.tsx for MDX
components) so all mentions of Mintlify, mint.json, and Mintlify components are
removed or rewritten to the Fumadocs equivalents.
In `@docs/MIGRATION.md`:
- Line 3: Update the MIGRATION.md references that point to `/docs2` so they
instead point to `/docs`; specifically edit the introductory sentence ("This
document summarizes the migration...") and any file-tree or path examples
between the intro and lines referenced (near the block cited and the region
noted as "Also applies to: 42-57") to use `docs/` rather than `docs2/` so the
guide matches the repository layout.
---
Nitpick comments:
In `@docs/app/`(home)/page.tsx:
- Around line 6-13: Replace the placeholder homepage copy in the JSX block
containing the <h1 className="text-2xl font-bold mb-4">Hello World</h1> and the
paragraph with the <Link href="/docs" className="font-medium
underline">/docs</Link> link: update the heading and paragraph to
Voicebox-specific messaging (concise product value, what users can do, and a
clear CTA to the docs) so the docs landing feels intentional and not
scaffolding; ensure you keep the existing element structure and classes while
swapping the text content only.
In `@docs/content/docs/api-reference/meta.json`:
- Line 3: Replace the placeholder value "unknown" in the top-level "pages" array
of meta.json with a user-meaningful group slug (e.g., "profiles", "health",
"auth") and then regenerate the docs so navigation reflects that domain; if the
slug is derived from your OpenAPI sources, add or correct the "tags" array on
each OpenAPI operation (the operation objects' "tags" field) to the intended
group name so the generator produces the proper page grouping instead of
"unknown".
In `@docs/content/docs/TROUBLESHOOTING.md`:
- Around line 1-6: The document repeats the description from the YAML front
matter in the body — remove or modify the duplicate sentence "Common issues and
solutions for Voicebox." in the body to avoid redundancy; locate the front
matter at the top (the title/description block) and either delete that repeated
line from the content or replace it with expanded contextual content (e.g., a
brief intro or summary that adds information beyond the meta description).
In `@docs/openapi.json`:
- Line 1: The OpenAPI spec intentionally omits security schemes for a local-only
deployment but the spec should make that explicit; update the root OpenAPI
"info.description" (the info.description field) to add a short note stating that
no security schemes are defined because the service is local-only by default and
refer to SECURITY.md for remote deployment guidance, so reviewers understand the
omission without changing endpoints or adding auth components.
In `@docs/README.md`:
- Around line 1-4: Update the README header and intro to remove the Create
Fumadocs boilerplate: change the H1 line currently reading
"fumadocs-ui-template" to "Voicebox Documentation" and replace the second
paragraph that references "This is a Next.js application generated with [Create
Fumadocs]" with a project-specific description summarizing Voicebox (what it
does, key tech like Next.js if desired, and any quick start or repo purpose).
Ensure the new title and description are concise and reflect the Voicebox
project instead of the generator.
In `@docs/scripts/generate-openapi.ts`:
- Around line 4-7: The output path passed to generateFiles is cwd-sensitive
(output: 'content/docs/api-reference'); update the call in generateFiles to
resolve a deterministic absolute path anchored to this script (use
import.meta.url) so it always writes to docs/content/... regardless of CWD.
Locate the generateFiles invocation and replace the literal output string with a
path resolved from import.meta.url (or equivalent URL-to-path helper) so the
generator uses the script's directory as the base when producing the output.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 89f175b2-39fc-4ab4-8779-c7978ae4848a
⛔ Files ignored due to path filters (3)
docs/bun.lockis excluded by!**/*.lockdocs/public/logo/icon-dark.pngis excluded by!**/*.pngdocs/public/logo/icon-light.pngis excluded by!**/*.png
📒 Files selected for processing (103)
backend/main.pydocs/.gitignoredocs/MIGRATION.mddocs/README.mddocs/api/authentication.mdxdocs/api/generation.mdxdocs/api/overview.mdxdocs/api/recordings.mdxdocs/api/voice-profiles.mdxdocs/app/(home)/layout.tsxdocs/app/(home)/page.tsxdocs/app/api/search/route.tsdocs/app/docs/[[...slug]]/page.tsxdocs/app/docs/layout.tsxdocs/app/global.cssdocs/app/layout.tsxdocs/app/llms-full.txt/route.tsdocs/app/og/docs/[...slug]/route.tsxdocs/components/api-page.client.tsxdocs/components/api-page.tsxdocs/components/mintlify-compat.tsxdocs/content/docs/AUTOUPDATER.mddocs/content/docs/AUTOUPDATER_QUICKSTART.mddocs/content/docs/README.mddocs/content/docs/TROUBLESHOOTING.mddocs/content/docs/api-reference/meta.jsondocs/content/docs/api-reference/unknown/add_profile_sample_profiles__profile_id__samples_post.mdxdocs/content/docs/api-reference/unknown/create_profile_profiles_post.mdxdocs/content/docs/api-reference/unknown/delete_generation_history__generation_id__delete.mdxdocs/content/docs/api-reference/unknown/delete_profile_profiles__profile_id__delete.mdxdocs/content/docs/api-reference/unknown/delete_profile_sample_profiles_samples__sample_id__delete.mdxdocs/content/docs/api-reference/unknown/generate_speech_generate_post.mdxdocs/content/docs/api-reference/unknown/get_audio_audio__generation_id__get.mdxdocs/content/docs/api-reference/unknown/get_generation_history__generation_id__get.mdxdocs/content/docs/api-reference/unknown/get_model_progress_models_progress__model_name__get.mdxdocs/content/docs/api-reference/unknown/get_model_status_models_status_get.mdxdocs/content/docs/api-reference/unknown/get_profile_profiles__profile_id__get.mdxdocs/content/docs/api-reference/unknown/get_profile_samples_profiles__profile_id__samples_get.mdxdocs/content/docs/api-reference/unknown/get_stats_history_stats_get.mdxdocs/content/docs/api-reference/unknown/health_health_get.mdxdocs/content/docs/api-reference/unknown/list_history_history_get.mdxdocs/content/docs/api-reference/unknown/list_profiles_profiles_get.mdxdocs/content/docs/api-reference/unknown/load_model_models_load_post.mdxdocs/content/docs/api-reference/unknown/meta.jsondocs/content/docs/api-reference/unknown/root__get.mdxdocs/content/docs/api-reference/unknown/transcribe_audio_transcribe_post.mdxdocs/content/docs/api-reference/unknown/trigger_model_download_models_download_post.mdxdocs/content/docs/api-reference/unknown/unload_model_models_unload_post.mdxdocs/content/docs/api-reference/unknown/update_profile_profiles__profile_id__put.mdxdocs/content/docs/developer/architecture.mdxdocs/content/docs/developer/audio-channels.mdxdocs/content/docs/developer/autoupdater.mdxdocs/content/docs/developer/building.mdxdocs/content/docs/developer/contributing.mdxdocs/content/docs/developer/history.mdxdocs/content/docs/developer/meta.jsondocs/content/docs/developer/model-management.mdxdocs/content/docs/developer/setup.mdxdocs/content/docs/developer/stories.mdxdocs/content/docs/developer/transcription.mdxdocs/content/docs/developer/tts-generation.mdxdocs/content/docs/developer/voice-profiles.mdxdocs/content/docs/index.mdxdocs/content/docs/meta.jsondocs/content/docs/overview/building-stories.mdxdocs/content/docs/overview/creating-voice-profiles.mdxdocs/content/docs/overview/generating-speech.mdxdocs/content/docs/overview/generation-history.mdxdocs/content/docs/overview/installation.mdxdocs/content/docs/overview/introduction.mdxdocs/content/docs/overview/meta.jsondocs/content/docs/overview/quick-start.mdxdocs/content/docs/overview/recording-transcription.mdxdocs/content/docs/overview/remote-mode.mdxdocs/content/docs/overview/stories-editor.mdxdocs/content/docs/overview/troubleshooting.mdxdocs/content/docs/overview/voice-cloning.mdxdocs/content/docs/plans/DOCKER_DEPLOYMENT.mddocs/content/docs/plans/EXTERNAL_PROVIDERS.mddocs/content/docs/plans/MLX_AUDIO.mddocs/content/docs/plans/OPENAI_SUPPORT.mddocs/content/docs/plans/meta.jsondocs/custom.cssdocs/lib/layout.shared.tsxdocs/lib/openapi.tsdocs/lib/source.tsdocs/mdx-components.tsxdocs/mint.jsondocs/next.config.mjsdocs/nixpacks.tomldocs/openapi.jsondocs/package.jsondocs/plans/TTS_PROVIDER_ARCHITECTURE.mddocs/postcss.config.mjsdocs/public/app-screenshot-1.webpdocs/public/app-screenshot-2.webpdocs/public/app-screenshot-3.webpdocs/public/images/app-screenshot-1.webpdocs/public/images/app-screenshot-2.webpdocs/public/images/app-screenshot-3.webpdocs/scripts/generate-openapi.tsdocs/source.config.tsdocs/tsconfig.json
💤 Files with no reviewable changes (9)
- docs/api/voice-profiles.mdx
- docs/api/overview.mdx
- docs/api/generation.mdx
- docs/api/authentication.mdx
- docs/mint.json
- docs/nixpacks.toml
- docs/plans/TTS_PROVIDER_ARCHITECTURE.md
- docs/api/recordings.mdx
- docs/custom.css
| import { getMDXComponents } from '@/mdx-components'; | ||
| import type { Metadata } from 'next'; | ||
| import { createRelativeLink } from 'fumadocs-ui/mdx'; | ||
| import { APIPage } from '@/components/api-page'; |
There was a problem hiding this comment.
Remove the unused APIPage import.
Biome is already flagging this, so it will keep the docs app noisy at best and fail lint at worst.
🧹 Minimal fix
-import { APIPage } from '@/components/api-page';📝 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.
| import { APIPage } from '@/components/api-page'; |
🧰 Tools
🪛 Biome (2.4.6)
[error] 12-12: This import is unused.
(lint/correctness/noUnusedImports)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/app/docs/`[[...slug]]/page.tsx at line 12, Remove the unused APIPage
import from the module: delete the import statement referencing APIPage so the
file no longer imports an identifier that isn't used (remove "APIPage" from the
import line shown in the diff). This will silence the linter/biome warning and
avoid failing the build.
| import { DocsLayout } from 'fumadocs-ui/layouts/docs'; | ||
| import { baseOptions } from '@/lib/layout.shared'; | ||
|
|
||
| export default function Layout({ children }: LayoutProps<'/docs'>) { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if LayoutProps is defined or imported elsewhere
echo "=== Searching for LayoutProps definition ==="
rg -n "LayoutProps" docs/
echo "=== Checking fumadocs-ui exports ==="
rg -n "LayoutProps" node_modules/fumadocs-ui/ 2>/dev/null || echo "Cannot search node_modules"Repository: jamiepine/voicebox
Length of output: 621
🏁 Script executed:
# Check the full content of docs/app/docs/layout.tsx to see all imports
echo "=== Full content of docs/app/docs/layout.tsx ==="
cat -n docs/app/docs/layout.tsx
echo -e "\n=== Full content of docs/app/layout.tsx ==="
cat -n docs/app/layout.tsx
echo -e "\n=== Full content of docs/app/(home)/layout.tsx ==="
cat -n docs/app/'(home)'/layout.tsx
echo -e "\n=== Search for LayoutProps type definition ==="
rg -n "type\s+LayoutProps|interface\s+LayoutProps" docs/
echo -e "\n=== Check tsconfig or global types ==="
find . -name "*.d.ts" -o -name "tsconfig.json" | head -5 | xargs grep -l "LayoutProps" 2>/dev/null || echo "No matches in type definition files"Repository: jamiepine/voicebox
Length of output: 1591
🏁 Script executed:
# Check package.json for fumadocs-ui
echo "=== Checking package.json for fumadocs-ui ==="
cat package.json | grep -A 2 -B 2 "fumadocs-ui"
# Search for any .d.ts files that might export LayoutProps
echo -e "\n=== Search for .d.ts files ==="
find . -name "*.d.ts" 2>/dev/null | head -20
# Check if there's a specific import path we're missing
echo -e "\n=== Search for fumadocs-ui imports to understand pattern ==="
rg -n "from ['\"]fumadocs-ui" docs/ --type tsxRepository: jamiepine/voicebox
Length of output: 268
🏁 Script executed:
# Read the global.d.ts file
echo "=== Content of ./app/src/global.d.ts ==="
cat -n ./app/src/global.d.ts
# Read package.json
echo -e "\n=== package.json ==="
cat package.json | head -50
# Search for LayoutProps in all files
echo -e "\n=== Search for LayoutProps definition anywhere ==="
rg -n "LayoutProps" . --max-depth 3
# Check fumadocs-ui imports
echo -e "\n=== Check all fumadocs-ui imports ==="
rg -n "from.*fumadocs-ui" .Repository: jamiepine/voicebox
Length of output: 3048
🏁 Script executed:
# Check if docs has its own package.json
echo "=== Checking for package.json in docs folder ==="
find docs -name "package.json" -o -name "package-lock.json"
cat docs/package.json 2>/dev/null || echo "No docs/package.json found"
# Check tsconfig to understand the project setup
echo -e "\n=== Checking docs tsconfig ==="
cat docs/tsconfig.json 2>/dev/null || cat tsconfig.json | head -30
# Search for LayoutProps being imported anywhere (might be a missed import)
echo -e "\n=== Check if LayoutProps should be imported from fumadocs-ui ==="
rg -n "LayoutProps" . --glob "*.ts" --glob "*.tsx" -B 5 | head -40Repository: jamiepine/voicebox
Length of output: 2963
🏁 Script executed:
# Check the fumadocs-ui types directory
echo "=== Looking for LayoutProps in fumadocs-ui type definitions ==="
find docs/node_modules/fumadocs-ui -name "*.d.ts" 2>/dev/null | xargs grep -l "LayoutProps" 2>/dev/null | head -5
# Try to find what LayoutProps should be
echo -e "\n=== Search for layout-related exports from fumadocs-ui ==="
find docs/node_modules/fumadocs-ui -name "*.d.ts" 2>/dev/null | xargs grep -i "layout" 2>/dev/null | grep -i "props\|type\|interface" | head -20
# Check if there's a main index.d.ts or types file
echo -e "\n=== Check fumadocs-ui main exports ==="
cat docs/node_modules/fumadocs-ui/package.json 2>/dev/null | grep -A 5 '"types"\|"exports"'Repository: jamiepine/voicebox
Length of output: 225
🏁 Script executed:
# Let's check if there's a type declaration file for LayoutProps anywhere in the docs folder
echo "=== Search for any type definitions or augmentations ==="
find docs -type f \( -name "*.d.ts" -o -name "types.ts" \) 2>/dev/null | xargs cat 2>/dev/null
# Check next.d.ts or similar
echo -e "\n=== Check for next env types ==="
ls -la docs/.next/types/ 2>/dev/null || echo ".next/types not found"
# Try to see what the actual TypeScript error would be by checking if fumadocs-ui exports LayoutProps
echo -e "\n=== Check fumadocs-ui layouts index ==="
cat docs/node_modules/fumadocs-ui/dist/layouts/index.d.ts 2>/dev/null || echo "Not found"
# Look at the actual fumadocs-ui exports structure
echo -e "\n=== List fumadocs-ui layout exports ==="
ls -la docs/node_modules/fumadocs-ui/dist/layouts/ 2>/dev/null | head -20Repository: jamiepine/voicebox
Length of output: 266
🏁 Script executed:
# Search the entire codebase for where LayoutProps might be defined or imported
echo "=== Complete search for LayoutProps ==="
rg "LayoutProps" docs/ -A 2 -B 2
# Check if there's a lib/types or similar
echo -e "\n=== Check for any type definitions in lib ==="
ls -la docs/lib/
# Look for any .ts file that might re-export types
cat docs/lib/layout.shared.tsx
# Check if LayoutProps might be a generic type from React or Next.js
echo -e "\n=== Check imports from React/Next that might provide LayoutProps ==="
rg "from ['\"]react['\"]|from ['\"]next" docs/app/*.tsx docs/app/**/*.tsxRepository: jamiepine/voicebox
Length of output: 1979
🏁 Script executed:
# Check if there's a .d.ts file that might declare LayoutProps globally
echo "=== Check all .d.ts files ==="
find docs -name "*.d.ts" -exec cat {} \;
# Search for type augmentation or global declarations
echo -e "\n=== Search for declare global or module augmentation ==="
rg "declare global|module\s+['\"]" docs/
# Let's check the React import to see what type should be used
echo -e "\n=== Check what React.FC or similar exports ==="
rg "React\." docs/app/layout.tsx docs/app/docs/layout.tsx docs/app/'(home)'/layout.tsx
# Try searching in node_modules for actual fumadocs-ui layout type exports
echo -e "\n=== Check fumadocs-ui/layouts/docs exports ==="
cat docs/node_modules/fumadocs-ui/dist/layouts/docs.d.ts 2>/dev/null | head -50
# Check if there's a global type file
echo -e "\n=== Check for global types in node_modules/@types or .next ==="
find docs/.next -name "*.ts" 2>/dev/null | xargs grep -l "LayoutProps" 2>/dev/null || echo "No LayoutProps found in .next"Repository: jamiepine/voicebox
Length of output: 339
🏁 Script executed:
# Let me try to understand what LayoutProps should be
# Search for any documentation or comments about LayoutProps
echo "=== Check if LayoutProps is a type that should be auto-generated ==="
rg -i "layoutprops|layout.*props" docs/
# Try to compile and see what error we get
echo -e "\n=== Try to see if there's a TypeScript build error ==="
cd docs && npx tsc --noEmit 2>&1 | head -50 || echo "TypeScript check failed or not available"Repository: jamiepine/voicebox
Length of output: 7335
🏁 Script executed:
# Check if LayoutProps is a known export from fumadocs-ui by checking package exports
echo "=== Check fumadocs-ui package.json exports ==="
cat docs/node_modules/fumadocs-ui/package.json | jq '.exports' 2>/dev/null | head -100
# Try to look for any type definition that might provide LayoutProps
echo -e "\n=== Search in fumadocs-ui for any layout-related types ==="
find docs/node_modules/fumadocs-ui -type f -name "*.d.ts" 2>/dev/null | head -10 | xargs grep -l "Layout" 2>/dev/nullRepository: jamiepine/voicebox
Length of output: 262
Add missing import for LayoutProps type.
The LayoutProps<'/docs'> type used on line 5 is not imported, causing a TypeScript compilation error (TS2304: Cannot find name 'LayoutProps'). This type should be imported from fumadocs-ui or defined locally.
🔧 Suggested fix
Import LayoutProps from fumadocs-ui (adjust the import path based on the actual fumadocs-ui export):
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/lib/layout.shared';
+import type { LayoutProps } from 'fumadocs-ui/layouts/shared';
export default function Layout({ children }: LayoutProps<'/docs'>) {Alternatively, if LayoutProps is not exported from fumadocs-ui, use React's standard prop type:
+import type { ReactNode } from 'react';
-export default function Layout({ children }: LayoutProps<'/docs'>) {
+export default function Layout({ children }: { children: ReactNode }) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/app/docs/layout.tsx` at line 5, The Layout component uses the type
LayoutProps<'/docs'> but that type is not imported; add an import for
LayoutProps (e.g., import { LayoutProps } from 'fumadocs-ui') at the top of the
file or alternatively define a local prop type (e.g., using
React.PropsWithChildren or a custom interface) and replace LayoutProps<'/docs'>
in the Layout function signature so the TypeScript error is resolved; update the
export default function Layout({ children }: LayoutProps<'/docs'>) declaration
to use the imported or newly defined type.
| <DefaultImage | ||
| title={page.data.title} | ||
| description={page.data.description} | ||
| site="My App" | ||
| /> |
There was a problem hiding this comment.
Replace the template site label before shipping.
These OG cards will render My App, which does not match the Voicebox branding used elsewhere in this migration.
🎨 Minimal fix
- site="My App"
+ site="Voicebox"📝 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.
| <DefaultImage | |
| title={page.data.title} | |
| description={page.data.description} | |
| site="My App" | |
| /> | |
| <DefaultImage | |
| title={page.data.title} | |
| description={page.data.description} | |
| site="Voicebox" | |
| /> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/app/og/docs/`[...slug]/route.tsx around lines 18 - 22, The OG card
currently passes a placeholder site label "My App" to the DefaultImage
component; update the site prop in the DefaultImage invocation
(title={page.data.title} description={page.data.description} site="My App") to
the correct branding (e.g., site="Voicebox" or reference the app's BRAND_NAME
constant) so the generated OG images match the Voicebox branding.
docs/components/mintlify-compat.tsx
Outdated
| // Extract text content from children to avoid nested <p> tags | ||
| // fumadocs Card component wraps description in a <p>, so we need plain content | ||
| const description = typeof children === 'string' | ||
| ? children | ||
| : undefined; |
There was a problem hiding this comment.
MintlifyCard drops non-string content in descriptions.
On Line 65, only raw string children are preserved. MDX often emits element-wrapped text, so card descriptions can disappear after migration.
Proposed fix
-import type { ReactNode } from 'react';
+import { Children, isValidElement, type ReactNode } from 'react';
+function extractText(node: ReactNode): string {
+ return Children.toArray(node)
+ .map((child) => {
+ if (typeof child === 'string' || typeof child === 'number') return String(child);
+ if (isValidElement<{ children?: ReactNode }>(child)) return extractText(child.props.children);
+ return '';
+ })
+ .join('');
+}
+
export function MintlifyCard({
@@
- const description = typeof children === 'string'
- ? children
- : undefined;
+ const description = extractText(children).trim() || undefined;📝 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.
| // Extract text content from children to avoid nested <p> tags | |
| // fumadocs Card component wraps description in a <p>, so we need plain content | |
| const description = typeof children === 'string' | |
| ? children | |
| : undefined; | |
| import { Children, isValidElement, type ReactNode } from 'react'; | |
| function extractText(node: ReactNode): string { | |
| return Children.toArray(node) | |
| .map((child) => { | |
| if (typeof child === 'string' || typeof child === 'number') return String(child); | |
| if (isValidElement<{ children?: ReactNode }>(child)) return extractText(child.props.children); | |
| return ''; | |
| }) | |
| .join(''); | |
| } | |
| export function MintlifyCard({ | |
| // ... other props | |
| }: Props) { | |
| // Extract text content from children to avoid nested <p> tags | |
| // fumadocs Card component wraps description in a <p>, so we need plain content | |
| const description = extractText(children).trim() || undefined; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/components/mintlify-compat.tsx` around lines 63 - 67, The description
currently only preserves raw string children, causing MDX-generated
element-wrapped text to be dropped; update the MintlifyCard/description
extraction logic to walk React children (using React.Children.toArray on the
children prop) and recursively extract and concatenate text content from strings
and element nodes (inspecting node.props.children) into a single plain string,
then assign that string to the description variable so element-wrapped MDX text
is preserved.
| ``` | ||
| docs/ | ||
| ├── mint.json # Mintlify configuration | ||
| ├── custom.css # Custom styles | ||
| ├── overview/ # Getting started & feature docs | ||
| ├── guides/ # User guides | ||
| ├── api/ # API reference | ||
| ├── development/ # Developer documentation | ||
| ├── logo/ # Logo assets | ||
| └── public/ # Static assets | ||
| ``` |
There was a problem hiding this comment.
Add a language identifier to the fenced block.
The structure tree fence at Line 36 is missing a language token (text is fine), which triggers MD040.
Quick lint fix
-```
+```text
docs/
...
-```
+```🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 36-36: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/content/docs/README.md` around lines 36 - 46, Add a language identifier
to the fenced code block that renders the directory tree (the triple-backtick
block that begins with the line "docs/"); change the opening fence from ``` to
```text so the block is explicitly marked as plain text (this fixes MD040).
| @@ -0,0 +1,87 @@ | |||
| # Documentation Migration: Mintlify → Fumadocs | |||
|
|
|||
| This document summarizes the migration of documentation from `/docs` (Mintlify) to `/docs2` (Fumadocs). | |||
There was a problem hiding this comment.
Update this guide to reference docs/, not docs2/.
The repo changes in this PR live under docs/..., so the current intro and tree send readers to a directory that does not exist in the final layout.
📝 Minimal fix
-This document summarizes the migration of documentation from `/docs` (Mintlify) to `/docs2` (Fumadocs).
+This document summarizes the migration of documentation from Mintlify to the new Fumadocs setup under `/docs`.
-docs2/
+docs/Also applies to: 42-57
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/MIGRATION.md` at line 3, Update the MIGRATION.md references that point
to `/docs2` so they instead point to `/docs`; specifically edit the introductory
sentence ("This document summarizes the migration...") and any file-tree or path
examples between the intro and lines referenced (near the block cited and the
region noted as "Also applies to: 42-57") to use `docs/` rather than `docs2/` so
the guide matches the repository layout.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
docs/app/(home)/page.tsx (1)
1-4: UsepermanentRedirectfor the root docs entrypoint.For a canonical root-to-docs landing path,
permanentRedirect('/docs')is the better choice. It sends an HTTP 308 status (permanent) instead of HTTP 307 (temporary), improving SEO and enabling proper caching by search engines and clients.♻️ Suggested change
-import { redirect } from 'next/navigation'; +import { permanentRedirect } from 'next/navigation'; export default function HomePage() { - redirect('/docs'); + permanentRedirect('/docs'); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/app/`(home)/page.tsx around lines 1 - 4, Replace the temporary redirect with a permanent one: in HomePage, import and call permanentRedirect instead of redirect so the root page issues an HTTP 308; update the import from 'next/navigation' to reference permanentRedirect and replace the redirect('/docs') call with permanentRedirect('/docs') in the HomePage component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/content/docs/TROUBLESHOOTING.md`:
- Around line 1-4: Delete the duplicate file
docs/content/docs/TROUBLESHOOTING.md and remove any references or links pointing
to it (e.g., in site navigation or README); ensure all references instead point
to the canonical page docs/content/docs/overview/troubleshooting.mdx and update
any import/route entries that used TROUBLESHOOTING.md so the site uses the
single correct troubleshooting page.
---
Nitpick comments:
In `@docs/app/`(home)/page.tsx:
- Around line 1-4: Replace the temporary redirect with a permanent one: in
HomePage, import and call permanentRedirect instead of redirect so the root page
issues an HTTP 308; update the import from 'next/navigation' to reference
permanentRedirect and replace the redirect('/docs') call with
permanentRedirect('/docs') in the HomePage component.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 18eb7434-8b09-4805-97d8-eae222214b4d
📒 Files selected for processing (9)
docs/app/(home)/page.tsxdocs/content/docs/TROUBLESHOOTING.mddocs/content/docs/api-reference/meta.jsondocs/content/docs/developer/meta.jsondocs/content/docs/index.mdxdocs/content/docs/meta.jsondocs/content/docs/overview/introduction.mdxdocs/content/docs/overview/meta.jsondocs/content/docs/overview/troubleshooting.mdx
✅ Files skipped from review due to trivial changes (1)
- docs/content/docs/index.mdx
🚧 Files skipped from review as they are similar to previous changes (3)
- docs/content/docs/developer/meta.json
- docs/content/docs/overview/meta.json
- docs/content/docs/api-reference/meta.json
| --- | ||
| title: "Troubleshooting Guide" | ||
| description: "Common issues and solutions for Voicebox" | ||
| --- |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify the current location of troubleshooting file and check if it matches the meta.json reference
echo "=== Current location of TROUBLESHOOTING files ==="
fd -i "troubleshooting" docs/content/
echo ""
echo "=== Contents of overview/meta.json showing expected 'troubleshooting' reference ==="
cat docs/content/docs/overview/meta.json 2>/dev/null || echo "File not found"
echo ""
echo "=== Check if troubleshooting.md exists in overview directory ==="
ls -la docs/content/docs/overview/troubleshooting* 2>/dev/null || echo "No troubleshooting file found in overview/"Repository: jamiepine/voicebox
Length of output: 789
Remove duplicate troubleshooting file — correct version already exists.
The troubleshooting page already exists at the correct location: docs/content/docs/overview/troubleshooting.mdx. The file being reviewed here (docs/content/docs/TROUBLESHOOTING.md) is a duplicate that should be deleted.
Delete the duplicate file:
rm docs/content/docs/TROUBLESHOOTING.md🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/content/docs/TROUBLESHOOTING.md` around lines 1 - 4, Delete the
duplicate file docs/content/docs/TROUBLESHOOTING.md and remove any references or
links pointing to it (e.g., in site navigation or README); ensure all references
instead point to the canonical page
docs/content/docs/overview/troubleshooting.mdx and update any import/route
entries that used TROUBLESHOOTING.md so the site uses the single correct
troubleshooting page.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/app/docs/`[[...slug]]/page.tsx:
- Line 26: The page uses page.data.lastModified for the lastUpdate prop but the
last-modified plugin isn’t configured, so add the plugin import (lastModified
from 'fumadocs-mdx/plugins/last-modified') and include lastModified() in the
defineConfig plugins array in your docs source config (where
defineConfig/defineDocs are used) so that page.data.lastModified is populated;
note the plugin uses Git commit history so ensure Git is available (avoid
shallow clones).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b428257f-7274-4fe2-b4ed-d8144d9fe4e4
📒 Files selected for processing (1)
docs/app/docs/[[...slug]]/page.tsx
| sha: 'main', | ||
| path: `docs/content/docs/${page.path}`, | ||
| }} | ||
| lastUpdate={page.data.lastModified} |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
How to enable lastModified in fumadocs-mdx source config?
💡 Result:
To enable lastModified in fumadocs-mdx source.config.ts, add the last-modified plugin:
// source.config.ts
import { defineConfig } from "fumadocs-mdx/config";
import lastModified from "fumadocs-mdx/plugins/last-modified";
export default defineConfig({
plugins: [lastModified()], // uses Git by default
});Then you can read it from page data as a Date:
const page = source.getPage(["..."]);
console.log(page.data.lastModified);Notes:
- It relies on your local Git history (Git must be installed; avoid shallow clones). [1]
- In MDX v14, the older
lastModifiedTimeoption was replaced by this plugin. [2]
Sources: [1] [2]
🏁 Script executed:
# Find fumadocs configuration files
fd -t f "source.config.ts" -o "source.config.js" -o "fumadocs.config.ts"Repository: jamiepine/voicebox
Length of output: 213
🏁 Script executed:
# Also search for any config file that might contain fumadocs setup
fd -t f "config" -e ts -e js | grep -E "(source|fumadocs)" | head -20Repository: jamiepine/voicebox
Length of output: 83
🏁 Script executed:
# Look for package.json to understand fumadocs setup
cat -n package.json | head -50Repository: jamiepine/voicebox
Length of output: 1892
🏁 Script executed:
# Inspect the source config file
cat -n docs/source.config.tsRepository: jamiepine/voicebox
Length of output: 758
🏁 Script executed:
# Check the page.tsx file to understand the context
cat -n docs/app/docs/[[...slug]]/page.tsx | head -50Repository: jamiepine/voicebox
Length of output: 1949
🏁 Script executed:
# Check the frontmatter schema to see if lastModified is defined there
rg "lastModified" docs/source.config.tsRepository: jamiepine/voicebox
Length of output: 44
🏁 Script executed:
# Check if lastModified is defined in the frontmatter schema
rg "lastModified" docs/ --type ts --type tsx -B 2 -A 2Repository: jamiepine/voicebox
Length of output: 89
🏁 Script executed:
# Check one of the actual documentation files to see what frontmatter is used
fd -t f ".mdx" docs/content/docs -o ".md" docs/content/docs | head -1 | xargs cat | head -30Repository: jamiepine/voicebox
Length of output: 187
🏁 Script executed:
# Find the source.ts or source configuration file
fd -t f "source" docs/Repository: jamiepine/voicebox
Length of output: 102
🏁 Script executed:
# Look for mdx files
fd -e mdx docs/Repository: jamiepine/voicebox
Length of output: 387
🏁 Script executed:
# Check the lib/source file referenced in page.tsx
cat -n docs/lib/source.ts 2>/dev/null || cat -n docs/lib/source.js 2>/dev/null || find docs -name "source.*" -type fRepository: jamiepine/voicebox
Length of output: 987
🏁 Script executed:
# Search for any lastModified or lastModifiedTime in the codebase
rg -i "lastmodified|lastmodifiedtime" docs/Repository: jamiepine/voicebox
Length of output: 138
🏁 Script executed:
# Check if there's a schema definition that might include lastModified
cat -n docs/source.config.tsRepository: jamiepine/voicebox
Length of output: 758
Add the last-modified plugin to enable lastModified in page data.
The lastModified field requires the fumadocs-mdx/plugins/last-modified plugin to be configured in docs/source.config.ts. Currently, it's missing, so page.data.lastModified will be undefined and lastUpdate will not display.
Add the plugin to your config:
source.config.ts
import {
defineConfig,
defineDocs,
frontmatterSchema,
metaSchema,
} from 'fumadocs-mdx/config';
import lastModified from 'fumadocs-mdx/plugins/last-modified';
export const docs = defineDocs({
dir: 'content/docs',
docs: {
schema: frontmatterSchema,
postprocess: {
includeProcessedMarkdown: true,
},
},
meta: {
schema: metaSchema,
},
});
export default defineConfig({
plugins: [lastModified()],
mdxOptions: {},
});The plugin uses Git commit history by default, so ensure Git is available and avoid shallow clones.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/app/docs/`[[...slug]]/page.tsx at line 26, The page uses
page.data.lastModified for the lastUpdate prop but the last-modified plugin
isn’t configured, so add the plugin import (lastModified from
'fumadocs-mdx/plugins/last-modified') and include lastModified() in the
defineConfig plugins array in your docs source config (where
defineConfig/defineDocs are used) so that page.data.lastModified is populated;
note the plugin uses Git commit history so ensure Git is available (avoid
shallow clones).
Migrate docs from Mintlify to Fumadocs
Ports the entire
docs/directory from Mintlify to Fumadocs (Next.js-based), using~/Projects/spacebot/docsas a reference implementation.What changed
Removed:
mint.json(Mintlify config)custom.css(Mintlify-specific styles)nixpacks.toml(Mintlify deployment config)overview/,api/,developer/,images/,logo/directories (old source locations)New project structure:
Key decisions
mdx-components.tsxprovides compatibility wrappers that map every Mintlify component (Card,CardGroup,Steps,Tab title="...",AccordionGroup,Note,Warning,Tip,Info,Check,Frame) to Fumadocs equivalentshsl(43, 52%, 50%))meta.jsonfilespublic/plans/and standalone.mdfiles left in place (not part of published docs)Stack
@tailwindcss/postcssBuild
Passes cleanly — 33 static pages generated. Run
bun run devfromdocs/to preview.Summary by CodeRabbit
Release Notes
New Features
Documentation
Chores