Scribe

Configuración

Todas las opciones de scribe.config.ts: ajustes del proyecto, tipos de contenido, marcadores de campo y enrutamiento por idioma.

View as Markdown

Todo se centraliza en un único archivo, scribe.config.ts, que exporta defineConfig({...}). Tanto el entorno de ejecución (createScribe) como la CLI (que detecta scribe.config.ts en el directorio de trabajo) leen este mismo archivo.

Opciones del proyecto

export default defineConfig({
  rootDir: ".",
  contentDir: "content",             // default
  store: ".scribe/store.sqlite",     // default
  assetsDir: "public",               // optional
  locales: ["en", "fr", "de"],
  defaultLocale: "en",               // default
  localeRouting: { strategy: "path-prefix", prefixDefaultLocale: false },
  localeFallbacks: true,             // default
  localePresets: { active: ["fr"] },
  translate: { /* see the translation page */ },
  types: [ /* defineContentType(...) */ ],
});
OpciónPredeterminadoDescripción
rootDirRequeridoDirectorio raíz del proyecto. Déjalo como ruta relativa (normalmente "."): la CLI lo resuelve respecto a la carpeta del archivo de configuración y createScribe respecto a process.cwd(). No lo construyas a partir de import.meta.url: los empaquetadores insertan esa ruta durante la compilación, lo que causa errores en entornos sin servidor como Vercel.
contentDir"content"Directorio que contiene una carpeta por cada tipo de contenido.
store".scribe/store.sqlite"Almacén de traducciones SQLite. Añádelo a tu repositorio de control de versiones; no incluyas .scribe/ en tu gitignore.
assetsDirOpcionalRaíz de los archivos estáticos (por ejemplo, "public"). Al configurarlo, scribe validate avisa si hay rutas de imágenes en el encabezado o en los cuerpos que no existen en el disco.
localesRequeridoTodos los idiomas, incluido el predeterminado.
defaultLocale"en"Idioma de origen canónico. Debe aparecer obligatoriamente en locales.
localeRoutingpath-prefix, unprefixed defaultDefine cómo aparecen los marcadores de idioma en las URL generadas. path-prefix añade el idioma al principio (omitiendo el predeterminado a menos que prefixDefaultLocale sea true). search-param añade ?param=locale para los idiomas no predeterminados.
localeFallbackstrueGenera cadenas de respaldo a partir de las etiquetas de idioma. Si una variante regional no tiene traducción para un documento, se muestra la traducción más cercana en el idioma base (por ejemplo, pt-BR recurre a pt) antes de pasar al idioma predeterminado. Configúralo en false para desactivarlo. Consulta la sección Cadenas de respaldo de idioma.
localePresetsOpcionalGrupos de idiomas con nombre para usar con scribe translate --preset name.
translateOpcionalValores predeterminados de traducción para todo el proyecto (traducción).
typesRequeridoDefiniciones de los tipos de contenido.

Las configuraciones se validan desde el primer momento: un defaultLocale desconocido, identificadores de tipo duplicados o una plantilla de path mal formada provocarán un error inmediato con un mensaje claro.

Opciones de tipo de contenido

