This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

La Agencia de Nueva Generación ya está aquí. Únete a más de 3.000 profesionales de agencias en Agency Advantage 2026. Regístrate gratis→

CMS Headless Node.js: qué es y cómo crear uno

Actualizado el Septiembre 21, 2026

13 min de lectura
headless-cms-nodejs

Puntos clave

  • Un CMS «headless» almacena el contenido por separado del frontend, y Node.js te permite decidir exactamente cómo se recupera y se muestra ese contenido.
  • Entre las opciones más populares de CMS sin interfaz compatibles con Node.js se encuentran plataformas autohospedadas como Strapi y Payload, y otras alojadas como Contentful y Sanity.
  • En esta guía crearás un backend de blog funcional con Express, EJS y Contentful, y luego lo probarás localmente.
  • El proyecto terminado se implementa directamente desde GitHub utilizando el alojamiento gestionado de Node.js de Cloudways.

En un CMS sin interfaz (headless), el contenido se almacena y gestiona por separado del front-end. Muchos blogs y sitios de comercio electrónico modernos funcionan así. El contenido se aloja en el CMS y se envía a la aplicación que lo muestra a través de una API.

Node.js encaja a la perfección con una configuración «headless», ya que no incluye ninguna regla de renderizado integrada. Tú decides cómo se recoja y se muestre el contenido, ya sea una página renderizada por el servidor, una API JSON para una app móvil o cualquier otra cosa que quieras crear a partir de ahí.

En este blog, te explicaré por qué tiene sentido combinar Node.js con un CMS sin interfaz gráfica, repasaré algunas de las opciones de CMS más populares que hay y, después, crearé un pequeño proyecto para mostrarlo en la práctica. Por último, lo implementaré todo en un servidor de Cloudways en producción.

¿Por qué usar Node.js con un CMS sin interfaz gráfica?

La razón principal por la que yo optaría por usar Node.js sin más en este caso es el control. No hay ningún marco de trabajo que te diga cómo tienes que recuperar o mostrar el contenido; tú mismo escribes la lógica, tal y como lo necesita tu proyecto.

Como Node.js no está ligado a ningún enfoque de front-end en concreto, el mismo back-end puede servir el contenido como tú quieras. Podrías generar páginas HTML completas en el servidor, ofrecer el contenido como una API JSON limpia para un front-end independiente o una aplicación móvil, o hacer ambas cosas desde una única base de código.

Además, es ligero. No tienes que cargar con todo un framework de front-end y sus herramientas de compilación solo para mostrar una lista de entradas de blog; con un pequeño servidor Express y un motor de plantillas basta para conseguir un resultado que funcione y esté listo para producción.

Y, como en cualquier configuración «headless», tienes la flexibilidad de mantener todo separado. El CMS se encarga de crear y almacenar el contenido. Tu backend de Node.js se ocupa de la lógica, el formato y la entrega. Ninguna de las dos partes interfiere con la otra.

Antes de ponerte manos a la obra, vale la pena saber qué opciones hay realmente en el mercado, ya que el término «CMS headless» abarca una gama bastante amplia de herramientas.

  • Strapi — De código abierto y autohospedado, lo que significa que todo el CMS funciona como tu propia aplicación de Node.js. Viene con un panel de administración completo listo para usar, además de un ecosistema de plugins por si necesitas ampliarlo más adelante.
  • Payload — Nativo de TypeScript y «code-first»: defines tu esquema directamente en el código. Está diseñado pensando especialmente en los flujos de trabajo de React y Next.js, aunque también funciona bien fuera de ese contexto.
  • KeystoneJS — Genera automáticamente una API de GraphQL a partir de tu definición de esquema. Mínimo código repetitivo si ya te gusta consultar datos con GraphQL.
  • Contentful — Está totalmente alojado, así que no tienes que gestionar ningún servidor. Viene con plantillas ya preparadas, incluida la plantilla de blog que voy a usar en el miniproyecto que te muestro a continuación.
  • Sanity — También está alojado y tiene edición colaborativa en tiempo real integrada. Admite tanto su propio lenguaje de consulta (GROQ) como GraphQL, según lo que prefieras.

En el miniproyecto del que voy a hablar a continuación, usaré Contentful, sobre todo para centrarme en la parte de Node.js del proyecto, en lugar de perder tiempo montando y configurando un CMS completo desde cero.

Cómo crear un blog «headless» con Node.js

