O Content v3 guarda as suas páginas em SQL e sabe falar com cinco bases de
dados. O duxt não tem opinião sobre nenhuma delas: o adaptador é uma decisão da
tua implementação, o Content já é dono dessa superfície, e a única função da
camada é não atrapalhar.

Esta página diz até onde isso foi de facto verificado, em vez de o insinuar.

## Duas bases de dados, não uma

Quase todas as surpresas nesta área nascem de ler «a base de dados» como uma só
coisa. O Content mantém duas, e têm tempos de vida e tipos diferentes.

| | `content._localDatabase` | `content.database` |
| :--- | :--- | :--- |
| O que guarda | A cache de análise — uma linha por ficheiro, tal como analisado | As coleções que o site consulta |
| Quando existe | Durante uma compilação, em `.data/content/` | No servidor implementado |
| Que adaptadores | `sqlite` ou `d1`, e mais nada | Qualquer um dos cinco abaixo |
| Quem a lê | `duxt report`, o validador de compilação, o mapa de redirecionamentos | `queryCollection()`, num pedido |

A consequência é a parte útil: **escolher um adaptador muda a base de dados
implementada e mais nada.** Um site implementado em PostgreSQL continua a
compilar através de uma cache de análise SQLite local, porque o próprio tipo que
o Content dá a essa cache não admite outra coisa.

::callout{type="info" title="Onde vive a cache"}
`.data/content/contents.sqlite`, no diretório onde compilas. É uma cache —
apagá-la custa uma compilação, nunca conteúdo.
::

## Os adaptadores

`content.database.type` no teu próprio `nuxt.config.ts`. O duxt não o define para
nenhum site; deixá-lo por definir dá-te o valor por omissão do Content.

| Adaptador | Precisa de instalado | duxt |
| :-------- | :------------------- | :--- |
| `sqlite` (por omissão) | Nada no Node 24 — lido pelo `node:sqlite` integrado | Verificado em CI em cada commit |
| `d1` | Nada; um binding da Cloudflare | Verificado — este site corre nele |
| `libsql` | `@libsql/client` | Verificado em CI |
| `postgresql` | `pg` | Verificado em CI |
| `pglite` | `@electric-sql/pglite` | **Por testar** |

«Verificado em CI» significa uma compilação do próprio site deste repositório
contra esse adaptador, seguida de uma sondagem de todos os pontos de acesso que
leem a base de dados em tempo de execução e de uma execução do `duxt report`. O
workflow é `.github/workflows/adapters.yml`; corre em cada pull request, para que
as linhas acima não possam deixar de ser verdadeiras em silêncio.

::callout{type="warning" title="O PGlite está por testar, não avariado"}
Não se conhece nada de errado nele. Também não se conhece nada de certo — não
teve uma execução dedicada, por isso está marcado como por testar em vez de se
dar a entender que funciona. Se o usares numa implementação, a camada gostaria de
saber como correu.
::

### Não é instalado nenhum controlador SQLite nativo

O valor por omissão do Content é o `better-sqlite3`, um addon nativo que compila
através do node-gyp. O duxt define `content.experimental.sqliteConnector` como
`'native'`, que usa em vez disso o `node:sqlite` integrado no Node 24 e não
precisa de pacote nenhum — razão pela qual a instalação da camada não arrasta um
compilador e pela qual a compilação quer o Node 24.

Herdas essa definição ao estender a camada e nunca deverias ver um aviso de
descontinuação por causa dela. O que o Content descontinuou foi o antigo
`experimental.nativeSqlite`; o duxt tem um teste que lê as próprias declarações
do Content e faz falhar as verificações da camada assim que algo que ela define
sob `content.experimental` traz uma etiqueta `@deprecated` — a próxima mudança de
nome aterra neste repositório em vez de aterrar no teu registo de compilação.

## O que corre durante a compilação, e nunca no servidor

Três partes da camada leem diretamente do sistema de ficheiros. As três correm
dentro de uma compilação, que é precisamente o que torna possível um Worker — ou
qualquer alvo sem disco.

| | O que faz | Quando |
| :--- | :--- | :--- |
| `content-cache.ts` | Abre a cache de análise com `node:sqlite` e põe-na em modo WAL | Compilação |
| `modules/git-meta.ts` | Corre `git log` sobre a cópia de trabalho para «última atualização» e contribuidores | Compilação |
| `duxt report` | Lê essa mesma cache a partir da linha de comandos | Ao lado da compilação |

Nenhuma delas é alcançável a partir de um pedido, e nenhuma é afetada pelo teu
adaptador: leem a cache SQLite local descrita acima, que existe diga o que disser
`content.database`.

## A regra

> A camada nunca lê a base de dados do Content em tempo de execução por outra via
> que não `queryCollection()`.

É nisto que consiste toda a compatibilidade de adaptadores do duxt. No momento em
que uma rota de servidor abrisse a base de dados por si, a camada passaria a
pressupor um sistema de ficheiros e um dialeto SQLite — e falharia na tua
implementação, não nos testes deste repositório.

É imposta em vez de prometida: `tests/content-database.test.ts` falha se qualquer
ficheiro sob `server/` ou `app/` importar um controlador de base de dados, e
mantém fechada a lista de ficheiros de tempo de compilação que podem abrir um,
pelo que um novo tem de ser justificado por escrito antes de entrar.

### O que lê a base de dados num pedido

Tudo o resto que um site duxt serve já é um ficheiro quando é servido. Isto não
é, e é isto que a matriz de adaptadores sonda:

- **`…/page.md`** — a fonte Markdown por trás de «Ver como Markdown» e das
  ligações de entrega.
- **`/mcp`** — todas as ferramentas, já que cada uma responde a partir de uma
  coleção.
- **`/llms.txt` e `/llms-full.txt`** — ambos percorrem todas as coleções.
- **`/rss.xml`**, assim que o configurares.

Uma página está igualmente nessa lista numa implementação renderizada no
servidor, e fora dela numa pré-renderizada. Ver
[Implementar um site](/guides/deploy-a-site) para saber qual das duas tens.