# SolidJS Documentation System The SolidJS documentation system is a modern, full-stack web application built with SolidJS and SolidStart that serves comprehensive documentation for the Solid ecosystem. The project manages documentation for four distinct projects (SolidJS core, Solid Router, Solid Start, and Solid Meta) through a unified interface with multi-language support, advanced search capabilities, and LLM-friendly index generation for AI assistants. This documentation platform leverages Solid's fine-grained reactivity to provide a fast, responsive user experience with server-side rendering (SSR) for optimal performance and SEO. The system features an automated content collection pipeline that transforms MDX documentation files into navigable content trees, generates sitemaps, syncs content with OramaSearch for full-text search functionality, and produces LLM-optimized documentation indexes. Built on Vinxi and deployed to Netlify, the platform supports internationalization, custom theming through Kobalte SolidBase, and includes sophisticated navigation with collapsible sections and tab-based interfaces. Each of the four projects maintains separate navigation trees and flat entry lists, exposed through a unified virtual module system. ## Development Commands ### Start development server Start the local development server with hot module replacement at localhost:3000. The sync script runs automatically before starting to generate navigation data. ```bash pnpm dev ``` ### Build for production Build the production-ready application with sitemap generation, LLM index generation, and SSR prerendering. Includes 8GB memory optimization for large documentation sets spanning multiple projects. ```bash pnpm build ``` The build process executes: `pnpm sync && pnpm build:sitemap && pnpm build:llms && NODE_OPTIONS="--max-old-space-size=8192" vinxi build` ### Generate content collections Parse MDX files from src/routes and generate navigation trees and flat entry lists in .solid directory. Creates virtual modules for runtime consumption. ```bash pnpm sync ``` Expected output structure in `.solid/`: ``` .solid/ ├── tree.ts # Core navigation tree ├── flat-entries.ts # Core flat entries (TypeScript) ├── entriesList.js # Core flat entries (JavaScript for scripts) ├── solid-router-tree.ts # Router-specific tree ├── solid-router-flat-entries.ts # Router flat entries ├── solid-start-tree.ts # Start-specific tree ├── solid-start-flat-entries.ts # Start flat entries ├── solid-meta-tree.ts # Meta-specific tree ├── solid-meta-flat-entries.ts # Meta flat entries ├── tree-{locale}.ts # Localized trees (e.g., tree-pt-br.ts) └── flat-entries-{locale}.ts # Localized entries (e.g., flat-entries-pt-br.ts) ``` ### Sync search index Build the site and sync all HTML pages to OramaSearch index for full-text search capability. Requires ORAMA_PRIVATE_API_KEY and ORAMA_PRIVATE_INDEX_ID environment variables. ```bash pnpm sync:orama ``` ### Generate LLM-friendly documentation index Create a markdown-formatted index of all documentation pages optimized for AI assistants and LLMs. Outputs to public/llms.txt with links to all pages across all four projects. ```bash pnpm build:llms ``` This generates a structured markdown file with sections for SolidJS, SolidStart, Solid Router, and Solid Meta documentation. ## Content Collection System ### Define documentation structure Documentation pages are organized using `data.json` files that define the navigation hierarchy. Each directory can contain a data.json to specify page order and section titles. ```json { "title": "Basic Reactivity", "pages": [ "index.mdx", "create-signal.mdx", "create-effect.mdx", "create-memo.mdx" ] } ``` ### Create MDX documentation pages Documentation pages use MDX format with frontmatter metadata. Each page requires a title and can include optional fields like mainNavExclude and isDeprecated. ```mdx --- title: createSignal mainNavExclude: false isDeprecated: false --- # createSignal Signals are the most basic reactive primitive in SolidJS... ```tsx import { createSignal } from "solid-js" const [count, setCount] = createSignal(0) console.log(count()) // 0 setCount(5) console.log(count()) // 5 ``` ``` ### Build navigation tree programmatically The buildFileTree function recursively scans directories and MDX files to construct a hierarchical navigation structure from the filesystem. ```javascript import { buildFileTree } from './scripts/collections/build-file-tree.mjs' // Build complete navigation tree from src/routes const tree = await buildFileTree('src/routes') // Result structure: // { // type: "section", // title: "root", // pages: ["index.mdx", "quick-start.mdx", "concepts"], // children: [ // { // type: "markdown", // title: "Overview", // path: "/index", // slug: "index", // mainNavExclude: false, // isTranslated: true // } // ] // } ``` ### Generate flat entry lists Transform hierarchical navigation trees into flat arrays for search, sitemap generation, and navigation rendering. ```javascript import { createFlatEntryList } from './scripts/collections/create-flat-entry-list.mjs' const tree = { learn: [/* nested structure */], reference: [/* nested structure */] } const flatEntries = { learn: createFlatEntryList(tree.learn, []), reference: createFlatEntryList(tree.reference, []) } // Result: flat array of all pages // [ // { title: "Overview", path: "/index", mainNavExclude: false }, // { title: "Quick Start", path: "/quick-start", mainNavExclude: false } // ] ``` ## Application Configuration ### Configure SolidStart application The app.config.ts file defines the complete application configuration including virtual modules for multi-project content collections, markdown processing with Shiki syntax highlighting, package manager presets for npm/pnpm/yarn/bun/deno, and custom Vite plugins for documentation features. ```typescript import { defineConfig } from "@solidjs/start/config" import { createWithSolidBase, defineTheme } from "@kobalte/solidbase/config" // Import all project navigation data import tree from "./.solid/tree" import entries from "./.solid/flat-entries" import solidstartEntries from "./.solid/solid-start-flat-entries" import solidrouterEntries from "./.solid/solid-router-flat-entries" import solidMetaEntries from "./.solid/solid-meta-flat-entries" import solidrouterTree from "./.solid/solid-router-tree" import solidStartTree from "./.solid/solid-start-tree" import solidMetaTree from "./.solid/solid-meta-tree" // Collect all routes for prerendering const allEntries = [ entries.learn, entries.reference, solidstartEntries.learn, solidstartEntries.reference, solidrouterEntries.learn, solidrouterEntries.reference, solidMetaEntries.learn, solidMetaEntries.reference, ].flat(Infinity).map(x => x.path.replace(/\\/g, "/")) const theme = defineTheme({ componentsPath: import.meta.resolve("./src/solidbase-theme"), }) export default defineConfig( createWithSolidBase(theme)( { ssr: true, middleware: "src/middleware/index.ts", server: { preset: "netlify", prerender: { crawlLinks: true, autoSubfolderIndex: false, failOnError: true, routes: allEntries, ignore: [/\{getPath\}/, /.*?emojiSvg\(.*/], }, }, vite: { plugins: [docsData(), heroCodeSnippet()], }, }, { title: "Solid Docs", description: "Documentation for SolidJS, the signals-powered UI framework", editPath: "https://github.com/solidjs/solid-docs/edit/main/:path", markdown: { expressiveCode: { themes: ["min-light", "material-theme-ocean"], themeCssSelector: (theme) => `[data-theme="${theme.type}"]`, frames: false, styleOverrides: { twoSlash: { cursorColor: "var(--twoslash-cursor)", }, }, }, toc: { minDepth: 2, }, packageManagers: { presets: { npm: { install: "npm i :content", "install-dev": "npm i :content -D", run: "npm run :content", exec: "npx :content", }, pnpm: { install: "pnpm i :content", "install-dev": "pnpm i :content -D", run: "pnpm :content", exec: "pnpx :content", }, yarn: { install: "yarn add :content", "install-dev": "yarn add :content -D", run: "yarn :content", exec: "yarn dlx :content", }, bun: { install: "bun i :content", "install-dev": "bun i :content -d", run: "bun run :content", exec: "bunx :content", }, deno: { install: "deno add npm::content", run: "deno run :content", exec: "dpx :content", }, }, }, }, } ) ) ``` ### Create virtual modules for navigation data Vite plugins expose navigation data as virtual modules that can be imported throughout the application without file I/O at runtime. The system creates two key virtual modules: one for multi-project navigation data and another for hero code snippet syntax highlighting. ```typescript // Virtual module for multi-project documentation navigation function docsData() { const virtualModuleId = "solid:collection" const resolveVirtualModuleId = "\0" + virtualModuleId return { name: virtualModuleId, resolveId(id: string) { if (id === virtualModuleId) { return resolveVirtualModuleId } }, async load(id: string) { if (id === resolveVirtualModuleId) { return ` export const coreEntries = ${JSON.stringify(entries, null, 2)} export const routerEntries = ${JSON.stringify(solidrouterEntries, null, 2)} export const startEntries = ${JSON.stringify(solidstartEntries, null, 2)} export const metaEntries = ${JSON.stringify(solidMetaEntries, null, 2)} export const coreTree = ${JSON.stringify(tree, null, 2)} export const routerTree = ${JSON.stringify(solidrouterTree, null, 2)} export const startTree = ${JSON.stringify(solidStartTree, null, 2)} export const metaTree = ${JSON.stringify(solidMetaTree, null, 2)} ` } }, } } // Virtual module for hero code snippet with syntax highlighting function heroCodeSnippet() { const virtualModuleId = "solid:hero-code-snippet" const resolveVirtualModuleId = "\0" + virtualModuleId return { name: virtualModuleId, resolveId(id: string) { if (id === virtualModuleId) { return resolveVirtualModuleId } }, async load(id: string) { if (id === resolveVirtualModuleId) { const snippet = await readFile( "./src/ui/layout/hero-code-snippet.code", "utf-8" ) const highlightedCode = await codeToHtml(snippet.trim(), { lang: "tsx", theme: "material-theme-ocean", }) return `export const highlightedCode = \`${highlightedCode}\`` } }, } } // Usage in components: import { coreTree, coreEntries, routerTree, startTree, metaTree } from "solid:collection" import { highlightedCode } from "solid:hero-code-snippet" ``` ## Navigation Components ### Render main navigation with tabs The MainNavigation component provides a tab-based interface switching between "Learn" and "Reference" documentation sections with collapsible subsections. ```tsx import { MainNavigation } from "~/ui/layout/main-navigation" function Layout() { const tree = { learn: [ { title: "Concepts", path: "/concepts", children: [ { title: "Signals", path: "/concepts/signals", mainNavExclude: false } ] } ], reference: [ { title: "Basic Reactivity", path: "/reference/basic-reactivity", children: [ { title: "createSignal", path: "/reference/basic-reactivity/create-signal" } ] } ] } return ( ) } ``` ### Handle internationalization The i18n system provides translation support using context and route-based locale detection for multi-language documentation. ```tsx import { I18nProvider, useI18n } from "~/i18n/i18n-context" function App() { return ( ) } function NavigationLabel() { const i18n = useI18n() return (