Para que veas cómo funciona esto en la práctica, voy a crear un miniproyecto: un backend sencillo para un blog que recupere artículos de un CMS y los muestre como páginas HTML limpias usando Express.

Lo que voy a usar

  • Node.js
  • VS Code
  • Contentful (plan gratuito)
  • Express y EJS

Paso 1: Configurar el CMS sin interfaz (Contentful)

Antes de escribir ningún código de backend, necesito un sitio donde guardar el contenido del blog. Para ello, voy a usar el plan gratuito de Contentful.

Al registrarme, Contentful me da la opción de empezar con una plantilla, y voy a elegir la plantilla «Blog» para no tener que crear una estructura de contenido desde cero.

Para confirmar que todo está configurado como esperaba, voy a la pestaña «Modelo de contenido» y compruebo lo que ya hay ahí.

El que realmente necesito es «página – Entrada de blog», que incluye campos como el título, los metadatos SEO y el cuerpo del contenido principal.

Modelo de contenido de Contentful que muestra la página: campos del tipo de contenido «Entrada de blog»

A continuación, voy a pasar a la pestaña «Contenido ». Como he usado la plantilla, Contentful ya debería haberme creado unas cuantas entradas de blog de muestra. Solo tengo que asegurarme de que su estado aparezca como «Publicado», ya que eso es lo que hace que se puedan recuperar a través de la API.

Pestaña «Contenido» de Contentful, con una lista de entradas de blog de ejemplo marcadas como publicadas

Todo aparece como publicado, así que esa parte ya está lista.

Lo último que tengo que hacer antes de salir de Contentful: necesito mis claves API para que mi aplicación de Node.js pueda conectarse a la plataforma. Voy a ir a «Configuración» > «Claves API», haré clic en «Añadir clave API», le pondré un nombre para acordarme más tarde para qué sirve y generaré las claves.

Pantalla de configuración de claves de la API de Contentful para generar un token de la API de distribución de contenidos

Voy a dejar esta pestaña abierta, porque dentro de un momento voy a tener que copiar el ID del espacio y el token de acceso a la API de distribución de contenidos.

Paso 2: Configurar el proyecto de Node.js

Ahora vamos con el backend en sí. Antes de nada, necesito tener Node.js instalado en mi ordenador.

Estoy trabajando en el portátil de la oficina, que tiene restricciones informáticas, así que, como siempre, voy a descargar la versión binaria independiente de Node.js de nodejs.org en lugar de ejecutar un instalador normal.

Página de descarga de Node.js para el binario independiente de Windows

En cuanto se haya descargado, lo descomprimiré en mi carpeta de Descargas.

Archivos binarios de Node.js descomprimidos en la carpeta «Descargas»

Al abrir la carpeta del proyecto en la línea de comandos

, voy a crear una carpeta para este proyecto en mi escritorio y la llamaré simplemente «headless-blog».

Entonces abriré el Símbolo del sistema y me iré a esa carpeta:

cd C:\Users\abdulrehman\Desktop\headless-blog

En la línea de comandos, ve a la carpeta del proyecto «headless-blog»

Indicar a la Línea de comandos dónde

está

el archivo binario de Node

Como la Línea de comandos no sabe dónde está realmente Node en mi ordenador, se lo voy a indicar manualmente:

set PATH=%PATH%;C:\Users\abdulrehman\Downloads\node-v24.18.0-win-x64\node-v24.18.0-win-x64

Símbolo del sistema con la variable PATH apuntando al archivo binario de Node.js

Para asegurarme de que realmente funciona, voy a ejecutar:

node -v
npm -v

Ambos comandos muestran los números de versión, así que ya puedo seguir adelante.

Salida del símbolo del sistema que muestra los números de versión de Node.js y npm

Crear el proyecto de Node.js

Primero voy a inicializar un proyecto sencillo de Node.js:

npm init -y

Salida del símbolo del sistema tras ejecutar «npm init -y»

Entonces voy a instalar todo lo que este proyecto realmente necesita: Express para gestionar el enrutamiento, EJS para generar HTML, el SDK oficial de Contentful para recuperar contenido, un renderizador de texto enriquecido para convertir el formato de contenido de Contentful a HTML y dotenv para gestionar mis claves de API a nivel local.

npm install express ejs contentful @contentful/rich-text-html-renderer dotenv

Resultado de la línea de comandos tras instalar Express, EJS, Contentful y dotenv

Paso 3: Obtener datos y crear una interfaz de usuario limpia

