We hand-roll our own server rendering (since Bun doesn't provide enough support for our use-cases yet) and hot reloading (which Bun does provide, but it's kinda wonky). Server rendering is better described by code snippets below. `build.ts` (only called for prod): ```ts const result = await build({ entrypoints: ['src/clientSideEntry.tsx'], ... }) const {jsPath, cssPath} = extractJSAndCSSPathFromResult(result) // we only have one js and css output await Bun.write('public/out/manifest.json', JSON.stringify({jsPath, cssPath})) ``` `server.ts` (`bun server.ts`, used for both dev and prod. Starts the server): ```tsx import app from './index.html' // ONLY used for dev mode. Duplicated html from Document.tsx that we use for prod server rendering (described later) let builtArtifacts if (isProd) { builtArtifacts = await Bun.file('public/out/manifest.json').json() } serve({ routes: { // In prod, server-render the full page. In dev, serve index.html directly for hot reloading. '/*': isProd ? async (req): Promise => { const authedUser = await getAuthUser(req.cookies) const initialProps = { authedUser } const fullJSX = await Document({ jsPath: builtArtifacts.jsPath, // Document.tsx below will render a script tag with this path cssPath: builtArtifacts.cssPath, // same initialProps, // Document.tsx will render a JSON script tag with this initialProps }) const fullHTML = renderToString(fullJSX) return new Response(fullHTML) } : app, // dev: serve index.html directly for Bun's hot reloading // Dev-only endpoint: the client fetches initialProps (including auth) via this API '/api/dev-initial-props': isProd ? new Response('Not found', { status: 404 }) : async (req) => { const initialAuthUser = await getAuthUser(req.cookies) return Response.json({ initialAuthUser, urlFromInitialServerRequest: new URL(req.url).searchParams.get('url') }) } } }) ``` `Document.tsx` (prod-only server-rendered HTML shell + OG tags): ```tsx function Document({ jsPath, cssPath, initialProps, parsedRoute }: Props) { const openGraphPreviewTags = await getOpenGraphPreviewTags(parsedRoute, ...) // server side rendering of OG tags return ( {/* ... */} {openGraphPreviewTags} {/* manually escape the initialProps JSON and put it in the script tag to be read by the JS entrypoint, clientSideEntry.tsx (well, its bundled name) */} {/* just like the good old times */} ```