Jun 7 2025 ~ 4 min read

Next.js + Tailwind Guide


Next.js Setup & Configuration Guide

πŸš€ Project Initialization

Getting started with a new Next.js project is straightforward, but proper configuration from the beginning saves time and ensures best practices.

Creating a New Project

npx create-next-app@latest my-project-name

The CLI will prompt you for several options:

  • TypeScript support
  • ESLint configuration
  • Tailwind CSS integration
  • App Router (recommended)
  • Import alias configuration

🎨 Tailwind CSS Setup

Tailwind CSS provides utility-first styling that pairs perfectly with Next.js components.

Step-by-Step Installation

  1. Create your Next.js project:

    npx create-next-app NAME_OF_PROJECT
    cd NAME_OF_PROJECT
  2. Install Tailwind CSS and dependencies:

    yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest
    npx tailwindcss init -p
  3. Configure tailwind.config.js:

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        './pages/**/*.{js,ts,jsx,tsx,mdx}',
        './components/**/*.{js,ts,jsx,tsx,mdx}',
        './app/**/*.{js,ts,jsx,tsx,mdx}',
      ],
      theme: {
        extend: {},
      },
      plugins: [],
    }
  4. Configure globals.css:

    @tailwind base;
    @tailwind components;
    @tailwind utilities;

Tailwind with App Router

If using the App Router, ensure your globals.css is imported in your root layout:

// app/layout.tsx
import './globals.css'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

πŸ—ΊοΈ Internationalization (i18n)

Next.js provides built-in support for internationalized routing, making it easy to create multilingual applications.

Configuration

Documentation: Next.js Internationalization Routing

Basic Setup

  1. Configure next.config.js:

    /** @type {import('next').NextConfig} */
    const nextConfig = {
      i18n: {
        locales: ['en', 'es', 'fr'],
        defaultLocale: 'en',
        domains: [
          {
            domain: 'example.com',
            defaultLocale: 'en',
          },
          {
            domain: 'example.es',
            defaultLocale: 'es',
          },
        ],
      },
    }
    
    module.exports = nextConfig
  2. Access locale in components:

    import { useRouter } from 'next/router'
    
    function MyComponent() {
      const router = useRouter()
      const { locale, locales, defaultLocale } = router
    
      return (
        <div>
          <p>Current locale: {locale}</p>
          <p>Available locales: {locales?.join(', ')}</p>
        </div>
      )
    }

Routing Patterns

With i18n configured, Next.js automatically handles:

  • / β†’ /en (default locale)
  • /about β†’ /en/about
  • /es/about β†’ Spanish version
  • /fr/about β†’ French version

🧾 Metadata Optimization

The new Metadata API in Next.js App Router provides powerful SEO and social sharing optimization.

Basic Metadata

Documentation: Metadata API in Next.js

// app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'My App',
  description: 'This is my awesome Next.js application',
  keywords: ['Next.js', 'React', 'Web Development'],
}

Dynamic Metadata

// app/blog/[slug]/page.tsx
import type { Metadata } from 'next'

type Props = {
  params: { slug: string }
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const post = await fetchPost(params.slug)

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.image],
    },
    twitter: {
      card: 'summary_large_image',
      title: post.title,
      description: post.excerpt,
      images: [post.image],
    },
  }
}

Metadata Templates

// app/layout.tsx
export const metadata: Metadata = {
  title: {
    template: '%s | My App',
    default: 'My App',
  },
  description: 'The best Next.js application',
}

// app/about/page.tsx
export const metadata: Metadata = {
  title: 'About', // Will become "About | My App"
}

βš™οΈ Additional Configuration

Environment Variables

Create .env.local for local development:

# .env.local
DATABASE_URL="your-database-url"
API_KEY="your-api-key"
NEXT_PUBLIC_APP_URL="http://localhost:3000"

Variables prefixed with NEXT_PUBLIC_ are available in the browser.

TypeScript Configuration

// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/utils/*": ["./src/utils/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

ESLint Configuration

// .eslintrc.json
{
  "extends": ["next/core-web-vitals", "next/typescript"],
  "rules": {
    "@next/next/no-img-element": "error",
    "@next/next/no-html-link-for-pages": "error"
  }
}
my-next-app/
β”œβ”€β”€ app/                 # App Router (Next.js 13+)
β”‚   β”œβ”€β”€ globals.css
β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”œβ”€β”€ page.tsx
β”‚   └── api/
β”œβ”€β”€ components/          # Reusable components
β”‚   β”œβ”€β”€ ui/             # Basic UI components
β”‚   └── features/       # Feature-specific components
β”œβ”€β”€ lib/                # Utility functions
β”œβ”€β”€ public/             # Static assets
β”œβ”€β”€ types/              # TypeScript type definitions
β”œβ”€β”€ next.config.js
β”œβ”€β”€ tailwind.config.js
└── package.json

This setup provides a solid foundation for scalable Next.js applications with modern tooling and best practices built in.

Headshot of Alvaro Uribe

Hi, I'm Alvaro. I'm a software engineer from Chile πŸ‡¨πŸ‡± based in New Zealand πŸ‡³πŸ‡Ώ.