# Future: Server-Side Rendering (SSR) Support > **Status**: Planning > **Priority**: Medium > **Complexity**: High > **Prerequisites**: React 19 migration, HTTP node implementation ## Executive Summary OpenNoodl has substantial existing SSR infrastructure that was developed but never shipped by the original Noodl team. This document outlines a path to completing and exposing SSR as a user-facing feature, giving users the choice between client-side rendering (CSR), server-side rendering (SSR), and static site generation (SSG). ## Why SSR Matters ### The Problem with Pure CSR Currently, Noodl apps are entirely client-side rendered: 1. **SEO Limitations**: Search engine crawlers see an empty `
` until JavaScript executes 2. **Social Sharing**: Link previews on Twitter, Facebook, Slack, etc. show blank or generic content 3. **First Paint Performance**: Users see a blank screen while the runtime loads and initializes 4. **Core Web Vitals**: Poor Largest Contentful Paint (LCP) scores affect search rankings ### What SSR Provides | Metric | CSR | SSR | SSG | |--------|-----|-----|-----| | SEO | Poor | Excellent | Excellent | | Social Previews | Broken | Working | Working | | First Paint | Slow | Fast | Fastest | | Hosting Requirements | Static | Node.js Server | Static | | Dynamic Content | Real-time | Real-time | Build-time | | Build Complexity | Low | Medium | Medium | ## Current State in Codebase ### What Already Exists The original Noodl team built significant SSR infrastructure: **SSR Server (`packages/noodl-viewer-react/static/ssr/`)** - Express server with route handling - `ReactDOMServer.renderToString()` integration - Browser API polyfills (localStorage, fetch, XMLHttpRequest, requestAnimationFrame) - Result caching via `node-cache` - Graceful fallback to CSR on errors **SEO API (`Noodl.SEO`)** - `setTitle(value)` - Update document title - `setMeta(key, value)` - Set meta tags - `getMeta(key)` / `clearMeta()` - Manage meta tags - Designed specifically for SSR (no direct window access) **Deploy Infrastructure** - `runtimeType` parameter supports `'ssr'` value - Separate deploy index for SSR files (`ssr/index.json`) - Commented-out UI code showing intended deployment flow **Build Scripts** - `getPages()` API returns all routes with metadata - `createIndexPage()` generates HTML with custom meta tags - `expandPaths()` for dynamic route expansion - Sitemap generation support ### What's Incomplete - SEO meta injection not implemented (`// TODO: Inject Noodl.SEO.meta`) - Page router issues (`// TODO: Maybe fix page router`) - No UI for selecting SSR deployment - No documentation or user guidance - Untested with modern component library - No hydration verification ## Proposed User Experience ### Option 1: Project-Level Setting Add rendering mode selection in Project Settings: ``` Rendering Mode: ○ Client-Side (CSR) - Default, works with any static host ○ Server-Side (SSR) - Better SEO, requires Node.js hosting ○ Static Generation (SSG) - Best performance, pre-renders at build time ``` **Pros**: Simple mental model, single source of truth **Cons**: All-or-nothing, can't mix approaches ### Option 2: Deploy-Time Selection Add rendering mode choice in Deploy popup: ``` Deploy Target: [Static Files (CSR)] [Node.js Server (SSR)] [Pre-rendered (SSG)] ``` **Pros**: Flexible, same project can deploy differently **Cons**: Could be confusing, settings disconnect ### Option 3: Page-Level Configuration (Recommended) Add per-page rendering configuration in Page Router settings: ``` Page: /blog/{slug} Rendering: [SSR ▼] Page: /dashboard Rendering: [CSR ▼] Page: /about Rendering: [SSG ▼] ``` **Pros**: Maximum flexibility, matches real-world needs **Cons**: More complex, requires smarter build system ### Recommended Approach **Phase 1**: Start with Option 2 (Deploy-Time Selection) - simplest to implement **Phase 2**: Add Option 1 (Project Setting) for default behavior **Phase 3**: Consider Option 3 (Page-Level) based on user demand ## Technical Implementation ### Phase 1: Complete Existing SSR Infrastructure **1.1 Fix Page Router for SSR** - Ensure `globalThis.location` properly simulates browser location - Handle query parameters and hash fragments - Support Page Router navigation events **1.2 Implement SEO Meta Injection** ```javascript // In ssr/index.js buildPage() const result = htmlData .replace('
', `
${output1}
`) .replace('', `${generateMetaTags(noodlRuntime.SEO.meta)}`); ``` **1.3 Polyfill Audit** - Test all visual nodes in SSR context - Identify browser-only APIs that need polyfills - Create SSR compatibility matrix for nodes ### Phase 2: Deploy UI Integration **2.1 Add SSR Option to Deploy Popup** ```typescript // DeployToFolderTab.tsx