Backend for Frontend (BFF) para Strapi 5
Este proyecto Next.js actúa como un Backend for Frontend (BFF) que se sitúa entre tus aplicaciones cliente y tu instancia de Strapi 5. Proporciona una capa de abstracción que oculta los detalles de implementación de Strapi y permite un mejor control sobre las peticiones.
🏗️ Arquitectura
Cliente (Web/Mobile)
↓
Backend for Frontend (Next.js)
↓
Strapi 5 CMS
🚀 Configuración
1. Variables de Entorno
Crea o edita el archivo .env.local en la raíz del proyecto:
STRAPI_API_URL=http://localhost:1337
STRAPI_API_TOKEN=tu_token_de_strapi
2. Instalación
npm install
3. Desarrollo
npm run dev
El servidor estará disponible en http://localhost:3000.
📡 API Endpoints
Health Check
Verifica el estado de la conexión con Strapi:
GET /api/health
Respuesta exitosa:
{
"status": "healthy",
"strapi": "connected",
"timestamp": "2025-11-22T10:00:00.000Z"
}
Proxy de Strapi
Todos los endpoints de Strapi están disponibles a través del proxy:
GET /api/strapi/{endpoint}
POST /api/strapi/{endpoint}
PUT /api/strapi/{endpoint}
DELETE /api/strapi/{endpoint}
Ejemplos:
Obtener artículos:
GET /api/strapi/articles
Obtener un artículo específico:
GET /api/strapi/articles/1
Con query parameters (populate, filters, etc.):
GET /api/strapi/articles?populate=*&filters[slug][$eq]=mi-articulo
Crear un artículo:
POST /api/strapi/articles
Content-Type: application/json
{
"data": {
"title": "Nuevo Artículo",
"content": "Contenido del artículo"
}
}
Actualizar un artículo:
PUT /api/strapi/articles/1
Content-Type: application/json
{
"data": {
"title": "Título actualizado"
}
}
Eliminar un artículo:
DELETE /api/strapi/articles/1
💻 Uso en el Cliente
Desde tu aplicación web:
// Llamar al BFF en lugar de Strapi directamente
const response = await fetch('http://localhost:3000/api/strapi/articles?populate=*');
const data = await response.json();
Desde React/Next.js:
// En un componente de Next.js
async function getArticles() {
const res = await fetch('/api/strapi/articles?populate=*', {
cache: 'no-store' // o usa next: { revalidate: 60 }
});
if (!res.ok) {
throw new Error('Failed to fetch articles');
}
return res.json();
}
export default async function ArticlesPage() {
const { data } = await getArticles();
return (
<div>
{data.map((article) => (
<div key={article.id}>
<h2>{article.title}</h2>
<p>{article.description}</p>
</div>
))}
</div>
);
}
🔧 Cliente de Strapi (Uso Directo)
También puedes usar el cliente de Strapi directamente en tus Server Components o API Routes:
import { strapiClient } from '@/lib/strapi';
// En un Server Component o API Route
async function getData() {
try {
const response = await strapiClient.get('/api/articles?populate=*');
return response.data;
} catch (error) {
console.error('Error fetching data:', error);
throw error;
}
}
Métodos disponibles:
// GET
await strapiClient.get('/api/articles');
// POST
await strapiClient.post('/api/articles', {
data: { title: 'Nuevo artículo' }
});
// PUT
await strapiClient.put('/api/articles/1', {
data: { title: 'Título actualizado' }
});
// DELETE
await strapiClient.delete('/api/articles/1');
📁 Estructura del Proyecto
backend-for-frontend/
├── app/
│ ├── api/
│ │ ├── health/
│ │ │ └── route.ts # Health check endpoint
│ │ └── strapi/
│ │ └── [...path]/
│ │ └── route.ts # Proxy dinámico para Strapi
│ ├── layout.tsx
│ └── page.tsx
├── lib/
│ ├── config/
│ │ └── strapi.config.ts # Configuración de Strapi
│ ├── strapi/
│ │ ├── client.ts # Cliente HTTP para Strapi
│ │ ├── types.ts # Tipos de Strapi
│ │ └── index.ts # Exports públicos
│ └── types/
│ ├── strapi-models.ts # Tipos de tus modelos
│ └── index.ts
├── .env.local # Variables de entorno
├── package.json
└── README.md
🛡️ Ventajas del BFF
- SeguridadEl token de Strapi nunca se expone al cliente