Next.js Crash Course: Build Your First Full-Stack App in Hours, Not Days

Emma GeorgeEmma George
21 Jun, 2025
Next.js Crash Course: Build Your First Full-Stack App in Hours, Not Days

TABLE OF CONTENTS

What You’ll Build

Prerequisites

Step 1: Setting Up Your Next.js Project

Step 2: Build the Pages and Layout

Step 3: Add Authentication with NextAuth

Step 4: API Routes - Backend in Next.js

Step 5: Connect to a Database using Prisma

Step 6: Building the Dashboard

Step 7: Deploy with Vercel

Bonus Features to Explore

Testing Your Full-Stack App

Developer Tips

Conclusion

Next.js has quickly become one of the most powerful and developer-friendly frameworks for building modern web applications. Whether you’re a beginner looking to step into full-stack development or an experienced developer exploring the React ecosystem’s cutting edge, this crash course is for you.

In this deep-dive guide, we’ll cover how to build a full-stack application using Next.js from start to finish. You’ll learn the core concepts and apply them in real time to build something functional, beautiful, and production-ready.

What You’ll Build

A simple yet powerful Task Manager application that includes:

  • Frontend: React-powered UI with Tailwind CSS
  • Backend: API routes built into Next.js
  • Database: PostgreSQL or MongoDB integration with Prisma
  • Authentication: Secure login using NextAuth.js
  • Deployment: Vercel hosting with environment variables and CI/CD

By the end, you’ll have a working full-stack app deployed live on the internet.

Prerequisites

  • Basic knowledge of JavaScript and React
  • Node.js and npm installed
  • Familiarity with Git & command line
  • PostgreSQL or MongoDB installed (local or cloud)

Step 1: Setting Up Your Next.js Project

npx create-next-app@latest task-manager --typescript
cd task-manager
npm install

Structure:

/pages
/components
/lib
/prisma
/public
/styles

Install Tailwind CSS:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Add Tailwind to styles/globals.css:

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

Configure tailwind.config.js:

content: [
  "./pages/**/*.{js,ts,jsx,tsx}",
  "./components/**/*.{js,ts,jsx,tsx}",
],

Start the server:

npm run dev

Step 2: Build the Pages and Layout

Next.js uses the /pages directory to automatically generate routes.

  • /pages/index.tsx → Homepage
  • /pages/login.tsx → Login
  • /pages/dashboard.tsx → Main App

Create a layout component:

// components/Layout.tsx
export default function Layout({ children }) {
  return (
    <div className="min-h-screen bg-gray-100 p-4">
      <main>{children}</main>
    </div>
  );
}

Use it in your pages:

import Layout from "../components/Layout";
export default function Home() {
  return (
    <Layout>
      <h1 className="text-2xl font-bold">Welcome to Task Manager</h1>
    </Layout>
  );
}

Step 3: Add Authentication with NextAuth

Install NextAuth.js:

npm install next-auth

Create the route:

/pages/api/auth/[...nextauth].ts

Example (using GitHub Provider):

import NextAuth from "next-auth";
import GitHubProvider from "next-auth/providers/github";

export default NextAuth({
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_ID!,
      clientSecret: process.env.GITHUB_SECRET!,
    }),
  ],
});

Use the useSession hook:

import { useSession, signIn, signOut } from "next-auth/react";

const { data: session } = useSession();

if (!session) {
  return <button onClick={() => signIn()}>Login</button>;
}

Step 4: API Routes - Backend in Next.js

Create your first API route:

/pages/api/tasks/index.ts
import { NextApiRequest, NextApiResponse } from "next";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "GET") {
    res.status(200).json({ tasks: [] });
  } else if (req.method === "POST") {
    const { title } = req.body;
    res.status(201).json({ task: { id: 1, title } });
  }
}

Step 5: Connect to a Database using Prisma

Install Prisma:

npm install prisma --save-dev
npx prisma init

Example PostgreSQL schema:

model Task {
  id        Int      @id @default(autoincrement())
  title     String
  done      Boolean  @default(false)
  createdAt DateTime @default(now())
}

Run migration:

npx prisma migrate dev --name init

Create helper functions:

  • /lib/prisma.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };

export const prisma =
  globalForPrisma.prisma ||
  new PrismaClient({ log: ['query'] });

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

Use in API:

import { prisma } from "../../../lib/prisma";

const tasks = await prisma.task.findMany();

Step 6: Building the Dashboard

Tasks List + Add Task Form:

// components/TaskForm.tsx
export default function TaskForm({ onAdd }) {
  const [title, setTitle] = useState("");

  return (
    <form onSubmit={e => {
      e.preventDefault();
      onAdd(title);
      setTitle("");
    }}>
      <input value={title} onChange={e => setTitle(e.target.value)} />
      <button type="submit">Add Task</button>
    </form>
  );
}

Fetch and render tasks:

useEffect(() => {
  async function load() {
    const res = await fetch("/api/tasks");
    const data = await res.json();
    setTasks(data.tasks);
  }
  load();
}, []);

Step 7: Deploy with Vercel

Push to GitHub, then:

Vercel automatically detects Next.js, installs dependencies, and runs your app in seconds.

Bonus Features to Explore

  • CRUD operations (update, delete)
  • Drag-and-drop tasks
  • Sort by createdAt or priority
  • Add user-specific tasks with session.email
  • Add pagination or infinite scroll
  • Optimize with SWR or React Query
  • Add tests using Jest or Cypress

Testing Your Full-Stack App

Install Jest and React Testing Library:

npm install --save-dev jest @testing-library/react

Test a component:

// __tests__/TaskForm.test.tsx
import { render, screen } from "@testing-library/react";
import TaskForm from "../components/TaskForm";

test("renders input", () => {
  render(<TaskForm onAdd={() => {}} />);
  expect(screen.getByRole("textbox")).toBeInTheDocument();
});

Developer Tips

  • Use .env.local for secrets
  • Add SEO with next/head
  • Use middleware for route protection
  • Use getServerSideProps for authenticated pages
  • Set up logging and error handling
  • Apply custom 404 and 500 pages

Conclusion

In just a few hours, you've gone from zero to full-stack, building a complete application using Next.js, API routes, a database, and authentication. You’ve touched on both frontend and backend, and even learned how to deploy to the cloud.

This is just the beginning.

Next.js opens doors to more powerful concepts, like static generation, server-side rendering, image optimization, middleware, edge functions, and more. Once you’re comfortable, try upgrading your task manager with advanced features or even rebuild it using the App Router in Next.js 13+.

Keep coding, keep learning, and ship your ideas into the world.

Do you want the complete source code for this project with styles and folder structure included? Just let me know!

Emma George

Emma George

Software Engineer

Senior Software Engineer