Open
Conversation
Replace Astro/Starlight with a RedwoodSDK-based docs site using content-collections for MDX processing. Adds app shell (Document, Sidebar, pages), component stubs for MDX rendering, and Cloudflare Workers configuration.
…ibility @content-collections/mdx uses new Function() at runtime which is blocked by Cloudflare Workers. Switch to @mdx-js/rollup which compiles MDX to React components at build time via Vite. - Add @mdx-js/rollup plugin with remark-frontmatter support - Alias Astro imports to local stub components via Vite resolve.alias - Move MDX stub components into components/mdx/ with barrel index - Simplify content-collections to metadata-only (no body compilation) - Use import.meta.glob to eagerly load MDX components in DocPage
…l icons Remove the top bar in favor of a unified sidebar containing the logo, search input (sticky top), scrollable navigation, and Discord/GitHub icons (sticky bottom).
…cs-ui Replace @content-collections and custom sidebar/layout with fumadocs ecosystem: - Add fumadocs-core, fumadocs-mdx, fumadocs-ui dependencies - Create source.config.ts and source loader for fumadocs-mdx - Add meta.json files for sidebar page ordering - Create custom FrameworkProvider for RedwoodSDK compatibility - Wrap app with fumadocs RootProvider (theme disabled for CSP) - Add scan-entries file for RedwoodSDK directive discovery - Rewrite DocPage to use DocsLayout/DocsPage/DocsBody - Adapt MDX components to fumadocs equivalents (Callout, Cards, Tabs, Steps) - Fix code block language identifiers in email docs - Remove numbered file prefixes (ordering via meta.json) - Delete unused Sidebar.tsx, sidebar.ts, content-collections.ts, Code.tsx
… open/close Replace manual useState toggle with @base-ui/react Collapsible component for sidebar folders. Add height and opacity transitions, chevron rotation via group data attributes, and switch className conditionals to clsx.
…c logos Switch Discord and GitHub icons to inline SVGs, removing the lucide-react dependency. Use theme-aware logo images from the public folder.
…w shim Replace fumadocs DocsLayout component with a plain grid layout since the custom Sidebar handles all navigation. Remove the scroll-into-view-noop workaround and its Vite alias as it's no longer needed.
- Remove patch-history.ts (unnecessary — rwsdk re-renders full RSC tree on navigation)
- Remove fumadocs-scan-entries.ts workaround, use forceClientPaths in vite config instead
- Switch DocPage to standard fumadocs page.data.body pattern
- Use fumadocs DocsLayout component in DocsLayoutWrapper
- Use navigate() from rwsdk/client instead of createElement("a").click()
- Add prefetch support to Link component
- Fix non-null assertions on requestInfo with proper guards
- Align Referrer-Policy with documented recommendation (strict-origin-when-cross-origin)
- Add Secure flag to theme cookie
- Add except() error handler before middleware in worker
- Add OG/Twitter meta tags and favicon to Document
- Add error handlers to initClient for better debugging
… docs - Add X-Frame-Options: DENY header to match documented recommendation - Remove unused Code compatibility shim from MDX barrel export - Remove unused Code imports from database.mdx and realtime.mdx - Fix RouteMiddleware import path in security.mdx (rwsdk/router not rwsdk/worker) - Replace legacy rwsdk() API with defineApp() pattern in security.mdx
… Analytics Match the old Astro docs head 1:1 — adds canonical URLs, og:locale, og:site_name, og:url, richer OG/Twitter descriptions, dynamic sitemap.xml route, robots.txt, Simple Analytics tracking, and updates CSP accordingly.
Avoid documentation copy changes on this branch.
Enable the fumadocs lastModified plugin to inject git-based timestamps, and render EditOnGitHub + PageLastUpdate components on every doc page.
Add MobileNav component using Base UI Dialog for responsive navigation. Fix forceClientPaths with extglob patterns to exclude framework-specific files importing uninstalled optional peer deps (next, waku, react-router, @tanstack/react-router). Exclude mdx/mdx.server from forceClientPaths to fix CodeBlock 'use' error caused by registerClientReference receiving a plain object instead of a React component. Add directiveScanBlocklist to prevent re-adding excluded files.
Consolidate base-ui and fumadocs-ui patterns into a single entry and update comments to reflect that the issue is build-time MDX imports rather than import.meta.glob visibility.
…, and polish UI - Add /llms.txt and /llms-full.txt routes for LLM-friendly documentation - Enable includeProcessedMarkdown in fumadocs source config - Remove ErrorBoundary (incompatible with rwsdk SSR) and EditOnGitHub/PageLastUpdate - Fix SSR pathname context for correct active sidebar highlighting - Add per-page SEO meta tags (og:title, twitter:title, etc.) - Improve light mode support for Badge component - Validate YouTube embed IDs, fix sidebar keys, harden CSP for data: URIs - Rename Provider to AppProviders, remove unused links.ts
Member
|
Duuude this is incredible! Thank you! |
Wire up full-text search using Fumadocs' createFromSource with Orama. The search index is built server-side on the Worker and queried via /api/search. DefaultSearchDialog provides Cmd/Ctrl+K hotkey, result grouping by page, and keyboard navigation. Search trigger buttons are added to both desktop sidebar and mobile nav.
Replace fumadocs search layer (which depends on @radix-ui/react-dialog and next-themes) with native Orama indexing on the Worker and a custom @base-ui/react Dialog on the client. - Rewrite /api/search to build Orama index from source.getPages() structured data (page, heading, and content entries) - Replace SearchDialog with own SearchProvider context, Cmd+K listener, and fetch-based search with debouncing - Update provider to wrap children in SearchProvider instead of passing search config to fumadocs RootProvider - Update Sidebar to use useSearch from our context
…ialog crash The fumadocs RootProvider automatically wraps children in its own SearchProvider (which lazy-loads DefaultSearchDialog depending on @radix-ui/react-dialog) unless search.enabled is explicitly false. This was silently breaking the render tree and preventing our custom SearchProvider context from working.
Replace manual Dialog + useState approach with base-ui's Autocomplete
component inside a Dialog, following the COSS command palette pattern:
- Autocomplete.Root with open, inline, filter={null} (server-side
search), autoHighlight="always", keepHighlight
- Autocomplete.Input for the search field
- Autocomplete.List with render function for results
- Autocomplete.Item with onClick for navigation
- Autocomplete.Empty for loading/empty states
- Dialog.Viewport for proper centering
Drop the broken context-based approach. SearchCommand now follows the COSS command palette pattern: Dialog.Root wraps Dialog.Trigger (the search button itself) + Dialog.Portal (the popup), exactly like MobileNav already does. No external context or provider needed. - SearchCommand is fully self-contained: own state, trigger, portal - Desktop sidebar gets enableShortcut for Cmd+K - Remove SearchProvider from AppProviders (no longer needed)
- Add fumadocs keyframe animations (fd-dialog-in/out) to search popup - Add backdrop blur to search dialog overlay - Extract base-ui ScrollArea component to components/ui/ - Replace fumadocs ScrollArea with base-ui ScrollArea in Sidebar - Match search input sizing to sidebar button - Add mono font to Esc button and fix ⌘ glyph vertical alignment
…em navigation Switch to @orama/plugin-qps for proximity-based ranking, return truncated body content for text results with heading breadcrumbs, add match highlighting, and fix Autocomplete item click navigation.
Remove debug console.log, fix unused variable, use non-global regex for HighlightMatch test(), and run prettier across all changed files.
Consolidate duplicated icon button class strings into buttonVariants() helper and move 7 inline SVG icon definitions into a shared Icon.tsx module, reducing boilerplate across Sidebar, SearchDialog, CopyMarkdownButton, and ThemeToggle.
Use <Button variant="ghost" /> via Base UI's render prop for Dialog.Trigger and Dialog.Close, and directly for CopyMarkdownButton. Keeps buttonVariants() export for <a> elements.
Button now accepts a render prop to swap the underlying element,
matching Base UI's convention. Sidebar links use
<Button render={<a />} /> instead of buttonVariants().
Replace hand-rolled render prop logic with Base UI's Button component which provides render prop support, prop merging, and accessibility out of the box.
…av from right Move the logo and search icon into the always-visible sticky header on mobile, and change the navigation drawer to slide in from right-to-left instead of left-to-right.
Replace stateful Base UI Switch with a plain button driven by Tailwind dark: variants. Set the dark class server-side via Sec-CH-Prefers-Color-Scheme client hint, falling back to a blocking script only when the preference is unknown. Remove data-theme attribute and initialTheme prop drilling.
Member
|
This is progressing wonderfully! |
…ions Replace Expressive Code meta syntax (mark, ins, del, word highlights) with native Shiki inline annotations across 18 MDX files. Add minimal custom transformer for features without native equivalents: collapse, withOutput, and footnotes (--- delimited code block footers). Remove frame="none" support (unnecessary with Shiki/fumadocs).
…migration issues
- Implement withOutput in custom Shiki transformer: splits code blocks on
first empty line into command (with $ prompt) and output sections, with
copy-to-clipboard only copying the command
- Fix Response.redirect word highlight (Shiki splits across tokens) by
using line highlight instead
- Fix initClientNavigation() word highlight by dropping parentheses
- Remove > prefix from storage.mdx withOutput block (broke bash tokenizer)
- Add nativeButton={false} to Button components rendering as <a> elements
Map the warm parchment/charcoal light mode and "Zip" dark mode palette from the main site onto fumadocs CSS variables. Add Inter and JetBrains Mono via Google Fonts with CSP allowlisting.
…ine numbers - Remove Playfair Display, use Inter for all text - Remove duplicate @tailwindcss/typography plugin conflicting with fumadocs - Fix search highlight using stale text-brand-orange token - Use baige for light mode card/secondary backgrounds - Use dark-panel for dark mode cards, dark-secondary for callout accents - Remove box-shadow from code blocks and callouts - Right-align code block line numbers - Tighten hr spacing to 1em
2dc4fc6 to
e1baae1
Compare
…ports - Replace all 51 Astro package imports (@astrojs/starlight/components, starlight-package-managers, astro-embed) across 35 MDX files with direct imports from @/app/components/mdx - Merge duplicate import lines where files had multiple Astro imports - Remove Astro alias entries from vite.config.mts - Add @/ path alias to vite config (mirrors tsconfig, needed since rwsdk doesn't use vite-tsconfig-paths) - Add module-stub.ts to alias unused fumadocs optional peer deps (flexsearch, @takumi-rs/image-response) that crash rwsdk's client barrel when eagerly loaded - Update comments to better explain forceClientPaths and directiveScanBlocklist
Match the previous Astro docs behavior where code blocks for js, javascript, ts, typescript, css, tsx, and jsx automatically show line numbers without needing explicit `lineNumbers` meta.
… fixes Add unit tests for parseRanges, parseMeta, and parseInlineMarkdown. Refactor parseMeta to use simpler matching, export testable functions, remove unused Image Optimization sidebar entry, and fix realtime link.
…rn statements - Add nonce attribute to dark-mode inline script so it passes CSP in production - Replace hardcoded localhost:4321 URL with relative path in sending-email guide - Add missing return statements to WelcomeEmail code examples in email-templates guide
…ge styling Add `experimental` frontmatter field to schema and render a caution badge inline with the page title when set. Fix Badge component to accept `type` prop (used in MDX) as alias for `variant`, update styling with more x-padding, less border radius, and vertical alignment.
Member
|
@joefairburn This looks like it's almost ready to merge!? |
Contributor
Author
|
@peterp - yep, it's in a good place and it's definitely feeling like an improvement over the current docs. always more we can do, but it can be iterated on! |
Member
|
This looks ready to merge! Gonna test it out locally and then I'll ship it, thanks so much for doing thsi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates the docs site from Astro/Starlight to RedwoodSDK, so the documentation itself runs on the same framework it documents.
The previous Astro site was a static build. This rewrite makes the docs a real RedwoodSDK application — server-rendered with React Server Components, deployed as a Cloudflare Worker, using the same router and patterns developers will find in the guides. fumadocs provides the documentation-specific primitives (sidebar, TOC, MDX processing, page layouts) on top of rwsdk's runtime.
Why fumadocs?
fumadocs is the best-in-class documentation framework in the React ecosystem — it powers the docs for shadcn/ui, Better Auth, and Zod. It was chosen because it provides many of the features and components that Astro/Starlight did — sidebar navigation, TOC extraction, MDX processing, docs page layouts — which significantly reduces the overhead of the migration.
It also serves as a showcase: integrating a mature, popular library like fumadocs demonstrates how straightforward it is to bring existing React ecosystem tools into an rwsdk application.
What changed
astro.config.mjs, Starlight config,custom.css,content.config.tsall deletedworker.tsxentry point withdefineApp,Document.tsxshell, route-based rendering viarender/layout/route@astrojs/starlight/componentsimports to our shim components (Badge,Steps,Tabs, etc.) so existing MDX content works without mass-editing<title>, Open Graph/Twitter meta tags,robots.txt, XML sitemapX-Frame-Options, CSP,X-Content-Type-Optionsvia middleware/llms.txt(index) and/llms-full.txt(full markdown content) endpoints using fumadocs'getText('processed')What's NOT in this PR
Test plan
localhost:5173/sitemap.xml,/robots.txt,/llms.txt,/llms-full.txtreturn correct content