HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
5 Topics
Chapter•75 Minutes

Next.js Fundamentals and Project Architecture

Understand what Next.js solves, how it differs from plain React, how a Next.js application is structured, and how to create a production-ready project.

What Is Next.js?

Next.js is a React framework for building applications that can render UI on the server, in the browser, or at build time. React primarily gives you a component model, while Next.js adds application-level capabilities such as routing, rendering strategies, server-side execution, optimization, metadata handling, image optimization, and backend endpoints.

A useful mental model is: React builds components; Next.js builds applications around those components.

For example, a traditional React SPA may initially download JavaScript and then request data from an API. A Next.js application can render the initial page on the server, send HTML to the browser, and then hydrate interactive components.

Next.js is particularly useful when you need SEO-friendly pages, fast initial rendering, authenticated applications, content-heavy websites, e-commerce applications, dashboards, or a single full-stack codebase.

It is important not to think of Next.js as simply 'React with routing'. The framework controls where code executes and provides mechanisms for deciding whether work belongs on the server, browser, build process, or request lifecycle.

Core Mental Model

Before learning individual APIs, understand where code executes. In modern Next.js, the most important distinction is Server Component versus Client Component.

Key Takeaways
  • Next.js is a framework built around React.
  • It provides routing, rendering, optimization, server execution, and full-stack capabilities.
  • Modern Next.js applications should be designed around server-first rendering.

React vs Next.js

React and Next.js solve different layers of the problem. React provides components, state, hooks, and rendering primitives. Next.js provides the application framework around React.

In a plain React application, you commonly install and configure routing, API communication, SEO libraries, bundling, code splitting, and deployment behavior yourself. Next.js provides conventions for many of these concerns.

Consider a product page. In a React SPA, the browser might load JavaScript first and then fetch /api/products/42. In Next.js, the product page can be rendered on the server and the resulting HTML can already contain the product information.

Another important difference is that Next.js supports server-only code directly inside the application. Database queries, secrets, filesystem operations, and private credentials should remain on the server rather than being bundled into browser JavaScript.

React and Next.js Responsibilities
Key Takeaways
  • React is the UI library; Next.js is the application framework.
  • Next.js can keep sensitive server logic outside the browser.
  • The framework reduces the amount of infrastructure you must configure manually.

Creating a Next.js Application

The standard way to start a modern project is with the Next.js project generator. During setup you can choose TypeScript, ESLint, Tailwind CSS, a source directory, and the App Router.

For modern applications, the App Router should generally be preferred because it provides Server Components, nested layouts, loading states, error boundaries, streaming, and modern data-fetching patterns.

A good production project should establish conventions early. Decide where reusable UI lives, where server-only modules live, how environment variables are named, how API clients are organized, and how domain-specific code is separated.

Create a Next.js Project
npx create-next-app@latest my-next-app
cd my-next-app
npm run dev
💡 The generator creates the project structure and development tooling. The development server normally becomes available locally after running the dev script.
Key Takeaways
  • Use the official project generator instead of manually assembling framework configuration.
  • Prefer the App Router for new applications.
  • Establish architectural conventions before the project becomes large.

Understanding Project Structure

The app directory is the center of an App Router application. A folder becomes a route when it contains the appropriate special file such as page.tsx.

Common special files include layout.tsx, page.tsx, loading.tsx, error.tsx, not-found.tsx, and route.ts.

Other directories such as components, lib, services, and types are application conventions rather than mandatory Next.js requirements. A large application benefits from separating UI components from business logic and infrastructure code.

A useful architecture is to keep route-specific UI near the route while keeping shared business logic in reusable modules.

Example Application Structure
app/
  layout.tsx
  page.tsx
  dashboard/
    layout.tsx
    page.tsx
    loading.tsx
    error.tsx
  api/
    users/
      route.ts
components/
  Button.tsx
  UserCard.tsx
lib/
  db.ts
  auth.ts
services/
  user-service.ts
types/
  user.ts
💡 This structure separates routing concerns from reusable UI, infrastructure, and business logic.
Key Takeaways
  • Files inside app define application routing and rendering behavior.
  • Special Next.js files have framework-defined meanings.
  • Business logic should not become tightly coupled to page components.

Environment Variables and Secrets

Environment variables allow configuration to vary between development, staging, and production. Examples include database URLs, API secrets, OAuth credentials, and public application configuration.

Variables intended only for server execution should not be exposed to browser code. Next.js uses the NEXT_PUBLIC_ prefix for values that are intentionally exposed to client-side JavaScript.

For example, a database password must never be prefixed with NEXT_PUBLIC_. Doing so indicates that the value is intended to become part of the client bundle.

Never Expose Secrets

Anything prefixed with NEXT_PUBLIC_ should be treated as public. Never place database credentials, private signing keys, or service secrets there.

Using Environment Variables
const databaseUrl = process.env.DATABASE_URL;

const publicApiUrl = process.env.NEXT_PUBLIC_API_URL;

if (!databaseUrl) {
  throw new Error('DATABASE_URL is not configured');
}
💡 Server-only secrets can be accessed from server-side code. Public configuration can use the NEXT_PUBLIC_ prefix when browser exposure is intentional.
Key Takeaways
  • Keep private secrets server-only.
  • Use NEXT_PUBLIC_ only for intentionally public values.
  • Production secrets should be supplied through the deployment environment.