Scribe

Configuração

Todas as opções do scribe.config.ts: configurações de projeto, tipos de conteúdo, marcadores de campo e roteamento de idiomas.

View as Markdown

Tudo fica em um único arquivo, scribe.config.ts, que exporta defineConfig({...}). Tanto o tempo de execução (createScribe) quanto a CLI (que descobre o scribe.config.ts no diretório de trabalho) leem esse mesmo arquivo.

Opções do projeto

export default defineConfig({
  rootDir: ".",
  contentDir: "content",             // padrão
  store: ".scribe/store.sqlite",     // padrão
  assetsDir: "public",               // opcional
  locales: ["en", "fr", "de"],
  defaultLocale: "en",               // padrão
  localeRouting: { strategy: "path-prefix", prefixDefaultLocale: false },
  localeFallbacks: true,             // padrão
  localePresets: { active: ["fr"] },
  translate: { /* veja a página sobre tradução */ },
  types: [ /* defineContentType(...) */ ],
});
OpçãoPadrãoDescrição
rootDir(obrigatório)Raiz do projeto. Mantenha caminhos relativos (geralmente "."). A CLI o resolve a partir do diretório do arquivo de configuração e o createScribe a partir de process.cwd(). Não construa esse valor a partir de import.meta.url: os empacotadores incorporam esse caminho na hora da compilação, o que causa falhas em hosts serverless como o Vercel.
contentDir"content"Diretório que contém uma pasta por tipo de conteúdo.
store".scribe/store.sqlite"Armazenamento de traduções em SQLite. Faça o commit deste arquivo; não adicione .scribe/ ao gitignore.
assetsDirVazioRaiz dos ativos estáticos (exemplo, "public"). Quando configurado, o comando scribe validate avisa se encontrar caminhos de imagens no frontmatter ou no corpo que não existem no disco.
locales(obrigatório)Todos os idiomas suportados, incluindo o padrão.
defaultLocale"en"Idioma de origem canônico. Deve estar listado em locales.
localeRoutingpath-prefix, sem prefixo no padrãoComo os marcadores de idioma aparecem nas URLs geradas. A opção path-prefix adiciona o idioma ao início do caminho (omitindo o idioma padrão, a menos que prefixDefaultLocale seja true). A estratégia search-param adiciona ?param=locale para os idiomas secundários.
localeFallbackstrueCria as cadeias de fallback de idioma a partir das tags de localização. Se um documento não tiver tradução em uma variante regional, o sistema entregará a tradução no idioma base mais próximo (exemplo: pt-BR usa pt como fallback) antes de recorrer ao fallback do idioma padrão. Defina como false para desativar. Veja Cadeias de fallback de idioma.
localePresetsVazioGrupos de idiomas nomeados para uso em scribe translate --preset name.
translateVazioPadrões de tradução globais do projeto (tradução).
types(obrigatório)Definições dos tipos de conteúdo.

As configurações passam por validação inicial. O sistema lança um erro com uma mensagem clara imediatamente se encontrar um defaultLocale desconhecido, IDs de tipo duplicados ou um modelo de path malformado.

Opções de tipos de conteúdo

