Boltdocs 3.1.0 — Modo Turbo, MDX con Sätteri y CSS Crítico con Zig

Jesús AlcaláJesús Alcalá
Boltdocs 3.1.0 — Modo Turbo, MDX con Sätteri y CSS Crítico con Zig

3.1.0 trae la bandera --turbo: un compilador MDX impulsado por Rust, extracción de CSS crítico compilada con Zig y un modo parser de pasada única. Primera fase del camino hacia builds 4x más rápidos.

Esta se trata de los cimientosLink

3.0.0 fue sobre velocidad pura — el parser nativo. 3.1.0 es sobre la siguiente capa: el modo turbo. Esta es la Fase 1 del Proyecto Nitro, y cambia lo que corre por debajo cuando construyes.

Info
Note

Una bandera experimental --turbo que reemplaza el compilador MDX por Sätteri (Rust), Beasties por extracción de CSS crítico compilada con Zig, y activa un modo parser de pasada única. Este es el primer paso hacia builds 4x más rápidos.

Info
Note

Build output optimizado: Beasties de inlining de CSS crítico ha sido desactivado por defecto, reduciendo el HTML total en ~7.3 MB. El bug de duplicación del locale por defecto también ha sido corregido, ahorrando ~8 MB adicionales. Combinado, el output del build es ahora ~60% más pequeño.


--turbo — Modo Build ExperimentalLink

La nueva bandera --turbo activa tres optimizaciones nativas en un solo comando:

pnpm boltdocs build --turbo

O configúralo permanentemente con una variable de entorno:

BOLTDOCS_TURBO=true pnpm boltdocs build

Qué cambia por debajo:

ComponenteSin --turboCon --turbo
Compilación MDX@mdx-js/rollup + plugins remark/rehype JSSätteri (Rust) + plugins nativos
CSS críticoNinguno (CSS externo solamente)@bdocs/zig-critters (Zig/WASM)
ParserModo multi-pasadaPasada única con buffer compartido
Info
Note

Esta bandera es experimental. Puedes encontrar problemas de compatibilidad de CSS por zig-critters o diferencias de compilación MDX por Sätteri. Si algo falla, elimina --turbo y reporta el problema — tu build estándar no se ve afectado.


Sätteri MDX — Compilación Impulsada por RustLink

El cambio más grande en modo --turbo es el compilador MDX. Sätteri reemplaza @mdx-js/rollup con un procesador basado en Rust, construido sobre pulldown-cmark con extensiones MDX.

El pipeline:

  1. El parser Rust (satteri-pulldown-cmark) parsea Markdown/MDX a un AST asignado en arena
  2. Los plugins MDAST corren sobre la arena (remark-meta, remark-gfm)
  3. El AST se convierte a HAST
  4. Los plugins HAST corren (rehype-slug, rehype-shiki)
  5. mdxToJs() compila el HAST a salida JSX

Benchmarks del sitio de documentación de Boltdocs (241 páginas):

MétricaDefault (@mdx-js/rollup)Turbo (Sätteri)Diferencia
Build Time97.3s43.9s2.2x más rápido
SSG Total98.7s45.1s54% más rápido
Salida JavaScript10.5 MB8.4 MB20% menos
Salida HTML25.65 MB15.51 MB40% menos

Sätteri también incluye tres sub-plugins nativos que reemplazan los equivalentes estándar de remark/rehype:

  • satteriRemarkMetaPlugin — captura las meta strings de las cercas de código en hProperties.metastring
  • satteriRehypeSlugPlugin — agrega atributos id a los encabezados
  • satteriRehypeShikiPlugin — resaltado de sintaxis Shiki via visitante HAST

Comportamiento de fallbackLink

Si Sätteri falla al compilar un archivo, automáticamente vuelve a @mdx-js/rollup con plugins básicos (remark-gfm, remark-frontmatter, rehype-slug). Tu build no se rompe — simplemente no es turbo para ese archivo.

Limitación conocida: compatibilidad con plugins legacyLink

Sätteri usa una arena Rust para los nodos HAST. Los plugins estándar de unified/remark/rehype que mutan nodos en su lugar no funcionan — Sätteri requiere un patrón de retorno-para-reemplazar. Si usas plugins personalizados via remarkPlugins o rehypePlugins en tu configuración, pueden no aplicarse en modo turbo. La capa de adaptador detecta esto y muestra un warning.

