react-router.config.ts1.6 KBView on GitHub import { readdirSync } from 'node:fs';
import { join } from 'node:path';
import type { Config } from '@react-router/dev/config';
// Scan the blog posts directory at build time so each post is emitted as static
// HTML. Real HTML is required for AI agents (which don't execute JS) and gives
// search engines a faster, more reliable indexing path.
function getBlogPrerenderPaths(): string[] {
const postsDir = join(process.cwd(), 'app', '(full-width)', 'blog', 'posts');
try {
const slugs = readdirSync(postsDir)
.filter((f) => f.endsWith('.tsx'))
.map((f) => f.replace(/\.tsx$/, ''));
return ['/blog', ...slugs.map((slug) => `/blog/${slug}`)];
} catch (err) {
// In production, refuse to ship a /blog index with zero posts — almost
// always a wrong-cwd build. In dev/test, fall back so tooling keeps working.
if (process.env.NODE_ENV === 'production') {
throw new Error(
`[react-router.config] blog posts dir not found at ${postsDir} during production build. ` +
`This usually means the build is running from the wrong cwd. ` +
`Original error: ${err instanceof Error ? err.message : String(err)}`,
);
}
console.warn(
`[react-router.config] blog posts dir not found at ${postsDir} — only /blog will be prerendered.`,
err,
);
return ['/blog'];
}
}
export default {
ssr: false,
buildDirectory: 'build',
appDirectory: 'app',
routeDiscovery: {
mode: 'initial',
},
future: {
v8_viteEnvironmentApi: true,
},
prerender: getBlogPrerenderPaths(),
} satisfies Config;