Skip to content

Next.js: The 80-20 Guide#

A practical guide to building modern Next.js applications with App Router, Server Components, and Better Auth.

🎯 What You'll Learn#

  • App Router - Modern Next.js routing with app directory
  • Server Components - Server-side rendering and data fetching
  • Client Components - Interactive UI with React hooks
  • Better Auth - Complete authentication with login/signup
  • API Routes - Build backend endpoints in Next.js
  • TypeScript - Type-safe Next.js development

📚 Sections#

1. Getting Started#

Project setup, folder structure, and basic concepts.

2. Better Auth Setup#

Complete authentication setup with Better Auth.

3. Auth UI Components#

Login, signup, and protected page components.

🚀 Quick Start#

# Create Next.js app with TypeScript
npx create-next-app@latest my-app --typescript --app --tailwind

# Navigate to project
cd my-app

# Install Better Auth
npm install better-auth

# Run development server
npm run dev

Visit http://localhost:3000

📁 Project Structure#

my-app/
├── app/
│   ├── (auth)/
│   │   ├── login/
│   │   │   └── page.tsx
│   │   └── signup/
│   │       └── page.tsx
│   ├── (protected)/
│   │   ├── dashboard/
│   │   │   └── page.tsx
│   │   └── layout.tsx
│   ├── api/
│   │   ├── auth/
│   │   │   └── [...all]/route.ts
│   │   └── users/
│   │       └── route.ts
│   ├── layout.tsx
│   └── page.tsx
├── components/
│   ├── ui/
│   ├── auth/
│   └── shared/
├── lib/
│   ├── auth.ts
│   └── db.ts
└── types/
    └── auth.ts

🎓 Core Concepts#

App Router vs Pages Router#

App Router (Modern, Recommended): - Uses app/ directory - Server Components by default - File-based routing with folders - Built-in layouts and loading states

Pages Router (Legacy): - Uses pages/ directory - Client components by default - File-based routing with files

Server vs Client Components#

Server Components (Default):

// app/page.tsx - Server Component
export default async function Page() {
  const data = await fetch('...');
  return <div>{data}</div>;
}

Client Components (Use 'use client'):

'use client'

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Routing Files#

app/
├── page.tsx          → /
├── about/
│   └── page.tsx      → /about
├── blog/
│   ├── page.tsx      → /blog
│   └── [slug]/
│       └── page.tsx  → /blog/:slug
└── layout.tsx        → Wraps all pages

⚡ Key Features#

Server-Side Data Fetching#

async function getUsers() {
  const res = await fetch('https://api.example.com/users');
  return res.json();
}

export default async function UsersPage() {
  const users = await getUsers();
  return <UserList users={users} />;
}

Dynamic Routes#

// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
  return <h1>Post: {params.slug}</h1>;
}

Loading States#

// app/loading.tsx
export default function Loading() {
  return <div>Loading...</div>;
}

Error Handling#

// app/error.tsx
'use client'

export default function Error({ error, reset }: {
  error: Error;
  reset: () => void;
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={reset}>Try again</button>
    </div>
  );
}

🔐 Authentication Overview#

Better Auth provides: - ✅ Email/password authentication - ✅ OAuth providers (Google, GitHub, etc.) - ✅ Session management - ✅ Protected routes - ✅ Type-safe API

// lib/auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
  database: {
    /* ... */
  },
  emailAndPassword: {
    enabled: true,
  },
});

// app/api/auth/[...all]/route.ts
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";

export const { GET, POST } = toNextJsHandler(auth);

📖 Best Practices#

  1. Use Server Components by default - Only add 'use client' when needed
  2. Group routes with folders - Use (auth), (protected) for organization
  3. Co-locate components - Keep components near where they're used
  4. Use TypeScript - Full type safety with Next.js
  5. Leverage caching - Next.js caches fetch requests by default
  6. Optimize images - Use next/image for automatic optimization

🛠️ Essential Packages#

# Authentication
npm install better-auth

# UI Components (optional)
npm install @radix-ui/react-dialog
npm install class-variance-authority clsx tailwind-merge

# Form handling
npm install react-hook-form zod @hookform/resolvers

# State management (if needed)
npm install zustand

Next Steps#

Start with Getting Started to set up your Next.js project, then follow through each section to build a complete authenticated application.


Pro Tip: Next.js 14+ uses Server Components by default. This means you can fetch data directly in your components without useEffect or loading states!