Quick Links — Hub de servicios externos del workspace
Quick Links — Hub de servicios externos del workspace
Plan: s52 · PR 1 de 4 · Autor: @Esquembri · Mergeado: 2026-05-07
Resumen
Quick Links es la primera tool del plan de largo plazo s52 para el workspace interno de CreaRack. Proporciona un hub de atajos CRUD a los servicios externos que usa el equipo (Hetzner, Cloudflare, Dokploy, GitHub, AI providers, monitoring, producto, self-host, Holded), accesible en /tools/quicklinks.
⚠️ Nota de vigencia (24-07-2026): el seed y los comentarios de categorías de abajo documentan el snapshot de mayo 2026 tal como se mergeó el PR. Varios de esos servicios ya NO existen en el equipo: Tailscale → NetBird (s85) · OpenRouter retirado (Regla 8: solo Google AI Studio) · llama-server/EPYC dado de baja (s53) · Proxmox fuera. Los enlaces VIVOS se gestionan desde el propio CRUD de
/tools/quicklinks(los del seed se editan/archivan ahí) — esta página es la doc de la feature, no el inventario de servicios (para eso: [[entity—ops—catalogo-servicios-externos]]).
Sigue el patrón canónico del workspace establecido por notes, tasks y news:
- Tabla D1 con migración versionada
- Cloudflare Pages Function como API REST
- Componente React con
client:loadenvuelto en layout Astro
Arquitectura
Capa de datos — D1
| Migración | Contenido |
|---|---|
0017_create_quick_links.sql | Tabla quick_links con todos los campos, 3 índices |
0018_seed_quick_links.sql | ~25 servicios pre-cargados con INSERT OR IGNORE (idempotente) |
La tabla soporta soft-delete vía columna archived_at (ISO-8601). El campo is_shared = 1 por defecto hace que todos los atajos sean visibles para todo el staff.
Capa de API — CF Pages Functions
| Archivo | Métodos | Ruta |
|---|---|---|
functions/api/quicklinks/index.ts | GET, POST | /api/quicklinks |
functions/api/quicklinks/[id].ts | GET, PUT, DELETE | /api/quicklinks/:id |
Auth: inyectada por el middleware existente de Cloudflare Access — se lee cf-access-authenticated-user-email para poblar owner_id y para el log de actividad (logActivity).
GET list acepta query params:
category— filtra por categoría (ver enum abajo)archived=1— incluye atajos archivados (por defecto excluidos)
PUT parcial: construye SET dinámico campo a campo, evitando COALESCE con sentinels. Soporta archived: true/false para archive/unarchive limpio.
Capa de UI — React + Astro
| Componente | Responsabilidad |
|---|---|
QuickLinksPage.tsx | Estado global, fetch, filtros, layout de grupos |
QuickLinkCard.tsx | Tarjeta bento individual. Favicon via google.com/s2/favicons |
QuickLinkEditModal.tsx | Modal nuevo/editar. Cierre con Escape |
Toggle de densidad: cozy (muestra URL y descripción) / compact (solo label + icono, layout row).
Agrupación: los atajos se muestran agrupados por categoría según el orden canónico definido en CATEGORY_ORDER.
CSS — src/styles/tools.css (nuevo)
Archivo de estilos compartido para todas las tools del workspace (/tools/*). Importado desde AppLayout.astro. Clases principales:
| Clase | Uso |
|---|---|
.tools-bento / .tools-bento-grid | Tarjetas y grid responsive |
.tools-chip / .tools-chip-row | Filtros de categoría |
.tools-seg | Toggle segmentado (densidad) |
.tools-modal-* | Modal backdrop + dialog |
.tools-empty | Estado vacío |
.tools-btn / .tools-btn-primary / .tools-btn-danger | Botones |
.tools-page-header | Cabecera de página con eyebrow |
.tools-section-title | Título de sección por categoría (Oswald, uppercase) |
Categorías
Enum tal como quedó en el PR de mayo (los comentarios son ejemplos de la época — ver nota de vigencia arriba):
type QuickLinkCategory =
| 'infrastructure' // Hetzner, Cloudflare, Dokploy, Proxmox
| 'code' // GitHub repos, issues, Actions
| 'ai' // Anthropic, Google AI Studio, OpenRouter
| 'monitoring' // UptimeRobot, Tailscale
| 'product' // crearack.com PROD/STAGE, Django Admin, Workspace, wikis
| 'selfhosted' // llama-server en tailnet (Gemma 4)
| 'admin' // Holded (ERP)
| 'general' // fallback
Seed inicial (~25 servicios · snapshot mayo 2026)
| Categoría | Servicios pre-cargados |
|---|---|
| infrastructure | Hetzner Cloud, Hetzner Robot, Cloudflare, Dokploy PROD/STAGE |
| code | GitHub CreaRack-Pro, GitHub workspace, Issues, Actions |
| ai | Anthropic Console, Google AI Studio, OpenRouter (retirado después) |
| monitoring | UptimeRobot, Tailscale (→ NetBird desde s85) |
| product | crearack.com, STAGE, Django Admin, Workspace, Wiki Help, Wiki Tech |
| selfhosted | llama-server 8080 (Auto-Plan), llama-server 8081 (Help), llama-help público — todo dado de baja en s53 |
| admin | Holded |
Decisiones tomadas en PR1
| Decisión | Detalle |
|---|---|
| Healthcheck deferido | Status dot por servicio necesita endpoint server-side (CORS). Pendiente PR aparte, no bloquea MVP. |
| Drag-and-drop deferido | Reordenado manual pendiente de PR futuro (plan s52). |
INSERT OR IGNORE en seed | Idempotencia: si la migración se reaaplica no duplica registros. owner_id = 'seed' identifica los registros del seed. |
| SET dinámico en PUT | Evita COALESCE con sentinel values para distinguir “no tocar” vs “set null” en campos nullable. |
| Favicon via Google S2 | https://www.google.com/s2/favicons?domain=<host>&sz=64 — gratuito, sin auth, devuelve PNG. Fallback a iniciales si la URL no parsea. |
Archivos creados / modificados
functions/api/quicklinks/index.ts ← GET list + POST create
functions/api/quicklinks/[id].ts ← GET / PUT / DELETE por id
migrations/0017_create_quick_links.sql ← DDL tabla + índices
migrations/0018_seed_quick_links.sql ← Seed ~25 servicios
src/components/quicklinks/
QuickLinksPage.tsx ← Página principal React
QuickLinkCard.tsx ← Tarjeta bento
QuickLinkEditModal.tsx ← Modal crear/editar
src/pages/tools/quicklinks/index.astro ← Route Astro
src/styles/tools.css ← Estilos compartidos /tools/* (NUEVO)
src/lib/types.ts ← QuickLink + QuickLinkCategory
src/lib/navigation.ts ← Entry en grupo Tools
src/layouts/AppLayout.astro ← Import tools.css
Validaciones de la API
labelrequerido, máx 80 charsurlrequerido, máx 500 charscategorydebe pertenecer aVALID_CATEGORIES; si inválido → fallback'general'en POST, ignorado en PUTarchived: true→ escribe ISO timestamp;archived: false→archived_at = NULL
Plan s52 — contexto
Este es el PR 1 de 4 del plan s52 del workspace. Los siguientes PRs (2-4) añadirán más tools siguiendo los mismos patrones de tools.css, Pages Functions y D1.
Véase también
- [[workspace—que-es-workspace]]
- [[entity—workspace—table—quick-links]]
- [[entity—ops—catalogo-servicios-externos]]