Keystatic CMS es el editor detrás del blog de seodraft, que corre en Next.js y hace deploy en Vercel. Lo elegí por la simpleza de trabajar git-based: cada post es un archivo en el repositorio, y seodraft entrega los borradores aprobados directo en esa carpeta.
El 13 de octubre de 2026, los primeros ocho resultados de Google para "keystatic cms" eran dos páginas de la documentación de Keystatic, su login de Cloud, una comparación con Decap CMS, una página de discusiones en GitHub y tres artículos, uno de ellos una guía para Astro. Este post suma el lado de producción, con las siete decisiones que hicieron andar el setup y la configuración detrás de cada una.
La lección 4 cubre un blog bilingüe, donde los posts en inglés y en español necesitan colecciones separadas para que cada idioma tenga su propio slug. Empezá por qué guarda Keystatic y dónde.
- 1. Keystatic edita los archivos que ya están en tu repo
- 2. Elegí el modo de almacenamiento antes del primer post
- 3. Corré el admin publicado en modo GitHub en Vercel
- 4. Dale a cada idioma su propia colección
- 5. Poné tus campos de SEO y una casilla de borrador en el esquema
- 6. Guardá las imágenes en public/ para que sus URLs respondan
- 7. Dejá que los borradores del agente lleguen como archivos que el admin abre
- Elegí Keystatic cuando tus posts pueden vivir en Git
1. Keystatic edita los archivos que ya están en tu repo
Keystatic es un editor de contenido que lee y escribe los archivos Markdown, Markdoc, JSON o YAML de tu código, y no necesita base de datos.
Describís cada tipo de contenido en keystatic.config.ts, y el admin en /keystatic convierte ese esquema en formularios. Su documentación tiene guías de integración para Next.js, Astro y Remix.
En este blog un post es un archivo .mdoc dentro de content/blog/en/ o content/blog/es/, editado con @keystatic/core 0.6 sobre Next.js 16. Guardar en el admin escribe ese archivo, y en modo GitHub cada guardado se vuelve un commit que podés revisar o revertir.
2. Elegí el modo de almacenamiento antes del primer post
Keystatic tiene tres modos de almacenamiento, y el que elijas decide quién puede editar y adónde va cada guardado.
local escribe en tu propio disco, lo que sirve para desarrollo y para un primer prototipo. github lee y escribe un repositorio de GitHub a través de una GitHub App que creás desde el admin, y cada editor necesita permiso de escritura en ese repo.
cloud le deja el login a Keystatic Cloud, así alguien sin cuenta de GitHub puede editar. Su documentación, leída el 13 de octubre de 2026, lista un plan gratis de hasta 3 usuarios por equipo y un plan Pro desde USD 10 por mes, más USD 5 por cada usuario después del tercero.
Este blog usa el modo local en mi máquina y el modo GitHub en producción. El modo cloud no lo usa.
3. Corré el admin publicado en modo GitHub en Vercel
Un admin de Keystatic publicado en Vercel tiene que usar el modo GitHub, porque el sistema de archivos de Vercel es de solo lectura y el admin solo puede guardar haciendo commits.
La documentación de Keystatic también pide un hosting que corra Node.js para sus rutas de API, y que copies las variables de entorno de Keystatic al proyecto publicado. El asistente de la GitHub App tiene que correr desde localhost, porque ese flujo crea KEYSTATIC_GITHUB_CLIENT_ID, KEYSTATIC_GITHUB_CLIENT_SECRET, KEYSTATIC_SECRET y la variable con el slug de la app.
El error de la intro salió del cambio entre modos. Elegía el modo con una variable de entorno que tenía el nombre del repo, pero keystatic.config.ts también lo importa el admin, que es un componente de cliente, y una variable común queda undefined en el bundle del navegador.
Renombrarla con el prefijo NEXT_PUBLIC_ lo resolvió. El nombre del repo es lo único que expone.
// keystatic.config.ts
function storage() {
const repo = process.env.NEXT_PUBLIC_KEYSTATIC_GITHUB_REPO;
if (!repo) return { kind: "local" } as const;
const [owner, name] = repo.split("/");
return { kind: "github", repo: { owner, name } } as const;
}
4. Dale a cada idioma su propia colección
Un blog bilingüe en Keystatic funciona mejor con una colección por idioma, porque un slug solo tiene que ser único dentro de su colección.
En una sola colección, la versión en inglés y la versión en español de un mismo post nunca podrían compartir slug. Con dos colecciones, un post sin traducir simplemente no tiene hermano, y el sitio solo anuncia una alternativa hreflang cuando ese archivo existe.
Emparejamos las traducciones con un campo translationKey que lleva el mismo valor en cada versión de idioma. Así el post en español conserva un slug en español, y dos posts sin relación que comparten slug por casualidad nunca quedan declarados como traducción uno del otro.
5. Poné tus campos de SEO y una casilla de borrador en el esquema
El esquema de Keystatic es donde los campos de SEO de un post se vuelven obligatorios, así una descripción vacía nunca llega al sitio publicado.
El nuestro exige una descripción de hasta 200 caracteres, porque alimenta la meta description y el índice del blog. Suma un tldr y FAQs que los motores de respuesta pueden citar enteros, etiquetas, y una fecha updatedAt para el lastmod del sitemap, ya que un checkout nuevo reescribe la fecha de modificación de cada archivo.
La casilla draft oculta un post del blog y del sitemap. Cuando importamos el sitemap de seodraft el 27 de septiembre de 2026, listaba 57 páginas, 6 de ellas posts del blog, y el chequeador de sitemap gratis te da el mismo conteo de tu sitio después de cada deploy.
6. Guardá las imágenes en public/ para que sus URLs respondan
Las imágenes de un blog en Keystatic necesitan una carpeta que tu sitio sirva de verdad, y en Next.js esa carpeta es public/.
Por defecto, Keystatic guarda la imagen al lado de su entrada, dentro de content/, con un src relativo al post. En nuestro sitio nada servía esa carpeta, así que esas imágenes devolvían 404.
Nuestro campo de imagen apunta el directorio a public/blog-images/en o public/blog-images/es y la ruta pública a la misma carpeta, así el src que escribe Keystatic es la URL que sirve el archivo. Una función transformFilename corta quita acentos y espacios, para que el nombre por defecto de una captura nunca termine como %20 en una URL.
image: {
directory: `public/blog-images/${locale}`,
publicPath: `/blog-images/${locale}/`,
},
7. Dejá que los borradores del agente lleguen como archivos que el admin abre
Un agente de IA puede escribir en un blog con Keystatic cuando cada borrador llega como un archivo con el frontmatter que espera tu esquema.
Mi agente escribe a través de seodraft, y cuando apruebo un post seodraft hace commit en content/blog/{locale}/{slug}.mdoc con draft: true. Mapea la fecha del post a publishedAt y la fecha de actualización a updatedAt, así Keystatic abre el archivo como cualquier post que escribí a mano.
Un campo necesitó un arreglo. Los posts entregados llevan anclas {% #id %} en los encabezados para el índice, y el editor de Keystatic rechaza los atributos de encabezado que su esquema no declara, así que esos archivos no abrían hasta que sumé id al esquema de encabezados.
Antes de que un archivo llegue al repo, el borrador pasa por un orden fijo. El proceso actual guarda el brief antes del cuerpo y requiere que cada evidencia del brief llegue al artículo.
Publicar sigue siendo decisión mía. En mi primera prueba de seodraft, el 17 de septiembre de 2026, la corrida terminó con el post marcado como listo. El flujo se detuvo en READY: no llamé a la entrega ni publiqué el artículo.
Para que salga en vivo, destildás Draft y hacés commit de ese cambio. La página de entrega al CMS lista las opciones de ruta y de frontmatter que seodraft puede escribir.
Elegí Keystatic cuando tus posts pueden vivir en Git
Elegí Keystatic cuando las personas que editan tu blog pueden trabajar desde un repositorio de Git, y pasate a su modo cloud cuando alguien sin cuenta de GitHub necesita editar.
Para un blog que lleva el founder en Next.js, yo arrancaría en modo local, escribiría el esquema con los campos de SEO y la casilla de borrador, y recién después pasaría producción a modo GitHub con la variable NEXT_PUBLIC_ de la lección 3. Si todavía estás eligiendo framework, la versión en Astro de este setup usa las mismas piezas de Keystatic.
Cuando quieras que los briefs, las reglas y la entrega de borradores a tu repo con Keystatic queden resueltos, probá seodraft con tu propio agente. Cuesta USD 9 por mes por un workspace, y la prueba de 7 días no pide tarjeta: tu agente escribe, las reglas deciden y vos aprobás.