Ahora voy a abrir la carpeta de mi proyecto en VS Code. Para ello, voy a ir a «Archivo» > «Abrir carpeta» y voy a seleccionar mi carpeta «headless-blog».

Abre el menú «Archivo» de VS Code para seleccionar la carpeta del proyecto «headless-blog»

Vale, ya tengo mi proyecto abierto en VS Code, así que ahora es el momento de empezar a escribir la lógica del backend.

Proteger las claves de la API

Lo primero que quiero hacer es guardar las claves de Contentful en algún lugar seguro del proyecto. Para ello, en la raíz de la carpeta de mi proyecto, voy a crear un nuevo archivo llamado .env y pegaré lo siguiente:

CONTENTFUL_SPACE_ID=your_space_id_here
CONTENTFUL_ACCESS_TOKEN=your_content_delivery_api_access_token_here

Archivo .env de VS Code con el ID del espacio de Contentful y el token de acceso

Ahora bien, como estas son mis claves reales, no quiero que estén en mi repositorio público de GitHub para que cualquiera pueda acceder a ellas. Para evitarlo, voy a crear un archivo más en la raíz de mi proyecto llamado .gitignore y pegaré lo siguiente:

node_modules
.env

Esto le dice a Git que se salte ambos archivos cada vez que suba mi proyecto. «node_modules» porque solo son paquetes descargados, no hay razón para subirlos. Y «.env» porque ese es el archivo que contiene mis claves reales de Contentful, así que al excluirlo me aseguro de que nunca acaben en ningún sitio público.

Configuración del cliente de Contentful

Ahora necesito algo que conecte mi app con Contentful. Para ello, voy a crear una carpeta llamada «lib» en la raíz del proyecto y, dentro de ella, un archivo llamado «contentful.js».

require('dotenv').config();
const contentful = require('contentful');
const client = contentful.createClient({
 space: process.env.CONTENTFUL_SPACE_ID,
 accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
 });
module.exports = { client };

Archivo contentful.js de VS Code para configurar la conexión del cliente de Contentful

En realidad, eso es todo lo que hace este archivo: solo configura la conexión una vez, para que pueda importarlo dondequiera que necesite extraer datos.

Creación de la interfaz de usuario del blog

Aquí es donde voy a crear el servidor propiamente dicho: se conecta a Contentful, recupera las entradas del blog y las pasa a una plantilla de página para que se muestren.

Voy a crear un archivo llamado server.js en la carpeta raíz de mi proyecto y voy a pegar esto ahí:

const express = require('express');
const path = require('path');
const { client } = require('./lib/contentful');
const { documentToHtmlString } = require('@contentful/rich-text-html-renderer');

const app = express();
const PORT = process.env.PORT || 3000;

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, 'public')));

