@@ -273,9 +273,52 @@ async function buildSSG(options: BuildSSGOptions = {}): Promise<void> {
273273 ( r ) => r . type === 'page' && ! r . special && r . path . includes ( ':' ) ,
274274 ) ;
275275
276+ log . info (
277+ `Dynamic routes found: ${ dynamicRoutes . length } ${
278+ dynamicRoutes . length > 0 ? ` (${ dynamicRoutes . map ( ( r ) => r . path ) . join ( ', ' ) } )` : ''
279+ } `,
280+ ) ;
281+
276282 if ( dynamicRoutes . length > 0 ) {
277- const { renderDSD } = await import ( '../render-dsd.js' ) ;
278- const { wrapInDocument } = await import ( '../ssr-handler.js' ) ;
283+ // Use server.ssrLoadModule() to ensure adapter registration is visible.
284+ // Direct import() creates a separate module graph where
285+ // installLitAdapter()'s registerAdapter() call is not visible.
286+ const renderDsdMod = await server . ssrLoadModule (
287+ '@lessjs/core/render-dsd' ,
288+ ) as Record < string , unknown > ;
289+ const ssrHandlerMod = await server . ssrLoadModule (
290+ '@lessjs/core/less-runtime' ,
291+ ) as Record < string , unknown > ;
292+ const renderDSDFn = renderDsdMod . renderDSD as typeof import ( '../render-dsd.js' ) . renderDSD ;
293+ const wrapInDocumentFn = ssrHandlerMod
294+ . wrapInDocument as typeof import ( '../ssr-handler.js' ) . wrapInDocument ;
295+
296+ // Initialize @lessjs /blog data store if present.
297+ // The blog plugin's buildStart() ran in Phase 1's Vite instance,
298+ // but Phase 3 creates a fresh SSR server with its own module graph.
299+ // We need to re-initialize so getPosts() returns data.
300+ let blogOptions : { contentDir ?: string ; basePath ?: string } | undefined ;
301+ try {
302+ const blogOptsPath = join ( root , '.less' , 'blog-options.json' ) ;
303+ if ( existsSync ( blogOptsPath ) ) {
304+ const raw = readFileSync ( blogOptsPath , 'utf-8' ) ;
305+ blogOptions = JSON . parse ( raw ) ;
306+ }
307+ } catch {
308+ // Non-fatal
309+ }
310+
311+ try {
312+ const blogModule = await server . ssrLoadModule ( '@lessjs/blog' ) as Record < string , unknown > ;
313+ if ( typeof blogModule . initBlogData === 'function' ) {
314+ await ( blogModule . initBlogData as ( opts ?: unknown ) => Promise < unknown > ) ( blogOptions ) ;
315+ const postCount = ( blogModule . getPosts as ( ) => unknown [ ] ) ( ) . length ;
316+ log . info ( `Blog data store initialized: ${ postCount } post(s) for SSG dynamic routes` ) ;
317+ }
318+ } catch {
319+ // @lessjs /blog not available — non-fatal, dynamic routes may not use it
320+ log . debug ( '@lessjs/blog not found — skipping blog data initialization' ) ;
321+ }
279322
280323 for ( const route of dynamicRoutes ) {
281324 const paramNames = [ ...route . path . matchAll ( / : ( [ ^ / ] + ) / g) ] . map ( ( m ) => m [ 1 ] ) ;
@@ -328,12 +371,12 @@ async function buildSSG(options: BuildSSGOptions = {}): Promise<void> {
328371
329372 try {
330373 // Render the component with route params as props
331- const html = await renderDSD ( tagName , ComponentClass , params , {
374+ const html = await renderDSDFn ( tagName , ComponentClass , params , {
332375 route : resolvedPath ,
333376 source : route . filePath ,
334377 } ) ;
335378
336- const fullHtml = wrapInDocument ( html , {
379+ const fullHtml = wrapInDocumentFn ( html , {
337380 title : options . html ?. title || 'LessJS' ,
338381 lang : options . html ?. lang || 'en' ,
339382 headExtras : options . headExtras || '' ,
0 commit comments