{i18n.t("main.nav.tab.learn")}

{i18n.t("main.nav.tab.reference")}

) } ``` ## LLM Integration ### Generate LLM-friendly documentation index The llms-gen.js script creates a markdown-formatted index of all documentation pages optimized for AI assistants. This enables LLMs to quickly discover and reference documentation across all four Solid projects. ```javascript import entries from "../.solid/entriesList.js" import startEntries from "../.solid/solid-start-flat-entries.js" import routerEntries from "../.solid/solid-router-flat-entries.js" import metaEntries from "../.solid/solid-meta-flat-entries.js" import fs from "fs" const generateLinkArray = (routes) => { return routes.map((route) => ({ title: route.title, url: `https://docs.solidjs.com${route.path}`, })) } const formatSection = (title, links) => { const formattedLinks = links .map((link) => `- [${link.title}](${link.url})`) .join("\n") return `## ${title}\n\n${formattedLinks}` } // Collect links from all projects const coreLinks = [ ...generateLinkArray(entries.learn), ...generateLinkArray(entries.reference), ] const startLinks = [ ...generateLinkArray(startEntries.learn), ...generateLinkArray(startEntries.reference), ] const routerLinks = [ ...generateLinkArray(routerEntries.learn), ...generateLinkArray(routerEntries.reference), ] const metaLinks = [ ...generateLinkArray(metaEntries.learn), ...generateLinkArray(metaEntries.reference), ] // Generate structured markdown output const output = `# SolidJS Documentation > Solid is a JavaScript library built around signals. These are the documentation for the main official projects. ${formatSection("SolidJS", coreLinks)} ${formatSection("SolidStart", startLinks)} ${formatSection("Solid Router", routerLinks)} ${formatSection("Solid Meta", metaLinks)} ` fs.writeFileSync("public/llms.txt", output, { encoding: "utf-8" }) ``` The generated `public/llms.txt` file provides a comprehensive index of documentation with direct links, organized by project for easy navigation by AI assistants and developers. ## Search Integration ### Sync documentation to OramaSearch The sync-orama script crawls built HTML files, extracts content using OramaCrawly, and uploads to OramaSearch index for full-text search. ```javascript import { readFileSync } from "node:fs" import { globSync } from "glob" import { generalPurposeCrawler } from "@orama/crawly" import "dotenv/config" const ORAMA_PRIVATE_API_KEY = process.env.ORAMA_PRIVATE_API_KEY const ORAMA_PRIVATE_INDEX_ID = process.env.ORAMA_PRIVATE_INDEX_ID const baseURL = new URL("../dist", import.meta.url).pathname const HTMLFiles = globSync("**/*.html", { cwd: baseURL }) const pagesToIndex = HTMLFiles.flatMap((file) => { const pageContent = readFileSync(new URL(`../dist/${file}`, import.meta.url), "utf8") const productionDocsURL = `https://docs.solidjs.com/${file.replace(/\.html$/, "")}` return { ...generalPurposeCrawler(productionDocsURL, pageContent, { parseCodeBlocks: false, })[0], contentWithCode: generalPurposeCrawler(productionDocsURL, pageContent)?.[0]?.content, } }) // Empty index await fetch( `https://api.oramasearch.com/api/v1/webhooks/${ORAMA_PRIVATE_INDEX_ID}/snapshot`, { method: "POST", headers: { "Content-Type": "application/json", authorization: `Bearer ${ORAMA_PRIVATE_API_KEY}`, }, body: JSON.stringify([]), } ) // Upload in batches of 25 const batchSize = 25 for (let i = 0; i < pagesToIndex.length; i += batchSize) { const batch = pagesToIndex.slice(i, i + batchSize) await fetch( `https://api.oramasearch.com/api/v1/webhooks/${ORAMA_PRIVATE_INDEX_ID}/notify`, { method: "POST", headers: { "Content-Type": "application/json", authorization: `Bearer ${ORAMA_PRIVATE_API_KEY}`, }, body: JSON.stringify({ upsert: batch }), } ) } // Deploy updated index await fetch( `https://api.oramasearch.com/api/v1/webhooks/${ORAMA_PRIVATE_INDEX_ID}/deploy`, { method: "POST", headers: { authorization: `Bearer ${ORAMA_PRIVATE_API_KEY}` }, } ) ``` ### Generate XML sitemap Generate sitemap.xml from collected documentation entries for search engine optimization and discoverability. ```javascript import { SitemapStream, streamToPromise } from "sitemap" import { Readable } from "stream" import entries from "../.solid/entriesList.js" import fs from "fs" const generateLinkArray = (routes) => { return routes.reduce((acc, route) => { return [ ...acc, { url: route, priority: route === "/" ? 1 : 0.7, changefreq: "weekly" }, ] }, []) } const referencesRoutes = entries.reference.map(({ path }) => path) const learnRoutes = entries.learn.map(({ path }) => path) const links = [ ...generateLinkArray(learnRoutes), ...generateLinkArray(referencesRoutes), ] const stream = new SitemapStream({ hostname: "https://docs.solidjs.com/" }) const sitemap = await streamToPromise(Readable.from(links).pipe(stream)) fs.writeFileSync("public/sitemap.xml", sitemap, { encoding: "utf-8" }) ``` ## Middleware and Routing ### Handle legacy route redirects Middleware intercepts requests and redirects legacy documentation URLs to the new structure for backward compatibility. ```typescript import { createMiddleware } from "@solidjs/start/middleware" import { handleLegacyRoutes } from "./legacy-routes-redirect" export default createMiddleware({ onRequest: [handleLegacyRoutes], }) // Example legacy routes redirect implementation export function handleLegacyRoutes(event) { const url = new URL(event.request.url) const legacyRoutes = { "/api/createSignal": "/reference/basic-reactivity/create-signal", "/api/createEffect": "/reference/basic-reactivity/create-effect", "/guides/getting-started": "/quick-start", } if (legacyRoutes[url.pathname]) { return Response.redirect( new URL(legacyRoutes[url.pathname], url.origin), 301 ) } } ``` ### Configure file-based routing SolidStart uses file-based routing where each .mdx or .tsx file in src/routes becomes a route automatically. ```tsx // src/app.tsx import { Router } from "@solidjs/router" import { SolidBaseRoot } from "@kobalte/solidbase/client" import { FileRoutes } from "@solidjs/start/router" export default function App() { return ( ) } // File structure maps to routes: // src/routes/index.mdx -> / // src/routes/quick-start.mdx -> /quick-start // src/routes/concepts/signals.mdx -> /concepts/signals // src/routes/[...404].tsx -> catch-all 404 page ``` ## Summary The SolidJS documentation system demonstrates modern web development patterns for building scalable, performant documentation sites. Key use cases include serving as a comprehensive reference for the Solid ecosystem with API documentation, guides, and tutorials across four distinct projects (SolidJS Core, Solid Router, Solid Start, and Solid Meta); providing multi-language support for international developers; offering fast, SEO-friendly content delivery through SSR and static prerendering; and generating LLM-optimized documentation indexes for AI assistant integration. The system's automated content pipeline ensures documentation stays synchronized while the integration with OramaSearch delivers powerful full-text search capabilities across all projects. Integration patterns showcase SolidJS best practices including virtual modules for compile-time data injection across multiple projects, fine-grained reactivity for navigation state management, custom Vite plugins for hero code snippet highlighting, and component composition with Kobalte for accessible UI elements. The build pipeline combines Node.js scripts for content processing with Vinxi for bundling and deployment, memory-optimized builds supporting 8GB allocation for large documentation sets, comprehensive package manager presets (npm, pnpm, yarn, bun, deno), and middleware for legacy URL redirects. Developers can extend this system by adding new documentation sections in src/routes, creating additional project-specific navigation trees, customizing themes through Kobalte SolidBase configuration, or integrating additional search providers by modifying the sync scripts. The architecture separates content concerns from presentation logic through a multi-layered virtual module system, making it straightforward to adapt for other documentation needs while maintaining support for multiple related projects within a unified platform.