Bases de datos
En qué adaptadores de base de datos de Content puede desplegarse un sitio duxt, cuáles se han verificado y la única regla que mantiene la capa apartada.
Content v3 guarda sus páginas en SQL y puede hablar con cinco bases de datos. duxt no tiene opinión sobre ninguna de ellas: el adaptador es una decisión de tu despliegue, Content ya es dueño de esa superficie, y el único cometido de la capa es no estorbar.
Esta página dice hasta dónde se ha comprobado eso realmente, en vez de insinuarlo.
Dos bases de datos, no una
Casi toda sorpresa en este terreno nace de leer «la base de datos» como una sola cosa. Content mantiene dos, y tienen vidas y tipos distintos.
content._localDatabase | content.database | |
|---|---|---|
| Qué contiene | La caché de análisis — una fila por archivo, tal como se analizó | Las colecciones que el sitio consulta |
| Cuándo existe | Durante una compilación, en .data/content/ | En el servidor desplegado |
| Qué adaptadores | sqlite o d1, y nada más | Cualquiera de los cinco de abajo |
| Quién la lee | duxt report, el validador de compilación, el mapa de redirecciones | queryCollection(), en una petición |
La consecuencia es la parte útil: elegir un adaptador cambia la base de datos desplegada y nada más. Un sitio desplegado sobre PostgreSQL sigue compilando a través de una caché de análisis SQLite local, porque el propio tipo que Content da a esa caché no admite otra cosa.
.data/content/contents.sqlite, en el directorio donde compilas. Es una caché:
borrarla cuesta una compilación, nunca contenido.
Los adaptadores
content.database.type en tu propio nuxt.config.ts. duxt no lo fija para
ningún sitio; dejarlo sin fijar te da el valor por defecto de Content.
| Adaptador | Necesita instalado | duxt |
|---|---|---|
sqlite (por defecto) | Nada en Node 24 — se lee con el node:sqlite integrado | Verificado en CI en cada commit |
d1 | Nada; un binding de Cloudflare | Verificado — este sitio funciona así |
libsql | @libsql/client | Verificado en CI |
postgresql | pg | Verificado en CI |
pglite | @electric-sql/pglite | Sin probar |
«Verificado en CI» significa una compilación del propio sitio de este
repositorio contra ese adaptador, seguida de una comprobación de todos los
endpoints que leen la base de datos en tiempo de ejecución y de una ejecución de
duxt report. El workflow es .github/workflows/adapters.yml; se ejecuta en
cada pull request, de modo que las filas de arriba no puedan dejar de ser
ciertas en silencio.
No se sabe de nada que falle en él. Tampoco se sabe de nada que funcione — no ha tenido una ejecución propia, así que se marca como sin probar en lugar de dar a entender que funciona. Si despliegas sobre él, a la capa le gustaría saber cómo fue.
No se instala ningún driver SQLite nativo
El valor por defecto de Content es better-sqlite3, un addon nativo que compila
con node-gyp. duxt pone content.experimental.sqliteConnector en 'native', que
usa en su lugar el node:sqlite integrado en Node 24 y no necesita paquete
alguno — por eso la instalación de la capa no arrastra ningún compilador y por
eso la compilación quiere Node 24.
Heredas ese ajuste al extender la capa, y nunca deberías ver un aviso de
obsolescencia por él. Lo que Content marcó como obsoleto es el antiguo
experimental.nativeSqlite; duxt tiene una prueba que lee las declaraciones del
propio Content y hace fallar las comprobaciones de la capa si algo de lo que fija
bajo content.experimental lleva una etiqueta @deprecated, así que el próximo
renombrado aterriza en este repositorio y no en tu registro de compilación.
Qué se ejecuta durante la compilación, y nunca en el servidor
Tres partes de la capa leen directamente del sistema de archivos. Las tres se ejecutan dentro de una compilación, que es justo lo que hace posible un Worker — o cualquier destino sin disco.
| Qué hace | Cuándo | |
|---|---|---|
content-cache.ts | Abre la caché de análisis con node:sqlite y la pone en modo WAL | Compilación |
modules/git-meta.ts | Ejecuta git log sobre el checkout para «última actualización» y colaboradores | Compilación |
duxt report | Lee esa misma caché desde la línea de órdenes | Junto a la compilación |
Ninguna es alcanzable desde una petición, y a ninguna le afecta tu adaptador:
leen la caché SQLite local descrita arriba, que existe diga lo que diga
content.database.
La regla
La capa nunca lee la base de datos de Content en tiempo de ejecución por otra vía que
queryCollection().
En eso consiste toda la compatibilidad de adaptadores de duxt. En el momento en que una ruta de servidor abriera la base de datos por su cuenta, la capa empezaría a dar por supuestos un sistema de archivos y un dialecto SQLite — y fallaría en tu despliegue, no en las pruebas de este repositorio.
Se impone en lugar de prometerse: tests/content-database.test.ts falla si
cualquier archivo bajo server/ o app/ importa un driver de base de datos, y
mantiene cerrada la lista de archivos de tiempo de compilación que pueden abrir
uno, de modo que uno nuevo debe justificarse por escrito antes de entrar.
Qué lee la base de datos en una petición
Todo lo demás que sirve un sitio duxt ya es un archivo cuando se sirve. Esto no lo es, y esto es lo que prueba la matriz de adaptadores:
…/page.md— la fuente Markdown detrás de «Ver como Markdown» y de los enlaces de traspaso./mcp— todas las herramientas, ya que cada una responde desde una colección./llms.txty/llms-full.txt— ambos recorren todas las colecciones./rss.xml, una vez lo configuras.
Una página también está en esa lista en un despliegue renderizado en servidor, y fuera de ella en uno prerenderizado. Consulta Desplegar un sitio para saber cuál de los dos tienes.