# Cómo integrar Keystatic en Next.js paso a paso

> Aprende a integrar Keystatic en Next.js paso a paso: instalación, keystatic.config.ts, panel en /keystatic, lectura de contenido con el reader y modo GitHub.

URL: https://codegea.com/como-integrar-keystatic-en-next-js-paso-a-paso
CMS · 2026-07-04 · Derian Pinto

Un CMS basado en Markdown suena muy bien hasta que toca montarlo. La buena noticia es que con Keystatic y Next.js el proceso es corto: al terminar tendrás un panel de edición en `/keystatic` que escribe archivos `.md` dentro de tu repositorio, sin ninguna base de datos de por medio.

Esta es la guía paso a paso. Si vienes en frío, conviene tener claro primero qué es un CMS basado en Markdown y por qué encaja con un [enfoque headless con Next.js](/wordpress-headless-con-next-js-arquitectura-ventajas-y-como-empezar). Los pasos que siguen están alineados con la [documentación oficial de Keystatic](https://keystatic.com/docs/installation-next-js).

## Qué vamos a montar

- Un panel de administración de Keystatic servido en la ruta `/keystatic` de tu propia app.
- Una colección de *posts* guardada como archivos Markdown en `src/content/posts`.
- La lectura de ese contenido desde tus páginas con el *reader* de Keystatic.

## Antes de empezar

- Un proyecto Next.js con App Router (sirve uno nuevo con `npx create-next-app`).
- Node.js instalado y el proyecto versionado en un repositorio Git.
- Nociones básicas de la terminal; no necesitas nada más.

## Paso 1: Instala las dependencias

```bash
npm install @keystatic/core @keystatic/next @markdoc/markdoc
```

`@keystatic/core` es el núcleo, `@keystatic/next` conecta el panel con Next.js y `@markdoc/markdoc` procesa el Markdown enriquecido del cuerpo de las entradas.

## Paso 2: Crea el archivo de configuración

En la raíz del proyecto crea `keystatic.config.ts`. Aquí defines dónde se guarda el contenido (`storage`) y qué colecciones existen con su esquema de campos.

```ts
import { config, fields, collection } from '@keystatic/core';

export default config({
  storage: {
    kind: 'local',
  },
  collections: {
    posts: collection({
      label: 'Posts',
      slugField: 'title',
      path: 'src/content/posts/*',
      format: { contentField: 'content' },
      schema: {
        title: fields.slug({ name: { label: 'Title' } }),
        content: fields.markdoc({ label: 'Content' }),
      },
    }),
  },
});
```

El `storage: { kind: 'local' }` guarda los archivos en tu disco mientras desarrollas. Más abajo lo cambiamos a GitHub para producción.

## Paso 3: Monta el panel de administración

Keystatic sirve su propia interfaz dentro de tu app. Crea estos tres archivos bajo `src/app/keystatic` para renderizar el panel en la ruta `/keystatic`.

```ts
// src/app/keystatic/keystatic.ts
'use client';
import { makePage } from '@keystatic/next/ui/app';
import config from '../../../keystatic.config';
export default makePage(config);

// src/app/keystatic/layout.tsx
import KeystaticApp from './keystatic';
export default function Layout() {
  return <KeystaticApp />;
}

// src/app/keystatic/[[...params]]/page.tsx
export default function Page() {
  return null;
}
```

## Paso 4: Añade el manejador de rutas de la API

El panel necesita un endpoint para leer y escribir. Crea `src/app/api/keystatic/[...params]/route.ts`.

```ts
import { makeRouteHandler } from '@keystatic/next/route-handler';
import config from '../../../../../keystatic.config';

export const { POST, GET } = makeRouteHandler({
  config,
});
```

Ya puedes arrancar el proyecto con `npm run dev` y abrir `http://127.0.0.1:3000/keystatic`: ahí está tu panel para crear entradas.

## Paso 5: Lee y muestra el contenido

Para pintar las entradas en tu sitio, Keystatic ofrece el *reader*. Con él accedes a toda la colección o a una entrada concreta por su slug.

```ts
import { createReader } from '@keystatic/core/reader';
import keystaticConfig from '../../keystatic.config';

const reader = createReader(process.cwd(), keystaticConfig);

// Todas las entradas de la colección
const posts = await reader.collections.posts.all();

// Una entrada concreta por su slug
const post = await reader.collections.posts.read('mi-primer-post');
```

El cuerpo de cada entrada se obtiene con `post.content()` y se renderiza con Markdoc (`Markdoc.transform` y `Markdoc.renderers.react`). Tienes el detalle en la [documentación del reader](https://keystatic.com/docs/reader-api).

## Del modo local a GitHub

El modo local es perfecto para desarrollar, pero en producción querrás que los editores guarden cambios sin tocar tu máquina. Para eso está el modo GitHub: Keystatic hace commits directamente a tu repositorio. Solo cambias el `storage`.

```ts
storage: {
  kind: 'github',
  repo: { owner: 'tu-usuario', name: 'tu-repo' },
},
```

La primera vez que entres a `/keystatic` en modo GitHub, Keystatic te guía para crear una GitHub App y conectar el repo; ese proceso genera en tu `.env` las variables `KEYSTATIC_GITHUB_CLIENT_ID`, `KEYSTATIC_GITHUB_CLIENT_SECRET` y `KEYSTATIC_SECRET`. A partir de ahí, cualquier persona con acceso de escritura al repositorio puede editar desde el panel. Los pasos completos están en la [documentación del modo GitHub](https://keystatic.com/docs/github-mode).

## El orden que evita los atascos

La mayoría de los problemas con Keystatic aparecen al pasar a producción, no al instalarlo. Por eso conviene trabajar en este orden: primero modo local con dos o tres entradas de prueba; después comprobar que el reader las lee y las pinta en tus páginas; y solo entonces pasar a GitHub.

Una trampa frecuente: el modo local escribe en el disco, así que funciona en tu máquina pero no en un hosting sin sistema de archivos persistente como Vercel. En producción el panel necesita el modo GitHub. Cuando lo actives, revisa que las variables que Keystatic genera en tu `.env` (`KEYSTATIC_GITHUB_CLIENT_ID`, `KEYSTATIC_GITHUB_CLIENT_SECRET` y `KEYSTATIC_SECRET`) también estén cargadas en el entorno de producción.

Y deja claro quién puede editar: cualquier persona con permiso de escritura en el repositorio podrá hacerlo desde el panel. Si el contenido crece hacia miles de entradas o muchos editores, compáralo con un [headless con base de datos como Directus o Strapi](/directus-vs-strapi-que-headless-cms-elegir-segun-tu-proyecto).

---

¿Quieres montar Keystatic (o el CMS que mejor encaje) en tu proyecto Next.js sin pelearte con la configuración? En Codegea lo hacemos por ti: mira el servicio de [integración de CMS](/servicios/integraciones-cms) o escríbenos desde [la página de contacto](/contacto).
