import { sentryHandleError } from '~/lib/sentry'; /** * Using our conditional Sentry implementation instead of direct import * This avoids loading Sentry in development environments */ import type { AppLoadContext } from '~/lib/remix-types'; import { RemixServer } from '@remix-run/react'; import { isbot } from 'isbot'; import { renderToString } from 'react-dom/server'; import { renderHeadToString } from 'remix-island'; import { Head } from './root'; import { themeStore } from '~/lib/stores/theme'; export const handleError = sentryHandleError; export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: any, _loadContext: AppLoadContext, ) { // Check if the request is from a bot const userAgent = request.headers.get('user-agent'); const isBot = isbot(userAgent || ''); // Create the HTML string const markup = renderToString(); // If this is a bot request, we can wait for all data to be ready if (isBot) { /* * In Cloudflare, we had: * await readable.allReady; * * For Vercel, we could do additional processing for bots * such as waiting for all data fetching to complete. * Future enhancement: add mechanism to ensure all data is loaded * before rendering for bots (important for SEO) */ console.log(`Bot detected: ${userAgent}`); } // @ts-ignore - Fix for incompatible EntryContext types between different remix versions const head = renderHeadToString({ request, remixContext, Head }); // Build full HTML response const html = ` ${head}
${markup}
`; responseHeaders.set('Content-Type', 'text/html'); responseHeaders.set('Cross-Origin-Embedder-Policy', 'require-corp'); responseHeaders.set('Cross-Origin-Opener-Policy', 'same-origin'); return new Response(html, { headers: responseHeaders, status: responseStatusCode, }); }