{"id":18493092,"url":"https://github.com/tomascuevas/whiteblack","last_synced_at":"2026-04-11T18:02:57.891Z","repository":{"id":109795022,"uuid":"591684262","full_name":"TomasCuevas/whiteblack","owner":"TomasCuevas","description":"Mi blog personal donde comparto artículos sobre mi aprendizaje y experiencia en el mundo del desarrollo de software. 👍","archived":false,"fork":false,"pushed_at":"2023-07-31T18:03:41.000Z","size":5398,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-25T16:09:51.478Z","etag":null,"topics":["blog","markdown","markdown-to-html","nextjs","open-graph-generator","reactjs","responsive-design","tailwind","typescript"],"latest_commit_sha":null,"homepage":"https://whiteblack.vercel.app","language":"MDX","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomasCuevas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-01-21T14:35:07.000Z","updated_at":"2023-07-11T19:10:36.000Z","dependencies_parsed_at":"2023-04-27T11:48:39.966Z","dependency_job_id":null,"html_url":"https://github.com/TomasCuevas/whiteblack","commit_stats":null,"previous_names":["tomascuevas/whiteblack"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2Fwhiteblack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2Fwhiteblack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2Fwhiteblack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2Fwhiteblack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomasCuevas","download_url":"https://codeload.github.com/TomasCuevas/whiteblack/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239207415,"owners_count":19599966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blog","markdown","markdown-to-html","nextjs","open-graph-generator","reactjs","responsive-design","tailwind","typescript"],"created_at":"2024-11-06T13:12:39.152Z","updated_at":"2026-04-11T18:02:57.884Z","avatar_url":"https://github.com/TomasCuevas.png","language":"MDX","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Whiteblack — Blog de programación con Next.js + MDX\n\nBlog técnico construido con Next.js 13, MDX y Tailwind CSS. Los artículos se escriben en MDX con frontmatter, se procesan estáticamente (SSG) y se renderizan con componentes React personalizados. Incluye SEO on-page, imágenes Open Graph dinámicas con `@vercel/og`, tema claro/oscuro, listado/paginación y navegación por categorías.\n\n- Producción estática: `getStaticProps` / `getStaticPaths`\n- Artículos en `src/content/articles/*.mdx`\n- Categorías en `src/content/categories/*.md`\n- SEO/OG centralizado en `src/components/layout/LayoutHead/LayoutHead.tsx`\n- OG dinámico en `src/pages/api/og.tsx` (Edge Runtime)\n- Theming con `next-themes`\n- Tailwind vía `tailwind.config.js`\n\n---\n\n### Tabla de contenido\n\n- [Tecnologías](#tecnologías)\n- [Arquitectura y flujo](#arquitectura-y-flujo)\n- [Estructura de carpetas](#estructura-de-carpetas)\n- [Instalación y ejecución](#instalación-y-ejecución)\n- [Variables de entorno](#variables-de-entorno)\n- [Añadir un artículo (MDX)](#añadir-un-artículo-mdx)\n- [Añadir una categoría](#añadir-una-categoría)\n- [Componentes MDX disponibles](#componentes-mdx-disponibles)\n- [SEO y Open Graph](#seo-y-open-graph)\n- [Estilos y theming](#estilos-y-theming)\n- [Paginación y feeds](#paginación-y-feeds)\n- [Rutas y páginas](#rutas-y-páginas)\n- [Licencia y autor](#licencia-y-autor)\n\n---\n\n### Tecnologías\n\n- Next.js 13.1 (pages router), React 18\n- MDX: `gray-matter`, `next-mdx-remote`, `rehype-highlight`\n- Estilos: Tailwind CSS, fuentes de Google\n- Theming: `next-themes`\n- OG dinámico: `@vercel/og` (API Edge)\n- Utilidades: `reading-time`, `uuid`, `react-icons`\n\n---\n\n### Arquitectura y flujo\n\n1) Fuentes de contenido\n- Artículos: `src/content/articles/*.mdx` con frontmatter (ver más abajo).\n- Categorías: `src/content/categories/*.md` (frontmatter YAML).\n\n2) Transformación MDX ➜ HTML\n- `src/utils/mdxArticlesTransform/mdxArticlesTransform.ts`\n  - `getAllArticleFiles()`: lista los archivos MDX.\n  - `getArticleFileBySlug(slug)`: extrae `frontmatter` y `content` con `gray-matter`, serializa MDX con `next-mdx-remote/serialize` y `rehype-highlight`. Calcula `readingTime`.\n  - `getAllArticleFilesMetadata(category?)`: compila metadatos ordenados por fecha, serializa `cardDescription` para previsualizaciones.\n- `src/utils/mdxCategoriesTransform/mdxCategoriesTransform.ts`\n  - `getAllCategoryFiles()`, `getCategoryFileBySlug(slug)`, `getAllCategoryFilesMetadata()`.\n\n3) Renderizado\n- Artículo: `src/pages/[slug].tsx` renderiza con `MDXRemote`, aplica tema y genera sidebar de contenidos con `getAllSectionsToSidebar`, `observers`, `PTagPreviousH2`.\n- Listados: `src/pages/index.tsx` (últimos artículos), `src/pages/categorias.tsx`, `src/pages/categoria/[category].tsx`.\n\n4) SEO / OG\n- `src/components/layout/LayoutHead/LayoutHead.tsx`: meta tags Open Graph y Twitter.\n- `src/pages/api/og.tsx`: genera imágenes OG on-the-fly (Edge). Usa fuentes de `/public/fonts` y assets de `/public/images`.\n\n---\n\n### Estructura de carpetas\n\n- `src/content/articles/`: artículos MDX.\n- `src/content/categories/`: categorías MD.\n- `src/pages/`: rutas Next.js\n  - `index.tsx`, `[slug].tsx`, `categorias.tsx`, `categoria/[category].tsx`, `api/og.tsx`.\n- `src/components/`: UI y piezas de artículo\n  - Artículo: `ArticleHeader`, `ArticleFooter`, `ArticleCard`, `ArticlesFeed`, `ArticlesFeedByCategory`.\n  - Layout: `MainLayout`, `Header`, `MobileSidebar`, `Footer`, `LayoutHead`.\n  - MDX: `MDXComponents` + componentes `Deploy`, `Repository`, `Section`, `Link`.\n  - UI: `ThemeSwitch`, `PaginationButtons`, `SectionTitle`, `MeCard`, `Icon`.\n- `src/utils/`: transformadores MDX, sidebar, observers, etc.\n- `src/styles/`: estilos globales y de artículos.\n- `public/images/categories/*.svg`: iconos por categoría.\n- `public/images/og/*.jpg`: imágenes OG estáticas (home/categorías).\n- `docs/`: documentación complementaria (`ARTICLES_METADATA.md`, `MDX_TO_HTML.md`).\n\n---\n\n### Instalación y ejecución\n\nRequisitos: Node.js 16+ recomendado.\n\n```bash\n# instalar dependencias\nnpm install\n\n# desarrollo\nnpm run dev\n\n# construir producción\nnpm run build\n\n# servir build\nnpm start\n\n# lint\nnpm run lint\n```\n\n---\n\n### Variables de entorno\n\nCrear `.env.local` en la raíz:\n\n```bash\nNEXT_PUBLIC_URL=https://tu-dominio.com\n```\n\n- Se usa en `LayoutHead` para `og:url`, `twitter:url` y para resolver `og:image`.\n- También lo usa `api/og.tsx` para cargar assets (`/wb.svg`, `/images/categories/...`).\n\nEn desarrollo puedes usar `http://localhost:3000`, pero para OG en producción debe apuntar al dominio público.\n\n---\n\n### Añadir un artículo (MDX)\n\n1) Crear un archivo en `src/content/articles/mi-articulo.mdx` con este frontmatter mínimo:\n\n```md\n---\nauthor: \"Tu Nombre\"\nlink: \"https://tu-linkedin-o-web\"\ntitle: \"Título del artículo\"\ndate: \"2023-12-31\"\ndescription: \"Descripción corta para SEO.\"\ncardDescription: \"Primer párrafo o resumen que se verá en la tarjeta de listado.\"\ncategory: \"react\" # debe existir como categoría (ver abajo)\ntags:\n  - \"react\"\n  - \"hooks\"\nkeywords: \"palabras, clave, separadas, por, comas\"\n---\n```\n\n2) Escribe contenido MDX debajo. Puedes usar los componentes MDX del proyecto (ver sección correspondiente).\n\n3) La página del artículo se generará en `/mi-articulo` usando `getStaticPaths/getStaticProps`.\n\nNotas:\n- `readingTime` se calcula automáticamente.\n- El OG del artículo se genera dinámicamente (`/api/og`) con título, autor, categoría, tags, fecha y tiempo de lectura.\n- Asegúrate de que `category` esté soportada (ver “Añadir una categoría”).\n\n---\n\n### Añadir una categoría\n\n1) Crear `src/content/categories/\u003ccategoria\u003e.md`:\n\n```md\n---\ntitle: Artículos sobre \u003cNombre\u003e\ncategory: \u003cslug-categoria\u003e # p.ej. react, javascript...\nsubtitle: Breve subtítulo\ndescription: Descripción de la categoría.\n---\n```\n\n2) Asegurar icono en `public/images/categories/\u003cslug-categoria\u003e.svg`.\n\n3) Agregar color en `src/data/categoryColors.ts`:\n\n```ts\nexport const categoryColors = {\n  // ...\n  \"\u003cslug-categoria\u003e\": \"#rrggbbaa\",\n};\n```\n\n4) Si es una categoría nueva no listada, añadirla al tipo `ICategories` en `src/interfaces/category/ICategoryMetadata.ts`.\n\nLa lista de categorías se ordena alfabéticamente y la página de categoría se genera en `/categoria/\u003cslug-categoria\u003e`.\n\n---\n\n### Componentes MDX disponibles\n\nEstos componentes están expuestos para usarlos dentro de los `.mdx` vía `MDXComponents`:\n\n- `Section`: bloque semántico que el sistema usa para construir el índice lateral (H2/H3).\n- `Link`: link estilizado con icono.\n- `Repository`: botón “Explorar en GitHub”.\n- `Deploy`: botón “Demostración en línea”.\n\nEjemplos:\n\n```mdx\n\u003cSection\u003e\n## Introducción\n\nTexto...\n\n\u003cLink url=\"https://example.com\"\u003eDocumentación oficial\u003c/Link\u003e\n\u003c/Section\u003e\n\n\u003cRepository url=\"https://github.com/usuario/repositorio\" /\u003e\n\n\u003cDeploy url=\"https://demo.example.com\" /\u003e\n```\n\n---\n\n### SEO y Open Graph\n\n- `src/components/layout/LayoutHead/LayoutHead.tsx` añade:\n  - `og:url`, `og:type`, `og:title`, `og:image`, `twitter:card`, `twitter:url`, etc.\n  - Usa `process.env.NEXT_PUBLIC_URL` + `router.asPath` para URLs canónicas.\n- OG dinámico (`src/pages/api/og.tsx`):\n  - Edge Runtime.\n  - Usa fuentes de `/public/fonts`.\n  - Parámetros: `title`, `author`, `category`, `tags`, `date`, `readingTime`.\n  - Los artículos configuran su `image` como `/api/og?...` automáticamente en `[slug].tsx`.\n\nHome y categorías usan imágenes OG estáticas de `public/images/og/`.\n\n---\n\n### Estilos y theming\n\n- Tailwind con `darkMode: \"class\"`. Config extendido en `tailwind.config.js` (colores, breakpoints `xs`, `mdx`, `sidebar`, `lgx`, tipografías).\n- Fuentes Roboto, Merriweather e Inter se cargan en `_document.tsx`.\n- Theming con `next-themes` (`ThemeProvider` en `_app.tsx`) y el componente `ThemeSwitch`.\n- Estilos específicos para MDX y resaltado en `src/styles/article.css`, `articleCard.css`, `articleSidebar.css` + tema de highlight `atom-one-dark`.\n\n---\n\n### Paginación y feeds\n\n- `ArticlesFeed` pagina de 4 en 4 usando el hook `usePagination`.\n- `ArticlesFeedByCategory` lista todos los artículos de la categoría sin paginar.\n- Botones de paginación en `src/components/ui/PaginationButtons/PaginationButtons.tsx`.\n\n---\n\n### Rutas y páginas\n\n- `/`: últimos artículos (`src/pages/index.tsx`).\n- `/[slug]`: artículo individual (SSG) con índice lateral (secciones H2/H3 observadas dinámicamente).\n- `/categorias`: listado de categorías existentes con al menos un artículo.\n- `/categoria/[category]`: artículos por categoría.\n- `/api/og`: API Edge que devuelve imagen OG.\n\n---\n\n### Licencia y autor\n\n- Autor: Tomás Cuevas — ver enlaces en el `Footer` del sitio (GitHub y LinkedIn).\n- Licencia: no especificada en el repositorio.\n\n---","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomascuevas%2Fwhiteblack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomascuevas%2Fwhiteblack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomascuevas%2Fwhiteblack/lists"}