defineContentType({
  id: "blog",
  schema: blogSchema,
  path: "/blog/{slug}",
  contentDir: "blog",          // padrão: assume o valor do id
  slugStrategy: "localized",   // padrão: "fixed"
  indexFallback: "en",         // padrão: "en" se o path estiver definido, ou "none"
  orderBy: "-publishedAt",     // padrão: "slug"
  label: "Blog",               // padrão: id capitalizado (apenas na UI do studio)
  crossValidate: (data, ctx) => [],
  translate: { /* substituições por tipo */ },
})
OpçãoDescrição
idIdentificador exclusivo. Ele se transforma no acessor tipado (scribe.blog) e no contentDir padrão.
schemaSchema de objeto Zod para o frontmatter, com os marcadores de campo (veja abaixo).
pathModelo de URL que exige exatamente um {slug} (exemplo, /blog/{slug}). Omita esta opção para tipos estritamente de referência (como autores e categorias) que não têm páginas próprias.
contentDirPasta dentro do contentDir do projeto que guarda os arquivos .mdx deste tipo específico.
slugStrategyCom "fixed", todos os idiomas usam o slug em inglês. Com "localized", o tradutor gera um slug para cada idioma (/fr/blog/bonjour-le-monde).
indexFallbackDefine a resposta de resolve() quando um idioma não possui tradução. O valor "en" serve o documento em inglês (marcado como actualLocale: "en"), enquanto "none" não retorna nada.
orderByCritério de ordenação padrão para list(). Valores permitidos: "slug", "publishedAt", "-publishedAt", "updatedAt", "-updatedAt", ou um comparador customizado (a, b) => number aplicado sobre os documentos tipados.
crossValidateValidação adicional realizada pelo comando scribe validate que recebe o frontmatter tipado e analisado. Deve retornar { field, message, level }[].
translateRegras, prompts e modelos de tradução específicos para este tipo (tradução).

Marcadores de campo

Todo campo do schema pertence a uma de três categorias. Os campos não marcados são tratados como estruturais por padrão.

import { field } from "scribe-cms";

const schema = z.object({
  // Enviado ao tradutor e armazenado por idioma:
  title: field.translatable(z.string().min(1)),

  // Apenas em inglês; copiado do documento em inglês para todos os idiomas:
  heroImage: field.structural(z.string().optional()),

  // Referência(s) de slug em inglês apontando para outro tipo de conteúdo:
  author: field.relation("author"),
  relatedPosts: field.relation("blog", { multiple: true, max: 4, optional: true }),
});

Os marcadores traduzíveis também se aplicam a campos aninhados em arrays comuns ou objetos (exemplo, sections.*.title). O único cuidado é não envolver o array principal em field.structural, pois isso transformaria toda a subárvore em conteúdo apenas em inglês.

field.relation(typeId, options?)

OpçãoPadrãoDescrição
multiplefalseO campo é um array de slugs.
optionalfalseO campo pode ser omitido. O método related() retornará null (quando único) ou pulará os itens ausentes (quando múltiplo).
min / maxVazioLimites de quantidade de itens (apenas para multiple: true).

As restrições devem ir no objeto de opções, e não através do encadeamento de métodos do Zod. Usar o encadeamento (como em .max(8) ou .optional()) acaba clonando o schema e apagando os metadados da relação.

As relações sempre armazenam slugs em inglês e passam pela verificação do scribe validate (uma relação obrigatória ausente bloqueia o build com um erro, enquanto uma opcional gera apenas um aviso). Além disso, elas são desreferenciadas em tempo de execução usando related(). Confira mais detalhes na API de tempo de execução.

Cadeias de fallback de idioma

Por padrão, se não houver tradução de um documento para um idioma regional, o sistema entregará a versão no idioma base associado antes de apelar para o idioma padrão da aplicação. Cada idioma testa prefixos progressivamente mais curtos de sua própria tag que também constem em locales. Dessa forma, fr-CA tenta fr, e zh-Hant-TW usa zh-Hant antes de tentar zh. Defina localeFallbacks: false se quiser desativar esse comportamento. O idioma padrão da aplicação nunca compõe essa cadeia: ele se mantém como o último recurso de fallback, obedecendo ao indexFallback do tipo.

Os fallbacks afetam o método resolve() (o idioma efetivamente entregue vem indicado em actualLocale, e os redirecionamentos de slug aproveitam o slug do idioma de fallback) e o método staticParams() (os slugs pré-renderizados seguem as entregas do resolve()). No entanto, eles propositalmente não afetam get(), list(), translation(), alternates() ou o sitemap, pois essas funções exigem correspondências exatas.

Tipos de cliente tipados

Para os aliases de tipo do lado da aplicação, basta derivar tudo diretamente da configuração:

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

type MyScribe = ScribeClient<typeof config>;
type BlogDoc = ScribeDocs<typeof config>["blog"];
Configuração · Scribe