---
order: 7
section: features
title: Assets (Recursos)
description: >-
  Declare campos de recursos validados com field.asset(), restrinja caminhos e
  formatos, e resolva-os para URLs públicas no momento da leitura.
noindex: false
canonicalPath: /pt-BR/docs/assets
---
O Scribe trata os recursos estáticos (atualmente imagens) como referências de primeira classe declaradas em um esquema, e não como simples strings soltas. O princípio básico é que os componentes nunca montam URLs de recursos concatenando strings. O frontmatter armazena uma referência de origem canônica e o tempo de execução a transforma na URL final na hora do carregamento. Essa pequena camada de separação permite que você adicione configurações como `publicPath`, CDNs e hash de conteúdo sem precisar reescrever o código do projeto.

## Configuração

O grupo de configuração `assets` define onde os arquivos de origem ficam guardados e como devem ser servidos. O antigo `assetsDir` ainda funciona como um atalho (agora descontinuado) para `{ dir: assetsDir }`.

```ts
export default defineConfig({
  // ...
  assets: {
    dir: "public",            // onde os arquivos de origem ficam no disco, em relação ao rootDir. O padrão é "public".
    publicPath: "/",          // o prefixo da URL sob o qual são servidos. Um caminho ("/static/") ou uma origem de CDN. O padrão é "/".
    managedDirs: ["/blog-images"], // raízes extras de caminho da web gerenciadas pelo Scribe que não são cobertas por nenhum field.asset()
  },
});
```

O `publicPath` segue a convenção do webpack/Vite para esse conceito. As entradas em `managedDirs` são raízes de origem: diretórios que você menciona no meio dos textos em MDX e que não estão atrelados a um campo de recurso específico.

## `field.asset()`

```ts
import { field } from "scribe-cms";

const garmentSchema = z.object({
  title: field.translatable(z.string()),
  productImage: field.asset({
    dir: "/try-on/garments",   // o valor deve estar dentro deste caminho da web
    formats: ["webp"],          // lista de extensões permitidas
    maxKB: 150,                 // limite de tamanho (gera um aviso)
    optional: false,            // padrão
  }),
});
```

Assim como no `field.relation()`, as restrições ficam no objeto de opções, não em métodos Zod encadeados. Se você encadear, o esquema é clonado e os metadados são perdidos. Os campos de recursos são sempre estruturais, ou seja, os caminhos dos recursos nunca são enviados para a equipe de tradução.

| Opção | Tipo | Significado |
| --- | --- | --- |
| `dir` | `string` | Prefixo do caminho da web sob o qual o valor deve estar. Também declara uma raiz gerenciada. |
| `template` | `string` | Modelo de caminho derivado. Por exemplo: `"/try-on/garments/{slug}/product.webp"`. `{slug}` é o slug em inglês da entrada. Se você configurar isso, dá para omitir o campo no frontmatter e o carregador preenche para você. Se você passar um valor explícito, ele substitui o modelo (útil para compartilhar imagens entre entradas). |
| `formats` | `string[]` | Extensões permitidas (letras minúsculas, sem o ponto). Se sair disso, gera um aviso de validação. |
| `maxKB` | `number` | Limite de tamanho do arquivo. Se passar, gera um aviso de validação. |
| `optional` | `boolean` | O campo pode estar ausente (só faz sentido se não usar `template`). Se o valor estiver lá e o arquivo não existir, vai dar erro do mesmo jeito. |

O valor no frontmatter é um caminho da web relativo à raiz dentro de `assets.dir`. Por exemplo, `/try-on/garments/denim-flare/product.webp` (a mesma regra de uma string de imagem normal, sem precisar inventar um esquema de URI novo). No disco, o frontmatter guarda a referência de origem (ou nada, se estiver usando um modelo). As URLs resolvidas só aparecem na saída do tempo de execução. As exportações estáticas/brutas e os tradutores sempre enxergam os valores de origem.

## Resolução no carregamento

Quando o tempo de execução carrega um documento, ele varre o esquema procurando campos de recursos e, para cada um:

1. Se não tiver um valor no frontmatter e o campo tiver um `template`, ele monta o caminho usando o modelo (o `{slug}` vira o slug em inglês).
2. Adiciona o prefixo de `assets.publicPath` (juntando sem barras duplas; se for um `publicPath` de origem absoluta, também funciona).

Assim, quem consome os dados recebe a URL final de bandeja, sem precisar fazer mais nenhuma chamada:

```ts
const garment = scribe.garment.get("denim-flare");
garment.frontmatter.productImage;
// "/try-on/garments/denim-flare/product.webp"                       (publicPath "/")
// "https://cdn.example.com/try-on/garments/denim-flare/product.webp" (CDN publicPath)
```

A resolução acontece depois que os campos estruturais são mesclados nos documentos localizados. Ou seja, todos os idiomas recebem os valores resolvidos direto da origem em inglês.

### `scribe.assets.url(ref)`

Uma válvula de escape para imagens no corpo do MDX ou para casos avulsos. Aplica o `publicPath` direto em uma referência bruta:

```ts
scribe.assets.url("/blog-images/hero.webp"); // publicPath aplicado
```

Você também pode puxar recursos direto no corpo do MDX usando o [token inline `asset`](/docs/inline-tokens), que é resolvido do mesmo jeito na hora da leitura.

## Validação

O comando `scribe validate` confere todos os campos de recursos que você declarou:

- **Arquivo faltando em um campo de recurso obrigatório**: erro (para a build, igual quando falta uma relação obrigatória).
- **Arquivo faltando em um campo `optional` que tem valor**: erro também. O `optional` significa que o campo pode ficar em branco, não que você pode inventar um caminho falso.
- **Valor fora do `dir` do campo**: erro.
- **Extensão fora do `formats`**: aviso.
- **Arquivo maior que o `maxKB`**: aviso.
- Campos que usam modelo validam o caminho materializado. O arquivo tem que existir, mesmo que o frontmatter não tenha o valor.

As mensagens dizem certinho de onde vem o problema. Por exemplo: `garment/denim-flare: productImage → /try-on/garments/denim-flare/product.webp not found`. Além disso, strings que parecem imagens e que a gente cata por heurística no frontmatter e no corpo do MDX ainda geram aviso quando não existem. Isso ajuda a cobrir as imagens do texto sem precisar migrar nada.

## Studio

O [studio](/docs/studio) mostra os recursos em modo somente leitura:

- O **inspetor de entrada** mostra os campos de recursos como prévias de imagem com a URL resolvida, tamanho do arquivo e as dimensões. Se o arquivo estiver faltando, aparece um selo vermelho.
- O **navegador de recursos** (`/assets`) exibe uma grade de miniaturas para cada raiz gerenciada. Cada recurso mostra seu caminho, tamanho, dimensões e uma lista com todos os campos e entradas que o referenciam. Selos ajudam a destacar recursos sem referência (candidatos a virar órfãos), referenciados mas que estão faltando, que passaram do tamanho ou que estão fora do formato.
- A **visualização em galeria** permite que qualquer tipo com um campo de recurso mostre sua lista de entradas como uma grade de cartões. É ótimo para bater o olho e fazer o controle de qualidade das imagens geradas.
