---
order: 1
section: start
title: Iniziare con Scribe
description: >-
  Installa scribe-cms, definisci uno schema, scrivi il contenuto e rileggilo con
  tipi forti in cinque semplici passaggi.
noindex: false
canonicalPath: /it/docs/getting-started
---
## Installazione

```bash
pnpm add scribe-cms zod better-sqlite3
```

Requisiti: Node 20+, Zod v4. Scribe non dipende da alcun framework in particolare: funziona con qualsiasi stack basato su Node. Poiché `better-sqlite3` è un modulo nativo, assicurati di mantenerlo esterno al tuo bundler (consulta la pagina dedicata all'[API di runtime](/docs/runtime-api)).

## 1. Crea `scribe.config.ts`

Inserisci questo file nella directory principale del tuo progetto:

```ts
import { z } from "zod";
import { defineConfig, defineContentType, field } from "scribe-cms";

const blogSchema = z.object({
  title: field.translatable(z.string().min(1)),
  description: field.translatable(z.string().min(50).max(250)),
  author: field.relation("author"),
  tags: field.structural(z.array(z.string()).default([])),
});

const authorSchema = z.object({
  name: field.structural(z.string().min(1)),
});

export default defineConfig({
  rootDir: ".", // relativo a questo file (CLI) / process.cwd() (runtime)
  locales: ["en", "fr", "de"],
  types: [
    defineContentType({
      id: "blog",
      path: "/blog/{slug}",
      schema: blogSchema,
      slugStrategy: "localized",
      orderBy: "-publishedAt",
    }),
    defineContentType({
      id: "author",
      contentDir: "authors",
      schema: authorSchema,
    }),
  ],
});
```

`defineConfig` e `defineContentType` sono funzioni di identità che preservano i tipi letterali. È grazie a loro che successivamente `scribe.blog` e `related(doc, "author")` saranno completamente tipizzati.

## 2. Scrivi il contenuto

```text
content/
  blog/
    hello-world.mdx
  authors/
    jane.mdx
```

```mdx
---
title: "Ciao, mondo"
description: "Un primo post per salutare il mondo, scritto in modo prolisso perché lo schema richiede almeno cinquanta caratteri."
author: jane
publishedAt: "2026-01-15"
---

Il corpo è in formato MDX. Funzionano sia il **Markdown** che i componenti React.
```

Il nome del file (`hello-world`) corrisponde allo slug in inglese. `publishedAt` è uno dei campi integrati disponibili per ogni tipo di contenuto. Per maggiori dettagli, consulta la sezione sul [modello dei contenuti](/docs/content-model).

## 3. Convalida

Dopo aver eseguito `pnpm install`, la CLI `scribe` sarà disponibile nel tuo PATH (proprio come `next`):

```bash
pnpm scribe validate
pnpm scribe status
```

Puoi integrarla facilmente prima della tua build:

```json
{
  "scripts": {
    "build": "scribe validate && <il comando di build del tuo framework>"
  }
}
```

## 4. Leggi il contenuto

```ts
import { createScribe } from "scribe-cms/runtime";
import config from "./scribe.config";

const scribe = createScribe(config);

const posts = scribe.blog.list(); // BlogDoc[], dal più recente al più vecchio
const { document } = scribe.blog.resolve("hello-world", "fr");
const author = scribe.blog.related(document!, "author"); // AuthorDoc, non nullo
```

I tipi per `document.frontmatter` vengono generati automaticamente a partire dal tuo schema Zod. Consulta l'[API di runtime](/docs/runtime-api) per scoprire tutte le funzionalità disponibili.

## 5. Traduci

```bash
export GEMINI_API_KEY=...   # oppure inseriscila in un file .env
npx scribe translate --locale fr
```

Scribe individua tutte le pagine mancanti o non aggiornate in francese, traduce i campi che hai contrassegnato con `field.translatable()` e salva il risultato in `.scribe/store.sqlite`. **Ricorda di committare questa directory**. Non aggiungere mai `.scribe/` al tuo `.gitignore`. Trovi maggiori dettagli nella sezione dedicata alla [traduzione](/docs/translation).
