Administración del Blog con decapcms

decapcms es una excelente elección para crear un blog sencillo a las empresas. Brinda una interfaz muy limpia para que el o los administradores del blog para escribir sus publicaciones, mientras a ti te mantiene todo guardado como archivos `.md` en tu proyecto.

https://decapcms.org/

Utilizar decapcms en tu proyecto de astro

Paso 1: Crear la carpeta del administrador

Paso 2: El archivo public/admin/index.html

Abre public/admin/index.html y pega este código (es la interfaz de Decap CMS cargada desde un CDN estático):


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Panel de Administración
  </head>
  <body>
    <!-- Carga la app de Decap CMS -->
   <script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
  </body>
</html>
  

Paso 3: El archivo public/admin/config.yml

Abre public/admin/config.yml y define la estructura de tus publicaciones. Puedes adaptar las rutas y campos a tu gusto:


  backend:
  name: git-gateway
  branch: main # O "master", según tu rama de GitHub

media_folder: "src/assets/images" # Dónde se almacenarán las imágenes
public_folder: "src/assets/images" # Atributo src para los medios cargados

collections:
  - name: "blog"
    label: "Entradas del Blog"
    folder: "src/content/posts"   # Ruta exacta a tus archivos .md
    create: true                # Permite al usuario crear nuevos posts
    slug: "{{slug}}"
    fields:
      - { label: "Título", name: "title", widget: "string" }
      - { label: "Fecha de publicación", name: "pubDate", widget: "datetime" }
      - { label: "Descripción", name: "description", widget: "text" }
      - { label: "Autor", name: "author", widget: "string", default: "Admin" }
      - { label: "Imagen destacada", name: "image", widget: "image", required: false }
      - { label: "Etiquetas", name: "tags", widget: "list", required: false }
      - { label: "Contenido", name: "body", widget: "markdown" }
  

Paso 4: Probar en local

Para poder probar la interfaz en local sin necesidad de configurar autenticaciones de GitHub:

  1. Instala un pequeño proxy local para pruebas como administrador:

    pnpm add -D decap-server
  2. Añade un script a tu package.json:

    "scripts": {
      "dev": "astro dev",
      "cms": "decap-server"
    }        
          
  3. Abre dos terminales:

    • En la primera ejecuta: pnpm dev
    • En la segunda ejecuta: pnpm cms
  4. Entra en tu navegador a: http://localhost:4321/admin/index.html

    Decap crea automáticamente el archivo Markdown en tu proyecto, pero Astro necesita dos cosas en el código para que esa entrada se vea en la web:

    • La página dinámica de la entrada individual (para ver el post completo al hacer clic)
    • La página de listado de entradas (un índice o blog donde se listen todos los posts creados).

Recordemos cómo se debe tratar una colección en Astro para que todo conecte automáticamente:

1. La plantilla para el post individual

Crear un archivo en esta ruta del proyecto: src/pages/posts/[slug].astro (o la ruta donde le dijiste a Decap que guardara los archivos).

Pega un código como este para que lea cualquier post que el usuario cree desde Decap:


import { getCollection } from 'astro:content';

// 1. Obtener todos los posts de la colección
export async function getStaticPaths() {
  const posts = await getCollection('posts'); // 'posts' debe coincidir con el nombre en tu src/content/config.ts
  return posts.map(post => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content } = await post.render();
---

<h1>{post.data.title}</h1>
<p><small>{post.data.pubDate}</small></p>


<Content />    

2. La página con el listado de todas las entradas

Crea o edita la página de tu blog (por ejemplo, src/pages/blog.astro):


---
import { getCollection } from 'astro:content';

// Obtener todas las entradas guardadas
const allPosts = await getCollection('posts');
---

<h1>Blog</h1>

<ul>
  {allPosts.map(post => (
    <li>
      <a href={`/posts/${post.slug}/`}>
        <h2>{post.data.title}</h2>
      </a>
      <p>{post.data.description}</p>
    </li>
  ))}
</ul>  

¿Cómo se conecta todo?