Por ahora, el modo turbo funciona mejor para sitios con MDX estándar (bloques de código, tablas GFM, frontmatter). Los sitios con muchos plugins personalizados deben usar el compilador estándar.


@bdocs/zig-critters — CSS Crítico Compilado con ZigLink

Beasties extrae CSS crítico cargando tu HTML y CSS, emparejando selectores, e inlineando solo las reglas que aplican above the fold. Funciona — pero está escrito en JavaScript.

@bdocs/zig-critters es una reescritura completa en Zig, compilada a WebAssembly. Mismo algoritmo, velocidad nativa.

Cómo funciona:

  1. Carga el binario WASM pre-compilado en el primer uso
  2. Codifica tu HTML y CSS en la memoria lineal de WASM
  3. Parsea CSS a reglas, parsea HTML a una lista plana de elementos
  4. Empareja selectores contra elementos, marca reglas no usadas
  5. Serializa solo las reglas críticas de vuelta a JS

El resultado se inyecta como un tag <style data-zig-critters>...</style> antes de </head>.

Qué soportaLink

  • Contenedores @media y @supports — se mantienen si alguna regla hija coincide
  • @keyframes — tres estrategias: critical (solo las usadas), all, none
  • @font-face — inline opcional via inline_fonts
  • Reglas @property — siempre se mantienen
  • Directivas de include/exclude basadas en comentarios
  • Minificación de CSS (habilitada por defecto)

Limitación conocida: compatibilidad de CSSLink

zig-critters elimina pseudo-clases y pseudo-elementos al emparejar (comportamiento equivalente a Beasties). Esto significa que :hover, :focus y selectores dependientes del viewport se emparejan solo contra su elemento base. Algunos casos bordeos con cadenas de selectores complejas pueden producir CSS crítico diferente al de Beasties.

Si notas problemas de estilos en modo turbo, intenta eliminar --turbo para confirmar que es un issue de zig-critters, luego reportalo con una reproducción.


Modo Parser de Pasada ÚnicaLink

El parser nativo en Zig ya corre 5-6x más rápido que el antiguo parser JS. En modo turbo, cambia a un algoritmo de pasada única:

  • Modo normal: parseDoc() — dos pasadas (una para frontmatter/headings, otra para texto plano)
  • Modo turbo: parseDocSinglePass() — una pasada con un ParseContext buffer compartido

Misma salida, menos asignación de memoria. El modo de pasada única genera encabezados, texto plano y contenido en un solo escaneo con estilo de arena.


Feature Flags y BorradoresLink

Controla qué páginas son visibles en cada entorno sin cambios de código ni builds condicionales.

BorradoresLink

Marca cualquier página como borrador en el frontmatter:

---
title: Próxima Función
draft: true
---

Las páginas en borrador se excluyen automáticamente de los builds de producción. En desarrollo, los borradores son visibles por defecto. Controla la visibilidad via config:

export default defineConfig({
  drafts: {
    visible: false,              // Ocultar en todos los entornos
    environments: ['development', 'staging'],  // O por entorno
  },
})

O usa la variable de entorno BOLTDOCS_DRAFTS=true forzar la visibilidad.

Feature FlagsLink

Define feature flags en tu config:

export default defineConfig({
  featureFlags: {
    'new-dashboard': true,           // Siempre visible
    'beta-api': 'development',       // Solo en desarrollo
    'experimental-search': false,    // Siempre oculto
  },
})

Luego marca las páginas con flags requeridos:

---
title: Nuevo Dashboard
featureFlags:
  - new-dashboard
  - beta-api
---

La página solo se renderiza cuando todos los flags declarados están activos. Perfecto para lanzamientos progresivos, pruebas A/B u ocultar herramientas internas de producción.

Info
Próximamente

Los feature flags se integrarán con el plugin Ask AI en v3.2.0 para habilitar respuestas contextuales basadas en funciones habilitadas.


Optimizaciones del Build OutputLink

Beasties Desactivado — Por Qué?Link

Beasties estaba habilitado por defecto, extrayendo CSS "crítico" e inlineandolo en cada página HTML como tags <style>. El problema: Beasties no tiene conciencia del viewport — no usa un navegador headless. Simplemente empareja selectores CSS contra el DOM y clasifica cualquier regla que coincida con cualquier elemento como "crítica."

