Blog de tecnología, administración de sistemas y redes para profesionales IT.
tengoping.com · Artículos · Categorías
| Herramienta | Uso |
|---|---|
| Astro 5 | Framework web estático |
| MDX | Markdown con componentes |
| Pagefind | Búsqueda estática (~15KB) |
| Shiki | Resaltado de sintaxis con temas duales |
| giscus | Comentarios vía GitHub Discussions |
| Claude | Asistencia en diseño y desarrollo |
# Clonar el repositorio
git clone https://github.com/Psycomy/tengoping.com.git
cd tengoping.com
# Instalar dependencias
npm install
# Servidor de desarrollo
npm run dev # localhost:4321
# Build de producción
npm run build # genera ./dist/
# Preview local
npm run previewLa búsqueda (Pagefind) solo funciona tras ejecutar
npm run build, ya que indexa el HTML generado.
El script scripts/postbuild.mjs permite habilitar reporting de violaciones CSP de forma opcional:
CSP_REPORT_ENDPOINT(opcional): URL HTTPS del endpoint receptor de reportes.CSP_REPORT_GROUP(opcional): nombre del grupo de reporting. Por defecto:csp.
Si CSP_REPORT_ENDPOINT no está definido (o no es una URL HTTPS válida), el build sigue funcionando y
se genera CSP sin report-to.
Crea un archivo .md o .mdx en src/content/blog/:
---
title: 'Título del artículo'
description: 'Descripción breve para SEO y tarjetas'
author: 'antonio'
pubDate: 2025-03-01
updatedDate: 2025-04-15
category: 'Linux'
tags: ['SSH', 'Seguridad']
image: '../../assets/images/mi-imagen.jpg'
draft: false
---
Contenido del artículo en Markdown...| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
title |
string | Sí | Título del artículo |
description |
string | Sí | Descripción para SEO |
author |
string | Sí | ID del autor (ver src/data/authors.json) |
pubDate |
date | Sí | Fecha de publicación |
updatedDate |
date | No | Fecha de última actualización (se muestra en el artículo) |
category |
string | Sí | Categoría principal |
tags |
string[] | Sí | Array de etiquetas |
image |
string | No | Ruta a imagen destacada |
draft |
boolean | No | true para ocultar el artículo |
El script scripts/import_image.py convierte la imagen a WebP, la redimensiona si supera 750px de ancho y genera el snippet listo para pegar:
# Activar el entorno virtual (primera vez: python3 -m venv scripts/.venv && scripts/.venv/bin/pip install Pillow)
source scripts/.venv/bin/activate
python3 scripts/import_image.py /ruta/a/imagen.pngEl script pregunta de forma interactiva:
- A qué artículo pertenece la imagen
- El texto alternativo (
alt) - El tipo de inserción: imagen suelta o figura con caption
Al terminar muestra el snippet que debes copiar al artículo y guarda el WebP en public/images/blog/<slug-post>/.
Funciona en .md y .mdx. La imagen se sirve desde public/:
Requiere que el archivo sea .mdx. Muestra la imagen con estética de terminal (cabecera $ filename, borde, caption opcional).
import Figure from '@components/Figure.astro';
<Figure
src="/images/blog/mi-post/nombre-imagen.webp"
alt="Descripción de la imagen"
caption="Texto de caption opcional"
/>La imagen destacada del artículo (
imageen el frontmatter) es independiente y apunta asrc/assets/images/, no apublic/.
Edita src/data/authors.json:
{
"id": "nuevo-autor",
"name": "Nombre Apellido",
"avatar": "/images/nuevo-autor.svg",
"bio": "Biografía completa del autor.",
"bioShort": "Rol breve",
"social": {
"twitter": "https://twitter.com/usuario",
"github": "https://github.com/usuario",
"linkedin": "https://linkedin.com/in/usuario"
}
}Los comentarios usan giscus, que almacena las conversaciones en GitHub Discussions de este repositorio. La configuración está en src/components/GiscusComments.astro.
src/
├── components/ # Header, Footer, ArticleCard, ShareButtons...
├── content/
│ └── blog/ # Artículos en Markdown/MDX
├── data/ # authors.json, site.json, navigation.ts
├── layouts/ # BaseLayout, ArticleLayout
├── pages/
│ ├── blog/ # Listado paginado + artículos individuales
│ ├── categorias/ # Páginas por categoría
│ ├── etiquetas/ # Páginas por etiqueta
│ └── autor/ # Páginas de autor
├── styles/ # CSS global (temas claro/oscuro)
├── utils/ # Helpers TypeScript
└── content.config.ts # Schema de Content Collections
public/
├── fonts/ # JetBrains Mono (auto-alojada)
├── manifest.json # PWA manifest
├── sw.js # Service worker (cache-first assets, network-first HTML)
└── _headers # Cabeceras de seguridad para Cloudflare Pages
- SEO: OG images, RSS con enclosures, JSON-LD (BlogPosting, WebSite, Organization)
- PWA: manifest + service worker con estrategia de caché híbrida
- Compartir: botones nativos para Twitter/X, Telegram, WhatsApp, Reddit y LinkedIn
- Seguridad: cabeceras CSP, X-Frame-Options, Permissions-Policy vía
_headers - Búsqueda: indexación estática con Pagefind post-build
- Comentarios: giscus (GitHub Discussions)
- Accesibilidad: landmarks ARIA, navegación por teclado, breadcrumbs
Inspirado en la estética de terminal:
- Tipografía monoespaciada (JetBrains Mono) en todo el sitio
- Sin bordes redondeados, sin sombras — bordes sólidos
- Encabezados con prefijos markdown (
##,###) - TOC con caracteres de árbol (
├──,└──) - Badges rectangulares, links en formato
[bracket] - Tema claro y oscuro con cambio automático
El sitio se despliega automáticamente en Cloudflare Pages con cada push a main.
| Configuración | Valor |
|---|---|
| Build command | npm run build |
| Output directory | dist |
| Node version | 24 |
Este blog ha sido diseñado y desarrollado con la asistencia de Claude de Anthropic, utilizando Claude Code como herramienta principal de desarrollo.
Contenido del blog bajo CC BY-NC-SA 4.0. Código fuente bajo MIT.
