solidjs/solid-start
SolidStart, the Solid app framework
Builds full-stack web applications with server-side rendering using SolidJS
Development starts with file-based routing where developers create route components in the src/routes directory. During build, Vite compiles both client and SSR bundles. The nitroV2Plugin intercepts the SSR bundle, validates it has exactly one entry point, then passes it to Nitro which generates server artifacts for the target deployment platform. At runtime, the server renders pages to HTML, and the client hydrates using the mount() function to attach SolidJS reactivity to the pre-rendered markup.
Under the hood, the system uses 2 feedback loops, 2 data pools, 2 control points to manage its runtime behavior.
A 6-component fullstack. 307 files analyzed. Data flows through 6 distinct pipeline stages.
How Data Flows Through the System
Development starts with file-based routing where developers create route components in the src/routes directory. During build, Vite compiles both client and SSR bundles. The nitroV2Plugin intercepts the SSR bundle, validates it has exactly one entry point, then passes it to Nitro which generates server artifacts for the target deployment platform. At runtime, the server renders pages to HTML, and the client hydrates using the mount() function to attach SolidJS reactivity to the pre-rendered markup.
- Route discovery — FileRoutes scans src/routes directory for .tsx files and automatically generates route definitions based on file paths and naming conventions [Route files → Route definitions]
- Dual bundle compilation — Vite builds separate client and SSR bundles — client bundle for browser hydration, SSR bundle for server-side rendering with Node.js compatibility [Route Component → SSR Bundle]
- SSR bundle validation — nitroV2Plugin.generateBundle validates the SSR output has exactly one entry point by iterating through bundle chunks and checking isEntry flags, storing the entry file name [SSR Bundle → Validated entry point]
- Server artifact generation — createNitro uses the validated SSR bundle and NitroConfig to build deployment-ready server artifacts with proper asset handling and routing [NitroConfig → Server artifacts]
- Server-side rendering — Nitro server receives HTTP requests, executes route components server-side to generate HTML with embedded state, and serves complete pages [HTTP request → Rendered HTML]
- Client hydration — Browser loads client bundle, mount() function attaches SolidJS reactivity to server-rendered DOM, StartClient initializes routing and meta tag management [Rendered HTML → Hydrated application]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
packages/start/src/client/StartClient.tsxJSX component that wraps the application root and handles client-side hydration, router initialization, and meta tag management
Created during mount(), receives app structure from SSR, initializes client-side routing and reactivity
packages/start-nitro-v2-vite-plugin/src/index.tsConfiguration object with preset: string, compatibilityDate: string, logLevel: number, and build settings for server deployment
Defined during Vite build process, consumed by Nitro to generate server artifacts and deployment bundles
packages/start-nitro-v2-vite-plugin/src/index.tsRollup.OutputBundle containing server-side chunks with entry point marked as isEntry: true, fileName: string, and associated assets
Generated by Vite during SSR build phase, validated for single entry point, then passed to Nitro for server artifact creation
apps/fixtures/basic/src/routes/index.tsxSolidJS functional component returning JSX.Element, typically with Title, metadata, and page content
Auto-discovered by FileRoutes based on file system structure, rendered server-side and hydrated client-side
apps/fixtures/basic/src/app.tsxJSX component with Router wrapper containing MetaProvider, navigation elements, and FileRoutes for route resolution
Entry point for both SSR and client rendering, sets up routing context and meta tag management
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
SSR bundle contains exactly one entry point with isEntry: true flag set by Vite, and no other chunks have isEntry: true
If this fails: If Vite generates multiple entry points or fails to mark any chunk as entry, the build fails with cryptic error messages rather than gracefully handling multi-entry scenarios or providing clear debugging info
packages/start-nitro-v2-vite-plugin/src/index.ts:generateBundle
Dynamic import of './_component' resolves to a valid SolidJS component that exports a default function returning JSX
If this fails: If the imported component exports something other than a JSX-returning function (like a class, object, or async function), clientOnly wrapper will fail at runtime during hydration with no type checking
apps/tests/src/routes/client-only/index.tsx:clientOnly
Location.port exists in browser environment and getRequestEvent().request.url contains valid port in server environment when making fetch requests
If this fails: If running in environments without location.port (some web workers) or behind proxies that strip port info, the fetch URL becomes malformed leading to network errors
apps/fixtures/experiments/src/routes/index.tsx:fetch
Client environment build must complete before SSR environment build, and both must finish before Nitro configuration is resolved
If this fails: If SSR build starts before client assets are available or Nitro tries to reference client chunks before they exist, the build process produces incorrect asset references or missing files
packages/start-nitro-v2-vite-plugin/src/index.ts:buildApp
Global ssrBundle and ssrEntryFile variables persist between generateBundle and buildApp phases without being overwritten by concurrent builds
If this fails: In parallel build scenarios or rapid dev rebuilds, race conditions cause wrong bundle data to be used, resulting in servers that reference non-existent entry points or stale code
packages/start-nitro-v2-vite-plugin/src/index.ts:ssrBundle
FileRoutes component scans a src/routes directory structure and automatically maps file paths to route patterns using filesystem conventions
If this fails: If src/routes doesn't exist, contains non-component files, or uses naming patterns that don't match FileRoutes expectations, routing silently fails with no pages accessible
apps/fixtures/basic/src/app.tsx:FileRoutes
MountableElement el exists in DOM and is empty or safe to replace when render() is called
If this fails: If el is null, already has event listeners, or contains form data, mount() either crashes with null reference or destroys user data without warning
packages/start/src/client/spa/index.tsx:mount
Server function hello() can be called immediately during component initialization before SSR context is fully established
If this fails: If getRequestEvent() returns null during early SSR phases, the server function crashes with property access on undefined, breaking page rendering
apps/fixtures/experiments/src/routes/index.tsx:hello
All lazy-loaded components (Lazy, LazyGlob, LazyLink, etc.) export default functions that return valid JSX and don't throw during initialization
If this fails: If any lazy component has side effects, missing exports, or throws on import, the Suspense boundary shows loading state indefinitely while errors are silently swallowed
apps/fixtures/css/src/routes/index.tsx:lazy imports
Hard-coded compatibilityDate '2024-11-19' remains valid for Nitro's API contract and feature set across all deployment targets
If this fails: As Nitro evolves, this fixed date may trigger deprecated behavior warnings or break compatibility with newer deployment platforms that require updated compatibility settings
packages/start-nitro-v2-vite-plugin/src/index.ts:compatibilityDate
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
File system-based route definitions mapped to component imports, updated during build time
Vite-managed compilation cache for both client and SSR bundles, persisted across development rebuilds
Feedback Loops
- Development hot reload (cache-invalidation, balancing) — Trigger: File system changes in src/routes. Action: Vite rebuilds affected bundles and updates route registry. Exit: Stable file system state.
- Build validation cycle (self-correction, balancing) — Trigger: Multiple or missing entry points in SSR bundle. Action: nitroV2Plugin throws error and halts build process. Exit: Valid single entry point found.
Delays
- Bundle compilation (compilation, ~Variable based on project size) — Development server startup and production build time
- Client hydration (async-processing, ~Network dependent) — Time between initial page render and interactive application
Control Points
- Build environment (env-var) — Controls: Whether to build for development or production with different optimization levels. Default: process.env.NODE_ENV
- Nitro preset (architecture-switch) — Controls: Deployment target (node-server, vercel, netlify, etc.) affecting build output format. Default: node-server
Technology Stack
Reactive UI framework providing fine-grained reactivity and JSX components
Build tool handling development server, hot reload, and production bundling for both client and SSR
Server framework that transforms SSR bundles into deployment-ready artifacts for various platforms
Primary development language providing type safety across the framework and applications
Monorepo package manager with workspace support for managing dependencies across multiple packages
Underlying bundler used by Vite for production builds, providing chunk analysis and bundle validation
Testing framework for unit tests integrated with Vite's build pipeline
End-to-end testing framework for validating full application workflows
Key Components
- mount (gateway) — Attaches the SolidJS application to a DOM element, handling the transition from server-rendered HTML to client-side reactivity
packages/start/src/client/index.tsx - StartClient (orchestrator) — Coordinates client-side hydration, router initialization, and meta tag synchronization after SSR
packages/start/src/client/StartClient.tsx - nitroV2Plugin (transformer) — Vite plugin that intercepts SSR bundle generation, validates entry points, and configures Nitro server build with proper asset handling
packages/start-nitro-v2-vite-plugin/src/index.ts - FileRoutes (registry) — Automatically discovers route components based on file system structure and creates routing configuration
@solidjs/start/router - clientOnly (loader) — Wraps components to prevent server-side rendering, ensuring they only execute in the browser
@solidjs/start - createNitro (factory) — Creates Nitro server instance with specified configuration for deployment target and build settings
nitropack
Package Structure
Core SolidStart framework providing client hydration, routing, and server integration
Vite plugin that integrates Nitro server framework for SolidStart deployment
Official SolidStart marketing website with documentation and examples
Test suite with unit and E2E tests for SolidStart features
Collection of example applications demonstrating different SolidStart patterns
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Fullstack Repositories
Frequently Asked Questions
What is solid-start used for?
Builds full-stack web applications with server-side rendering using SolidJS solidjs/solid-start is a 6-component fullstack written in TypeScript. Data flows through 6 distinct pipeline stages. The codebase contains 307 files.
How is solid-start architected?
solid-start is organized into 4 architecture layers: Core Framework, Build Tooling, Applications, Development Tools. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through solid-start?
Data moves through 6 stages: Route discovery → Dual bundle compilation → SSR bundle validation → Server artifact generation → Server-side rendering → .... Development starts with file-based routing where developers create route components in the src/routes directory. During build, Vite compiles both client and SSR bundles. The nitroV2Plugin intercepts the SSR bundle, validates it has exactly one entry point, then passes it to Nitro which generates server artifacts for the target deployment platform. At runtime, the server renders pages to HTML, and the client hydrates using the mount() function to attach SolidJS reactivity to the pre-rendered markup. This pipeline design reflects a complex multi-stage processing system.
What technologies does solid-start use?
The core stack includes SolidJS (Reactive UI framework providing fine-grained reactivity and JSX components), Vite (Build tool handling development server, hot reload, and production bundling for both client and SSR), Nitro (Server framework that transforms SSR bundles into deployment-ready artifacts for various platforms), TypeScript (Primary development language providing type safety across the framework and applications), pnpm (Monorepo package manager with workspace support for managing dependencies across multiple packages), Rollup (Underlying bundler used by Vite for production builds, providing chunk analysis and bundle validation), and 2 more. A focused set of dependencies that keeps the build manageable.
What system dynamics does solid-start have?
solid-start exhibits 2 data pools (Route Registry, Bundle Cache), 2 feedback loops, 2 control points, 2 delays. The feedback loops handle cache-invalidation and self-correction. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does solid-start use?
4 design patterns detected: File-based routing, Islands architecture, Universal build pipeline, Progressive hydration.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.