Con Tailwind CSS, casi cada clase de utilidad se usa en algún lugar de la página. Esto significa que Beasties inlineó casi todo el bundle CSS (~37 KB) en cada página. A través de 246 páginas, eso es 7.3 MB de CSS duplicado — 75x de bloat sobre el archivo CSS real de 99 KB.

Consideré dos alternativas:

  1. Agregar inteligencia de viewport a Beasties — Esto requeriría ejecutar un navegador headless durante el build para determinar qué reglas CSS están realmente above-the-fold. Funciona, pero hace el build significativamente más lento (Beasties ya es el paso más lento del pipeline).

  2. Desactivar Beasties completamente — Las páginas cargan CSS via un solo tag <link> externo. El navegador lo cachea después de la primera carga. Sin tags <style> inlineados, sin CSS duplicado, sin ralentización del build.

Elegí la opción 2. El archivo CSS es solo 99 KB y se comprime bien con gzip. Los navegadores modernos manejan stylesheets externos eficientemente — la tasa de aciertos de caché entre páginas es excelente.

Info
Note

Diferencia en modo turbo: En modo --turbo, @bdocs/zig-critters (Zig/WASM) maneja la extracción de CSS crítico. Es órdenes de magnitud más rápido que Beasties y puede extraer inteligentemente solo el CSS verdaderamente crítico. Si necesitas inlining de CSS crítico para despliegues sensibles al rendimiento, usa --turbo.

Corrección de Locale DuplicadoLink

Anteriormente, generateI18nFallbacks() creaba copias con prefijo de locale del contenido del locale por defecto. Para un sitio con locales en (por defecto) y es, cada página en inglés existía dos veces:

  • /docs/api/cli — el original
  • /docs/en/api/cli — una copia idéntica

Esto resultó en 74 archivos HTML duplicados totalizando ~8 MB de espacio desperdiciado. La corrección omite la generación de rutas de fallback para el locale por defecto — su contenido ya existe a nivel raíz.

ResultadosLink

MétricaAntesDespuésAhorro
HTML output (total)25.4 MB~10.1 MB~15.3 MB (60%)
Tamaño por página (promedio)~217 KB~180 KB~37 KB por página
Páginas duplicadas74074 archivos eliminados

Otros detallesLink

  • Visibilidad de tiempos de plugins — el build turbo ahora reporta tiempos por plugin en la salida del build, para que veas exactamente dónde se pasa el tiempo
  • Sätteri lazy-loaded — el plugin Sätteri se importa dinámicamente en el primer uso, no al iniciar. Si no usas --turbo, no hay sobrecarga
  • Separación de caché — Sätteri y el compilador MDX estándar usan namespaces de caché separados (v6-fallback vs v3). Cambiar entre modos turbo y no-turbo no corrompe los transforms cacheados
  • Fallback de Beasties — si el binario WASM de zig-critters no existe, Beasties toma el control con un warning. Tu build nunca falla por un binario faltante
  • crossorigin duplicado corregido — el regex que agrega crossorigin a los links de stylesheet ahora evita duplicar el atributo cuando ya está presente
  • Integración con PostHog — soporte integrado para PostHog. Configura via integrations.analytics.posthog con tu clave API del proyecto, y el snippet de PostHog se inyecta automáticamente. Soporta nube de la UE, grabación de sesión y autocapture (desactivado por defecto)

ActualizaciónLink

Sin breaking changes. La bandera --turbo es optativa — tu comando de build existente funciona exactamente igual.

Para probar el modo turbo:

pnpm boltdocs build --turbo

Si tienes problemas, elimina la bandera. El build estándar no cambia.


Qué SigueLink

La Fase 2 de Nitro ya está en progreso:

  • FileStore shardeado — reemplazando la caché monolítica de rutas con shards por archivo
  • Caché por ruta + parches delta — cambiar un archivo no invalidará todas las rutas
  • HMR delta de frontmatter — editar un título no recargará el navegador
  • Worker threads para MDX — transforms MDX en paralelo entre núcleos del CPU
  • Mapa de dependencias de código cliente — reconstruir solo las páginas afectadas por un cambio CSS

Instala o actualiza:

pnpm add boltdocs@latest

Revisa la documentación completa para explorar todo lo nuevo.

Last updated on July 27, 2026