Cómo crear un blog personal con Next.js y Markdown: Tutorial paso a paso
Crear un blog personal es un excelente proyecto para desarrolladores que quieren practicar habilidades en Next.js, manejo de Markdown para contenido, y despliegue moderno con Vercel. Este tutorial detallado está pensado para principiantes e intermedios que desean construir un blog estático, elegante y fácil de gestionar.
Te guiaré desde la configuración inicial de Next.js, pasando por la integración de archivos Markdown para las publicaciones, hasta la generación de páginas estáticas con getStaticProps
y getStaticPaths
. También te mostraré cómo estilizar tu blog usando Tailwind CSS para un diseño limpio y moderno. Finalmente, aprenderás a desplegar tu sitio en Vercel — la plataforma ideal para proyectos Next.js.
¡Vamos allá! 🚀
Índice
- 1. Preparación del entorno y configuración de Next.js
- 2. Integrar Markdown para manejar las publicaciones
- 3. Crear páginas estáticas con
getStaticProps
ygetStaticPaths
- 4. Estilizar el blog con Tailwind CSS
- 5. Desplegar el blog en Vercel
- Conclusión
1. Preparación del entorno y configuración de Next.js
Primero, vamos a crear el proyecto base con Next.js usando npx para no instalar globalmente dependencias.
1 2 3 4 5 6 7 8 9 10 |
# Crea el proyecto Next.js con el template de TypeScript (opcional) npx create-next-app@latest my-next-blog --typescript # Accede a la carpeta del proyecto default cd my-next-blog # Ejecuta el servidor de desarrollo npm run dev |
Visita http://localhost:3000
y deberías ver la página inicial de Next.js.
Estructura principal del proyecto
pages/
: Carpeta para las páginas y rutas.public/
: Archivos estáticos, como imágenes.styles/
: Hojas de estilos CSS.
2. Integrar Markdown para manejar las publicaciones
Nuestro contenido de blog estará escrito en archivos Markdown (.md
). Usaremos el paquete gray-matter
para extraer metadatos (frontmatter) y remark
para convertir Markdown a HTML.
Paso 1: Instalar dependencias necesarias
1 2 |
npm install gray-matter remark remark-html |
Paso 2: Crear la estructura para las publicaciones
Dentro del proyecto:
- Crea una carpeta llamada
posts/
en la raíz (misma carpeta donde estápages/
). - Allí pondremos todos los archivos Markdown.
Ejemplo de un archivo Markdown en posts/mi-primer-post.md
:
1 2 3 4 5 6 7 8 9 |
--- title: "Mi primer post en Next.js" date: "2024-06-10" --- ¡Hola! Este es el contenido de mi **primer post** en el blog. Puedes escribir todo lo que quieras usando Markdown. |
Paso 3: Leer archivos Markdown
Crea un archivo llamado lib/posts.ts
para funciones relacionadas con las publicaciones.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; const postsDirectory = path.join(process.cwd(), 'posts'); export interface PostData { id: string; title: string; date: string; content: string; } // Obtener lista de posts ordenados por fecha export function getSortedPostsData(): PostData[] { // Lee todos los archivos en la carpeta posts const fileNames = fs.readdirSync(postsDirectory); const allPostsData = fileNames.map(fileName => { // El id es el nombre del archivo sin extensión const id = fileName.replace(/\.md$/, ''); // Leer contenido del archivo Markdown const fullPath = path.join(postsDirectory, fileName); const fileContents = fs.readFileSync(fullPath, 'utf8'); // Usar gray-matter para parsear el frontmatter const matterResult = matter(fileContents); // Retornar los datos combinados return { id, ...(matterResult.data as { title: string; date: string}), content: matterResult.content, }; }); // Ordenar por fecha descendente return allPostsData.sort((a, b) => { if (a.date < b.date) { return 1; } else { return -1; } }); } |
Explicación:
- Leemos todos los archivos
.md
enposts/
. - Extraemos metadatos (como
title
ydate
) con gray-matter. - Devolvemos una lista ordenada por fecha.
3. Crear páginas estáticas con getStaticProps y getStaticPaths
Gracias al sistema de generación estática de Next.js, podemos crear páginas de blog a partir de Markdown en build time, lo que mejora rendimiento y SEO.
Paso 1: Listar posts en la página principal
Edita pages/index.tsx
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import { GetStaticProps } from 'next'; import Link from 'next/link'; import { getSortedPostsData, PostData } from '../lib/posts'; interface HomeProps { allPostsData: PostData[]; } export default function Home({ allPostsData }: HomeProps) { return ( <main className="max-w-3xl mx-auto p-4"> <h1 className="text-4xl font-bold mb-8">Mi Blog Personal</h1> <ul> {allPostsData.map(({ id, date, title }) => ( <li key={id} className="mb-4"> <Link href={`/posts/${id}`}> <a className="text-2xl text-blue-600 hover:underline">{title}</a> </Link> <br /> <small className="text-gray-500">{date}</small> </li> ))} </ul> </main> ); } export const getStaticProps: GetStaticProps = async () => { const allPostsData = getSortedPostsData(); return { props: { allPostsData, }, }; }; |
Explicación:
- Usamos
getStaticProps
para obtener los datos en tiempo de build. - Mostramos una lista con enlaces a cada post según su
id
.
Paso 2: Crear la página dinámica para cada post
En Next.js, las rutas dinámicas usan corchetes:
- Crea un archivo:
pages/posts/[id].tsx
Este archivo renderizará cada post individualmente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
import { GetStaticProps, GetStaticPaths } from 'next'; import { getSortedPostsData, PostData } from '../../lib/posts'; import fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; import { remark } from 'remark'; import html from 'remark-html'; interface PostProps { postData: { id: string; title: string; date: string; contentHtml: string; }; } export default function Post({ postData }: PostProps) { return ( <main className="max-w-3xl mx-auto p-4"> <h1 className="text-4xl font-bold mb-2">{postData.title}</h1> <small className="text-gray-500 mb-8 block">{postData.date}</small> <article className="prose prose-lg" dangerouslySetInnerHTML={{ __html: postData.contentHtml }} /> </main> ); } export const getStaticPaths: GetStaticPaths = async () => { const postsDirectory = path.join(process.cwd(), 'posts'); const fileNames = fs.readdirSync(postsDirectory); // Generamos paths con los ids correspondientemente const paths = fileNames.map(fileName => ({ params: { id: fileName.replace(/\.md$/, ''), }, })); return { paths, fallback: false, }; }; export const getStaticProps: GetStaticProps = async ({ params }) => { const id = params?.id as string; const fullPath = path.join(process.cwd(), 'posts', `${id}.md`); const fileContents = fs.readFileSync(fullPath, 'utf8'); // Usamos gray-matter para obtener metadata y contenido const matterResult = matter(fileContents); // Convertimos markdown a HTML con remark const processedContent = await remark() .use(html) .process(matterResult.content); const contentHtml = processedContent.toString(); return { props: { postData: { id, title: matterResult.data.title, date: matterResult.data.date, contentHtml, }, }, }; }; |
Explicación:
getStaticPaths
define las rutas dinámicas en base a archivos Markdown.getStaticProps
carga el contenido convertido a HTML para cada post.- Usamos
dangerouslySetInnerHTML
para renderizar el contenido HTML generado (asegúrate que proviene de fuente confiable).
4. Estilizar el blog con Tailwind CSS
Tailwind CSS es una librería CSS útil para desarrollar interfaces limpias y responsivas con clases utilitarias.
Paso 1: Instalar Tailwind CSS
Ejecuta los siguientes comandos:
1 2 3 |
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p |
Esto crea archivos tailwind.config.js
y postcss.config.js
.
Paso 2: Configurar Tailwind para Next.js
Edita tailwind.config.js
para añadir los paths donde Tailwind debe buscar clases:
1 2 3 4 5 6 7 8 9 10 11 12 |
/** @type {import('tailwindcss').Config} */ module.exports = { content: [ './pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}', ], theme: { extend: {}, }, plugins: [require('@tailwindcss/typography')], } |
La plugin @tailwindcss/typography
ayuda a darle estilo a HTML dentro de los posts.
Instálala también:
1 2 |
npm install @tailwindcss/typography |
Paso 3: Añadir Tailwind en CSS global
Edita el archivo styles/globals.css
para incluir las directivas:
1 2 3 4 |
@tailwind base; @tailwind components; @tailwind utilities; |
Paso 4: Usar clases Tailwind en nuestro blog
Ya pudiste ver cómo las clases .max-w-3xl
, .mx-auto
, .text-4xl
, .prose
, etc., fueron usadas para estilizar el contenido.
Si quieres, añade un fondo claro y una fuente agradable en globals.css
:
1 2 3 4 |
body { @apply bg-gray-50 text-gray-900 font-sans; } |
Resultado visual
- Posts con fuente legible
- Listas de posts con enlaces intuitivos
- Diseño responsivo que funciona bien en móviles y escritorios
5. Desplegar el blog en Vercel
Finalmente, para compartir tu blog en la web, Vercel es el hosting perfecto para proyectos Next.js con generación estática.
Paso 1: Crear una cuenta en Vercel
Ve a https://vercel.com y crea una cuenta gratis.
Paso 2: Subir el repositorio a GitHub
Si no usas Git aún, inicializa git y sube tu proyecto:
1 2 3 4 5 6 7 |
git init git add . git commit -m "Init blog with Next.js and Markdown" # Asume que ya tienes un repo en GitHub git remote add origin https://github.com/tuusuario/tu-repo.git git push -u origin main |
Paso 3: Conectar GitHub con Vercel
- En Vercel, elige “Importar Proyecto” y conecta tu cuenta de GitHub.
- Selecciona tu repo.
- Deja las configuraciones por defecto y despliega.
Paso 4: ¡Listo!
Vercel construirá automáticamente tu proyecto usando next build
, ejecutará getStaticProps
y getStaticPaths
para generar tu blog estático.
Obtendrás una URL tipo https://tu-proyecto.vercel.app
para compartir!
Conclusión
En este tutorial hemos:
- Configurado un proyecto Next.js desde cero.
- Integrado Markdown para manejar publicaciones dinámicas usando archivos estáticos.
- Utilizado
getStaticProps
ygetStaticPaths
para la generación estática de páginas, mejorando el rendimiento y SEO. - Estilizado nuestro blog con Tailwind CSS para un diseño moderno y responsive.
- Desplegado fácilmente el sitio en Vercel.
Crear tu blog personal con esta tecnología no solo es una excelente práctica de desarrollo frontend moderno, sino que también te permitirá mantener control total del contenido en Markdown de una forma sencilla y eficiente.
Buenas prácticas
- Organiza tu contenido en carpetas claras (
posts/
,components/
). - Mantén el código tipado (TypeScript) para evitar errores.
- Usa plugins de Markdown con precaución para evitar riesgos de seguridad.
- Optimiza las imágenes si decides añadir para mejorar el rendimiento.
¿Quieres seguir aprendiendo?
- Implementa una página de “Acerca de” con contenido estático.
- Añade un sistema de comentarios (por ejemplo, con GitHub Issues o external).
- Implementa paginación para la lista de posts.
- Explora la internacionalización (i18n) en Next.js.