Qué es Next.js

Next.js es el framework de React más popular para crear aplicaciones web modernas. Te permite desarrollar apps con SSR, SSG, API Routes y mucho más, todo en un solo framework.

Next.js extiende las capacidades del framework base, añadiendo funcionalidades como:

  Next.js

  • Server-Side Rendering (SSR): Renderiza páginas en el servidor
  • Static Site Generation (SSG): Genera sitios estáticos en build time
  • API Routes: Crea endpoints de API sin servidor adicional
  • File-based Routing: Sistema de rutas basado en archivos
  • Optimizaciones automáticas: Imágenes, fuentes, CSS y JavaScript

  ¿Por qué Next.js?

Next.js resuelve los problemas de SEO, performance y experiencia de usuario que tiene React vanilla. Es la opción ideal para apps de producción.

Instalación del Framework


Acontinuacion se muestra como instalar Next.js usando create-next-app, el método más sencillo y recomendado.

bash
# Con npm
npx create-next-app@latest mi-proyecto-nextjs

# Con yarn
yarn create next-app mi-proyecto-nextjs

# Con pnpm
pnpm create next-app mi-proyecto-nextjs
  Configuración durante la instalación

Durante la instalación, Next.js te preguntará sobre TypeScript, ESLint, Tailwind CSS, App Router, etc. Para empezar, acepta las opciones por defecto.

Scripts en package.json

json
{
"scripts": {
  "dev": "next dev",
  "build": "next build", 
  "start": "next start",
  "lint": "next lint"
}
}

Interactuando con el proyecto


Comandos básicos

bash
# Modo desarrollo (puerto 3000)
npm run dev

# Construir para producción
npm run build

# Ejecutar en producción
npm run start

# Linting del código
npm run lint

Estructura inicial después de la instalación

bash
mi-proyecto-nextjs/
├── app/                 # App Router (Next.js 13+)
│   ├── globals.css
│   ├── layout.tsx
│   └── page.tsx
├── public/              # Archivos estáticos
├── next.config.js       # Configuración de Next.js
├── package.json
└── tailwind.config.js   # Si elegiste Tailwind
  App Router vs Pages Router

Next.js 13+ usa App Router por defecto. Si necesitas Pages Router (sistema anterior), puedes crear una carpeta pages/ en la raíz del proyecto.

Archivos mínimos necesarios para trabajar


1next.config.js

Este archivo es la configuración principal de Next.js. Asegúrate de incluirlo en la raíz de tu proyecto.

javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
// Configuraciones básicas
reactStrictMode: true,

// Optimización de imágenes
images: {
  domains: ['example.com'],
},

// Variables de entorno públicas
env: {
  CUSTOM_KEY: process.env.CUSTOM_KEY,
}
}

module.exports = nextConfig

2app/layout.tsx

El archivo layout.tsx define el layout principal de tu aplicación. Asegúrate de incluirlo en la carpeta app/ de tu proyecto.

tsx
import type { Metadata } from 'next'
import './globals.css'

export const metadata: Metadata = {
title: 'Mi App Next.js',
description: 'Aplicación creada con Next.js',
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
  <html lang="es">
    <body>
      <header>
        <nav>Mi Navegación</nav>
      </header>
      <main>{children}</main>
      <footer>© 2024 Mi App</footer>
    </body>
  </html>
)
}

3app/page.tsx

El archivo page.tsx es la página principal de tu aplicación. Asegúrate de incluirlo en la carpeta app/ de tu proyecto.

tsx
export default function HomePage() {
return (
  <div>
    <h1>¡Bienvenido a Next.js!</h1>
    <p>Esta es tu primera página con Next.js</p>
  </div>
)
}

4package.json

El archivo package.json contiene las dependencias necesarias para tu proyecto. Asegúrate de incluirlo en la raíz de tu proyecto.

json
{
"name": "mi-proyecto-nextjs",
"version": "0.1.0",
"private": true,
"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint"
},
"dependencies": {
  "next": "15.0.0",
  "react": "^19.0.0",
  "react-dom": "^19.0.0"
},
"devDependencies": {
  "@types/node": "^20",
  "@types/react": "^18",
  "@types/react-dom": "^18",
  "eslint": "^8",
  "eslint-config-next": "15.0.0",
  "typescript": "^5"
}
}

Estructura de carpetas y organización del proyecto


En este escenario, consideremos una aplicación con autenticación y dashboard. La estructura recomendada para proyectos medianos/grandes es la siguiente:

bash
mi-proyecto-nextjs/
├── app/                    # App Router
│   ├── (auth)/            # Grupos de rutas
│   │   ├── login/
│   │   └── register/
│   ├── dashboard/         # Rutas anidadas
│   │   ├── settings/
│   │   └── profile/
│   ├── api/               # API Routes
│   │   ├── users/
│   │   └── posts/
│   ├── globals.css
│   ├── layout.tsx
│   ├── loading.tsx        # UI de carga
│   ├── error.tsx          # UI de error
│   ├── not-found.tsx      # 404 personalizado
│   └── page.tsx
├── components/            # Componentes reutilizables
│   ├── ui/               # Componentes de UI básicos
│   └── forms/            # Componentes de formularios
├── lib/                  # Utilidades y configuraciones
│   ├── auth.ts
│   ├── db.ts
│   └── utils.ts
├── public/               # Archivos estáticos
│   ├── images/
│   └── icons/
├── styles/               # Estilos globales
├── types/                # Definiciones de TypeScript
└── hooks/                # Custom hooks

Convenciones de nombres importantes

Estas convenciones ayudan a mantener una estructura organizada y consistente en tu proyecto.

ArchivoPropósitoUbicación
layout.tsxLayout compartidoCualquier carpeta en app/
page.tsxPágina de rutaCualquier carpeta en app/
loading.tsxUI de cargaCualquier carpeta en app/
error.tsxUI de errorCualquier carpeta en app/
not-found.tsxPágina 404Cualquier carpeta en app/
  Grupos de rutas

Los paréntesis (auth) crean grupos de rutas que no afectan la URL. Útil para organizar rutas relacionadas sin cambiar la estructura de URLs.

Carpetas ui y lib


Carpeta lib/ - Utilidades y configuraciones

La carpeta lib/ contiene código reutilizable, configuraciones y utilidades:

typescript
// lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

export function formatDate(date: Date): string {
return new Intl.DateTimeFormat('es-ES').format(date)
}

// lib/auth.ts
import { NextAuthOptions } from "next-auth"

export const authOptions: NextAuthOptions = {
providers: [
  // Configuración de proveedores
],
callbacks: {
  // Callbacks personalizados
}
}

// lib/db.ts
import { PrismaClient } from '@prisma/client'

const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}

export const prisma = globalForPrisma.prisma ?? new PrismaClient()

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

Carpeta components/ui/ - Componentes de interfaz

La carpeta ui/ dentro de components/ contiene componentes básicos reutilizables:

typescript
// components/ui/button.tsx
import { cn } from "@/lib/utils"

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'default' | 'destructive' | 'outline'
size?: 'default' | 'sm' | 'lg'
}

export function Button({ 
className, 
variant = 'default', 
size = 'default',
...props 
}: ButtonProps) {
return (
  <button
    className={cn(
      "inline-flex items-center justify-center rounded-md font-medium",
      {
        'bg-blue-600 text-white hover:bg-blue-700': variant === 'default',
        'bg-red-600 text-white hover:bg-red-700': variant === 'destructive',
        'border border-gray-300 bg-white hover:bg-gray-50': variant === 'outline',
      },
      {
        'h-10 px-4 py-2': size === 'default',
        'h-9 px-3': size === 'sm',
        'h-11 px-8': size === 'lg',
      },
      className
    )}
    {...props}
  />
)
}

// components/ui/input.tsx
import { cn } from "@/lib/utils"

interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}

export function Input({ className, type, ...props }: InputProps) {
return (
  <input
    type={type}
    className={cn(
      "flex h-10 w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm",
      "placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500",
      "disabled:cursor-not-allowed disabled:opacity-50",
      className
    )}
    {...props}
  />
)
}

Ejemplo de uso de componentes ui/

typescript
// app/contact/page.tsx
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"

export default function ContactPage() {
return (
  <div className="max-w-md mx-auto p-6">
    <h1 className="text-2xl font-bold mb-6">Contacto</h1>
    <form className="space-y-4">
      <Input 
        type="email" 
        placeholder="tu@email.com" 
      />
      <Input 
        type="text" 
        placeholder="Tu nombre" 
      />
      <Button type="submit" className="w-full">
        Enviar mensaje
      </Button>
    </form>
  </div>
)
}
  Organización de componentes

Separa componentes básicos (ui/) de componentes específicos del negocio. Esto facilita el mantenimiento y la reutilización del código.

Resumen de la estructura ideal

CarpetaContenidoEjemplo
app/Rutas y layoutspage.tsx, layout.tsx
components/ui/Componentes básicosButton, Input, Modal
components/Componentes específicosHeader, ProductCard
lib/Utilidades y configutils.ts, auth.ts, db.ts
hooks/Custom hooksuseAuth, useLocalStorage

Con esta estructura tendrás un proyecto Next.js bien organizado, escalable y fácil de mantener.