---
order: 2
section: guides
title: Configuração
description: >-
  Todas as opções do scribe.config.ts: configurações de projeto, tipos de
  conteúdo, marcadores de campo e roteamento de idiomas.
noindex: false
canonicalPath: /pt-BR/docs/configuration
---
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

```ts
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ção | Padrão | Descriçã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.** |
| `assetsDir` | Vazio | Raiz 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`. |
| `localeRouting` | path-prefix, sem prefixo no padrão | Como 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. |
| `localeFallbacks` | `true` | Cria 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](#locale-fallback-chains). |
| `localePresets` | Vazio | Grupos de idiomas nomeados para uso em `scribe translate --preset name`. |
| `translate` | Vazio | Padrões de tradução globais do projeto ([tradução](/docs/translation)). |
| `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

```ts
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ção | Descrição |
| --- | --- |
| `id` | Identificador exclusivo. Ele se transforma no acessor tipado (`scribe.blog`) e no `contentDir` padrão. |
| `schema` | Schema de objeto Zod para o frontmatter, com os marcadores de campo (veja abaixo). |
| `path` | Modelo 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. |
| `contentDir` | Pasta dentro do `contentDir` do projeto que guarda os arquivos `.mdx` deste tipo específico. |
| `slugStrategy` | Com `"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`). |
| `indexFallback` | Define 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. |
| `orderBy` | Crité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. |
| `crossValidate` | Validação adicional realizada pelo comando `scribe validate` que recebe o frontmatter tipado e analisado. Deve retornar `{ field, message, level }[]`. |
| `translate` | Regras, prompts e modelos de tradução específicos para este tipo ([tradução](/docs/translation)). |

## 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.

```ts
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ção | Padrão | Descrição |
| --- | --- | --- |
| `multiple` | `false` | O campo é um array de slugs. |
| `optional` | `false` | O campo pode ser omitido. O método `related()` retornará `null` (quando único) ou pulará os itens ausentes (quando múltiplo). |
| `min` / `max` | Vazio | Limites 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](/docs/runtime-api).

## 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:

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

type MyScribe = ScribeClient<typeof config>;
type BlogDoc = ScribeDocs<typeof config>["blog"];
```