defineContentType({
  id: "blog",
  schema: blogSchema,
  path: "/blog/{slug}",
  contentDir: "blog",          // default: the id
  slugStrategy: "localized",   // default: "fixed"
  indexFallback: "en",         // default: "en" if path is set, else "none"
  orderBy: "-publishedAt",     // default: "slug"
  label: "Blog",               // default: capitalized id (studio UI only)
  crossValidate: (data, ctx) => [],
  translate: { /* per-type overrides */ },
})
OpciónDescripción
idIdentificador único. Se convierte en el método de acceso tipado (scribe.blog) y en el contentDir predeterminado.
schemaEsquema de objetos Zod para el encabezado (frontmatter), con sus respectivos marcadores de campo (ver más abajo).
pathPlantilla de URL con exactamente un {slug} (por ejemplo, /blog/{slug}). Omítela para tipos que sean solo de referencia (autores, categorías) y que no tengan páginas propias.
contentDirCarpeta dentro del contentDir del proyecto que alberga los archivos .mdx de este tipo.
slugStrategy"fixed": todos los idiomas usan el slug en inglés. "localized": el traductor genera un slug específico para cada idioma (/es/blog/hola-mundo).
indexFallbackLo que devuelve resolve() cuando un idioma no tiene traducción: "en" sirve el documento en inglés (con actualLocale: "en"), mientras que "none" no devuelve nada.
orderByOrden predeterminado para list(): "slug", "publishedAt", "-publishedAt", "updatedAt", "-updatedAt", o un comparador (a, b) => number sobre documentos con tipado completo.
crossValidateValidación adicional ejecutada por scribe validate, que recibe el encabezado analizado (tipado). Devuelve { field, message, level }[].
translateIndicaciones, reglas o modelos de traducción específicos para cada tipo (traducción).

Marcadores de campo

Cada campo del esquema pertenece a uno de tres tipos. Los campos sin marcar son estructurales por defecto.

import { field } from "scribe-cms";

const schema = z.object({
  // Se envía al traductor y se guarda por idioma:
  title: field.translatable(z.string().min(1)),

  // Solo en inglés; se copia del documento en inglés a todos los idiomas:
  heroImage: field.structural(z.string().optional()),

  // Referencia(s) del slug en inglés a otro tipo de contenido:
  author: field.relation("author"),
  relatedPosts: field.relation("blog", { multiple: true, max: 4, optional: true }),
});

Los marcadores traducibles también funcionan en campos anidados dentro de matrices o arreglos sencillos (por ejemplo, sections.*.title). Simplemente asegúrate de no envolver el arreglo contenedor en un field.structural o todo el subárbol quedará únicamente en inglés.

field.relation(typeId, options?)

OpciónPredeterminadoDescripción
multiplefalseEl campo es un arreglo de slugs.
optionalfalseSe puede omitir el campo. related() devolverá null (si es único) o ignorará los elementos que falten (si es múltiple).
min / maxOpcionalLímites en la cantidad de elementos (solo para multiple: true).

Las restricciones van dentro del objeto de opciones, no en los métodos encadenados de Zod. Encadenar métodos (.max(8), .optional()) clona el esquema y eliminaría los metadatos de la relación.

Las relaciones siempre guardan slugs en inglés y se verifican mediante scribe validate (una relación requerida huérfana bloquea la compilación con un error, mientras que una opcional solo genera una advertencia). Además, se resuelven en tiempo de ejecución con related(). Consulta la API de tiempo de ejecución.

Cadenas de respaldo de idioma

Por defecto, si un idioma regional no tiene traducción para un documento, se muestra su idioma base antes de pasar al idioma predeterminado. Cada idioma prueba prefijos cada vez más cortos de su propia etiqueta que también estén presentes en locales. Así, fr-CA recurre a fr, y zh-Hant-TW prueba primero con zh-Hant y luego con zh. Configúralo en localeFallbacks: false para desactivarlo. El idioma predeterminado nunca forma parte de esta cadena; sigue siendo el último recurso absoluto y se rige por el indexFallback del tipo de contenido.

Estas cadenas de respaldo se aplican a resolve() (el idioma servido se indica en actualLocale y las redirecciones de slug usan el slug del idioma de respaldo) y a staticParams() (los slugs pre-renderizados coinciden con lo que sirve resolve()). De forma intencionada, no se aplican a get(), list(), translation(), alternates() ni al mapa del sitio (sitemap), que requieren coincidencias exactas.

Tipos de cliente con tipado

Para los alias de tipo en el lado de la aplicación, puedes derivar todo desde la configuración:

import type { ScribeClient, ScribeDocs } from "scribe-cms/runtime";
import config from "./scribe.config";

type MyScribe = ScribeClient<typeof config>;
type BlogDoc = ScribeDocs<typeof config>["blog"];
Configuración · Scribe