app.get('/', async (req, res) => {
  try {
    const response = await client.getEntries({ content_type: 'pageBlogPost' });

    const posts = response.items.map((post) => ({
      title: post.fields.title,
      contentHtml: post.fields.content
        ? documentToHtmlString(post.fields.content)
        : null,
    }));

    res.render('index', { posts });
  } catch (err) {
    console.error(err);
    res.status(500).send('Something went wrong fetching posts.');
  }
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Este archivo se conecta a Contentful, recupera todas las entradas con el ID del tipo de contenido «pageBlogPost» (que se encuentra igual que antes: dentro del modelo «Content», abriendo la página «Blog post» y copiando el ID) y envía esos datos a una plantilla llamada «index» para convertirlos en HTML. Esa plantilla aún no existe, así que la crearé a continuación.

Voy a crear una carpeta llamada «views» en la raíz de mi proyecto y, dentro de ella, un archivo llamado «index.ejs». Voy a pegar esto en él:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Headless CMS Blog</title>
  <link rel="stylesheet" href="/style.css">
</head>
<body>
  <main>
    <h1>My Headless CMS Blog</h1>
    <div class="posts">
      <% posts.forEach(post => { %>
        <article class="post-card">
          <h2><%= post.title %></h2>
          <% if (post.contentHtml) { %>
            <div class="post-content"><%- post.contentHtml %></div>
          <% } %>
        </article>
      <% }) %>
    </div>
  </main>
</body>
</html>

Plantilla «index.ejs» de VS Code para mostrar los títulos y el contenido de las entradas del blog

Esta es la página que se ve realmente en el navegador. Recorre todas las entradas que envía server.js, mostrando el título y, debajo, el contenido si lo hay.

Voy a crear otra carpeta llamada «public» y, dentro de ella, un archivo llamado «style.css». Voy a pegar esto ahí:

body {
  font-family: sans-serif;
  background-color: #f9fafb;
  margin: 0;
  padding: 40px 20px;
}

main {
  max-width: 700px;
  margin: 0 auto;
}

h1 {
  text-align: center;
  margin-bottom: 30px;
}

.post-card {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.post-card h2 {
  margin-top: 0;
}

Archivo style.css de VS Code con estilos básicos para las fichas del blog

Esto es lo justo para que la página no parezca un texto sin formato cuando la cargue en el navegador.

Probando lo que hemos creado

Es hora de ver si algo de esto funciona de verdad. Voy a añadir un script de inicio en package.json para no tener que escribir el comando completo de Node cada vez:

"scripts": {
 "start": "node server.js"
 }

Archivo package.json con el script «npm start» añadido

Luego, de vuelta en la línea de comandos:

npm start

Y voy a abrir http://localhost:3000 en el navegador para ver qué pasa.

Y ahí están, las mismas entradas de ejemplo de la plantilla de Contentful, apareciendo directamente en la página.

Vista previa en el navegador local del blog «headless» que se ejecuta en localhost 3000

Esto confirma que la conexión funciona. Contentful ha devuelto los datos de las entradas y el servidor Express los ha convertido a HTML en la página.

Paso 4: Subir el proyecto a GitHub

Antes de implementarlo en ningún sitio, quiero subirlo primero a GitHub.

Voy a crear un nuevo repositorio allí.

Luego, de vuelta en la línea de comandos, voy a ejecutar estos comandos uno por uno:

git init
git add .
git commit -m "First commit"
git branch -M main
git remote add origin https://github.com/abdulrehman293/nodejs-headless-cms
git push -u origin main

Voy a volver al repositorio y a actualizarlo, y sí, está todo ahí, menos el .env archivo y node_modules, que es justo como tiene que ser.

Repositorio de GitHub donde se pueden ver los archivos del proyecto «headless-blog» que se han subido

Paso 5: Conectar Cloudways con GitHub

A estas alturas, mi proyecto ya funciona en el entorno local y también lo he subido a GitHub. Ahora lo voy a pasar del entorno local a un servidor en producción. Para ello, voy a usar el alojamiento gestionado de Node.js de Cloudways, diseñado específicamente para desplegar proyectos como este directamente desde un repositorio de Git.

En el panel de control, voy a hacer clic en «Node.js » en el menú de la izquierda y, después, voy a pulsar «Iniciar ahora».

Pantalla de inicio del alojamiento Node.js en el panel de control de Cloudways

A partir de ahí, elegiré un plan. Este proyecto no requiere mucha potencia, así que el plan Starter me viene de perlas.

Selección del plan Starter de Cloudways para el alojamiento de Node.js

Esto me lleva a la pantalla «Implementa tu aplicación web Node.js ». Voy a hacer clic en «Conectar vía Git», iniciaré sesión en GitHub cuando me lo pida y, una vez autorizada la implementación de Cloudways, elegiré mi repositorio «nextjs-headless-cms» de la lista y seguiré adelante.

Pantalla «Cloudways Connect Via Git» con el repositorio de GitHub seleccionado

Paso 6: Implementar la aplicación y ponerla en producción

En esta siguiente parte le digo a Cloudways qué es este proyecto y cómo ejecutarlo.

Voy a configurar «Framework Preset» en «Express», ya que eso es exactamente lo que es este backend. Para la versión de Node, «Node 24 (LTS)» es la opción correcta aquí, ya que es la línea de soporte a largo plazo activa actualmente. El «Directorio raíz» se deja por defecto.

Configuración de implementación de Cloudways para el framework preconfigurado y la versión de Node

A continuación, haré clic en «Cambiar» en la sección «Configuración de compilación y salida» para desplegarla y, después, configuraré el «Gestor de paquetes» como npm, igual que el que uso en mi ordenador. En «Archivo de entrada», pondré server.js, el mismo archivo que inicia todo a nivel local.

Configuración de compilación y salida de Cloudways con el gestor de paquetes y el archivo de entrada

Ahora, como mi archivo .env nunca llegó a subirse a GitHub a propósito, tengo que volver a añadir aquí manualmente esas claves de Contentful. Voy a «Variables de entorno», le doy a «Añadir» e introduzco tanto CONTENTFUL_SPACE_ID como CONTENTFUL_ACCESS_TOKEN, con los mismos valores que en mi archivo local.

Pantalla de variables de entorno de Cloudways para añadir claves de la API de Contentful
Lista de variables de entorno de Cloudways con las claves de Contentful añadidas

También puedo importar el archivo .env desde la carpeta de mi proyecto en el ordenador si no me apetece pegar las claves a mano.

Una vez rellenado, le doy a «Deploy Now».

A partir de aquí, Cloudways extrae el código directamente de GitHub, instala las dependencias e inicia la aplicación utilizando el archivo de entrada que le he indicado. No hay ningún paso de compilación, ya que este proyecto no lo necesita.

Progreso de la implementación en Cloudways al recuperar el código de GitHub

El momento de la verdad

En cuanto la implementación aparezca como «correcta», abriré la URL temporal de Cloudways que ha generado.

Pantalla de Cloudways que indica que la implementación se ha realizado con éxito y muestra la URL temporal del sitio en producción
El blog del CMS sin interfaz está activo en la URL de Cloudways y muestra entradas de ejemplo

Y ahí está. Las mismas entradas de blog de muestra de Contentful, ahora servidas en directo desde Cloudways en lugar de estar almacenadas en mi portátil. El contenido realiza todo el recorrido, desde Contentful, pasando por mi servidor Express, hasta una URL pública que cualquiera puede visitar.

Blog en directo con un CMS sin interfaz que muestra entradas del blog de Contentful

Conclusión

En resumen, este es el proceso completo para crear un CMS sin interfaz gráfica con Node.js. Expliqué por qué Node.js puro es una excelente opción para esto, repasé las opciones de CMS más populares, tanto las autoalojadas como Strapi como las alojadas como Contentful, y utilicé Contentful para la implementación en este caso.

También te he enseñado cómo montar un pequeño backend en Express que recupera artículos de un CMS, los procesa con EJS, lo he probado localmente y luego lo he puesto en producción en Cloudways.

He subido el proyecto terminado a mi GitHub, así que no dudes en clonarlo y reutilizar el código. Y si quieres implementar algo similar por tu cuenta, nuestro alojamiento gestionado de Node.js se encarga precisamente de este flujo de trabajo: conecta tu repositorio, elige tu configuración preestablecida del framework y ya estás en producción.

P. ¿Node.js es un CMS?

No. Node.js es solo un entorno de ejecución de JavaScript, no un sistema de gestión de contenidos en sí mismo. Dicho esto, algunas plataformas populares de CMS «headless», como Strapi, KeystoneJS y Payload, están desarrolladas con Node.js. Otras, como Contentful y Sanity, están alojadas por separado y una aplicación de Node.js las utiliza a través de una API.

P. ¿Cuál es el mejor CMS «headless» para Node.js?

Depende de lo que busques. Si quieres alojarlo tú mismo y tener todo bajo tu control de principio a fin, Strapi es una buena opción, y está desarrollado con el propio Node.js. Si prefieres evitar tener que alojar un CMS y simplemente recuperar el contenido a través de una API, Contentful o Sanity te permiten hacerlo más rápido.

P. ¿Un CMS sin interfaz gráfica ayuda con el SEO?

Sí, es posible. El CMS almacena tu contenido, y la forma en que lo renderizas en el servidor determina su indexación. El HTML renderizado en el servidor, como el que este proyecto crea con Express y EJS, suele ser fácil de leer para los motores de búsqueda.

P. ¿Tengo que usar Express con Node.js para esto?

No, es solo que Express es una de las opciones más habituales para crear un backend con Node.js. Podrías usar Fastify, Koa o incluso el módulo integrado de Node, http; la idea principal de recuperar datos de un CMS sin interfaz gráfica y mostrar el resultado es la misma en cualquier caso.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Start Growing with Cloudways Today.

Our Clients Love us because we never compromise on these

[email protected]

Abdul es un experto en tecnología, aficionado al café y al marketing creativo al que le encanta estar al día de las últimas actualizaciones de software y aparatos tecnológicos. También es un hábil escritor técnico capaz de explicar conceptos complejos de forma sencilla para un público amplio. Abdul disfruta compartiendo sus conocimientos sobre el sector de la Nube a través de manuales de usuario, documentación y entradas de blog.

×

Webinar: How to Get 100% Scores on Core Web Vitals

Join Joe Williams & Aleksandar Savkovic on 29th of March, 2021.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Want to Experience the Cloudways Platform in Its Full Glory?

Take a FREE guided tour of Cloudways and see for yourself how easily you can manage your server & apps on the leading cloud-hosting platform.

Start my tour