Saltar al contenido
duxt

Hooks

El único hook de compilación que duxt emite, qué te entrega y por qué solo hay uno.

duxt emite un hook. Es un hook de compilación de Nuxt, se dispara una vez por compilación y te entrega todas las páginas del sitio como registros de búsqueda planos.

import { defineNuxtModule } from '@nuxt/kit';
import type { DuxtSearchRecord } from '@kirchdev/duxt/search-records';

export default defineNuxtModule({
  setup(_options, nuxt) {
    nuxt.hook('duxt:search:records', async (records) => {
      await upload(records);
    });
  }
});

Un ejemplo completo de uno — el esquema de la colección, el upsert, la eliminación de lo que ya no está y la clave que jamás debe llegar a una página — está en Envía tus páginas a Typesense.

duxt:search:records

(records: readonly DuxtSearchRecord[]) => void | Promise<void>

Cuándo se dispara. Después de que Content haya analizado cada fuente, cada versión, cada idioma y cada sección generada — incluidos los repositorios remotos que descargó — y antes de que Nitro prerenderice o empaquete nada. Un listener todavía puede escribir un archivo en public/ y verlo aparecer en la salida.

Qué es un registro. Una página, más uno por cada encabezado que tenga.

CampoTipoQué contiene
idstringLa identidad del registro, y una clave primaria válida en cualquier motor
urlstringDónde aterriza quien lee — segmento de idioma y ancla incluidos
titlestringEl encabezado que cubre, o el título de la página en el primero
contentstringLas palabras bajo ese encabezado, sin marcado y con espacios normalizados
sourcestringDe qué fuente procede, como segmentos de URL sin la versión
versionstringLa etiqueta de versión, donde la fuente tenga versiones — si no, ausente
localestringEl idioma en que está escrito el contenido

id es un resumen hexadecimal en lugar de la URL, porque Meilisearch solo acepta A-Za-z0-9_- como identificador de documento. Se deriva de url, así que es igual en cualquier máquina y se mantiene mientras la página siga donde está — que es justo lo que permite a un proveedor hacer upsert en vez de reconstruir.

source es una identidad, no una dirección: / para la documentación servida en la raíz, /harbour para un segundo repositorio, /harbour/api para una sección generada dentro de él. La versión queda fuera a propósito, para que una faceta construida sobre source sobreviva a una publicación y version a su lado sea lo que reduce a una sola.

locale es el idioma del contenido, no el idioma de interfaz en que alguien está leyendo. Un sitio con fuentes sin traducir obtiene un conjunto de registros aunque sirva siete idiomas: el mismo párrafo indexado siete veces es una respuesta repetida.

Lo que deliberadamente no lleva

  • Ningún extracto. Un fragmento es una decisión sobre una lista de resultados, y la lista de resultados es tuya.
  • Ningún nombre de colección. Eso es la contabilidad interna del índice de duxt, y un documento con esa clave se rompe el día en que una fuente gana un idioma.
  • Ninguna etiqueta visible. label, name y el rótulo de versión son prosa para quien lee, traducida por idioma. Un registro no lo lee nadie.

Lo que queda fuera del índice

Una página que escribió search: false no produce ningún registro — la misma exclusión que ya respetan el diálogo de búsqueda, la herramienta MCP search_docs y ambos índices llms. Tampoco la produce una fuente traducida a un idioma que duxt.locales no sirve, porque indexarla sería ofrecer a quien lee una URL que devuelve 404.

Donde un sitio sirve dos regiones de un mismo idioma sobre un solo árbol — pt-PT y pt-BR leyendo la misma carpeta pt/ —, los registros apuntan a la primera. Ambas URL llevan las mismas palabras, así que indexar las dos duplicaría el índice para decir lo mismo dos veces; un proveedor que quiera llevar a quien lee a su propia región cambia el segmento, algo que duxt no puede hacer porque no sabe quién está buscando.

Y cuando nadie escucha, duxt no construye carga alguna: un sitio sin proveedor no paga nada por que el hook exista.

Por qué solo hay uno

Una extensión distribuible de duxt es una capa de Nuxt, no un objeto plugin:

export default defineNuxtConfig({
  extends: ['@kirchdev/duxt', 'duxt-typesense']
});

Eso ya lleva componentes, valores por defecto de app.config, colecciones de content.config.ts, rutas de servidor, herramientas MCP y un módulo propio, en un paquete con su propia versión. Una API duxt.plugins reimplementaría la resolución de capas dentro de una capa — y un registro en el que un plugin escribe al importarse choca contra el mismo muro que dio forma a sectionTypes: content.config.ts y el módulo de duxt los cargan cargadores distintos, así que un registro mutable en el que escribieran ambos serían dos registros. Un hook de compilación de Nuxt no tiene ese problema, porque solo la mitad del módulo llega a verlo.

Así que la superficie se mantiene pequeña a propósito, y cada una de las otras vías sigue siendo la respuesta correcta a su propia pregunta:

Quieres cambiarUsa
Un color, una tipografía, un espaciadoUn token CSS — Sobrescribir el tema
Lo que dibuja un componenteSombrearlo, o un slot donde exista
Lo que el sitio dice de sí mismoLa clave duxt de app.config — Configuración
Un nuevo tipo de sección generadasectionTypes — Fuentes
Lo que una página dibuja a su alrededorFrontmatter — Frontmatter
Dónde se indexa el texto del sitioEste hook
¿Le ha resultado útil esta página?