跪拜 Guibai
← Back to the summary

Next.js Is the AI-Friendly Full-Stack Framework, Explained Through a Blog Build

Starting from a "House": Why Next.js is a Full-Stack Framework for AI (with a Blog Project Breakdown)

This article will take you from the most fundamental question — "What problems do JS and React actually solve?" — step by step to "Why choose Next.js?", and finally tie the knowledge together with a real blog project. Plain language throughout, no jargon.

Zero: First, Answer a "Stupid Question": What is a Framework?

Imagine building a house. You can't start by firing bricks every time you build a house — that's too slow. You need a basic architecture that already provides the foundation, walls, and roof, so you only need to focus on assembly and decoration.

This is a Framework.

Without a framework:                     With a framework:
┌───────────┐              ┌───────────────┐
│ Fire bricks → Build walls →│              │ Foundation (already laid)  │
│ Install windows → Lay floor →│              │ Walls (already built)  │
│ Decorate...   │              │ Roof (already built)  │
│ Start from 0 each time│              │ You only handle decoration  │
└───────────┘              └───────────────┘

Previously, frameworks only served developers; now, AI can also use frameworks. One could even say that the value of frameworks is amplified in the AI era: frameworks give AI a set of constraints and a context, allowing AI to develop projects more efficiently based on these constraints.


One: The Bottom Layer: What Problems JS and React Solve

There are only three sentences in the notes, but each is worth expanding on:

Functions that return JSX, reactive state. They liberate developers from low-level frontend API imperative pipeline programming, through modern frontend libraries like React/Vue MVVM, allowing you to write business logic directly.

1.1 Imperative vs. Declarative: How We Used to Write Pages

Old-school frontend (vanilla JS / jQuery) was imperative: you had to "tell the browser what to do step by step."

// Imperative: every step is a manual instruction
const btn = document.querySelector("#btn");
const countEl = document.querySelector("#count");

btn.addEventListener("click", () => {
  const next = Number(countEl.textContent) + 1;
  countEl.textContent = next; // Manually manipulate the DOM: read value, calculate value, write back
});

The code is long and fragile — you have to stare at every piece of DOM and change it manually, like an assembly line worker. This is what the notes call "low-level frontend API imperative pipeline programming".

React took a different approach — declarative: you only describe "what the interface looks like," and the framework handles the rest of the updates.

1.2 Function Components: A Component is a "Function that Returns JSX"

React's core concept can be summed up in one sentence:

Component = a function that returns JSX.

// Function component: a regular function that returns JSX
function Counter() {
  return <div>I am part of the interface</div>;
}

1.3 Reactive State: When Data Changes, the Interface Automatically Follows

"Reactive state" means — you just change the data, and the interface updates automatically, without you manually manipulating the DOM.

const [count, setCount] = useState(0); // Declare a "reactive state"

The onClick={setCount(count++)} in the notes is exactly this: click → change data → React automatically renders the new number onto the interface. This is the value of MVVM/reactivity: liberating you from "low-level frontend APIs" to write business logic directly.


Two: Why Use a Framework: Scattered Blocks vs. Pre-made Lego

Original notes:

Without a framework: scattered blocks and tools. Where to put images? /public. Where to put page files? /app. Where to put components? /components. Using a framework: pre-made Lego bricks, providing a series of constraint best practices, which coincidentally align with AI SDD documentation context.

Without a framework, every decision about "where to put things" is yours to make, and different people make different decisions — this is scattered blocks. With a framework, it tells you the standard answer through a set of conventions:

Without a framework → Where to put images? Where to put pages? Where to put components? → All based on gut feeling
With a framework   → Images in /public   Pages in /app   Components in /components → Standard answer

The value of a framework = a set of constraints + best practices:

The key point is here: This set of constraints is exceptionally valuable for AI. As soon as AI sees "this is a Next.js project," it knows what the code should look like and where files should go. That sentence in the notes is very insightful:

AI Context = Components + Reactive Business Logic + Server-Side Rendering + API

For developers, a framework is the "foundation"; for AI, it's the "instruction manual."


Three: Why Specifically Next.js?

3.1 Context Switching Cost: One Less Backend Language to Learn

Traditional full-stack is "Frontend React + Backend Java/Python," two languages, two ecosystems, switching back and forth, with a high context-switching cost.

Traditional Full-stack:  React(JS)  +  Java/Python   ← Two languages
Next.js :                React(JS)  +  Next(JS)      ← One TS for everything

Next.js is a React-based full-stack framework that integrates server-side rendering, static generation, and APIs, all handled with one set of JS/TS.

3.2 Best Support for AI

AI coding tools like Claude Code / Codex have the best support for Next.js. Because its constraints are clear, CSR/SSR works out of the box, and AI-generated code is less likely to go off the rails.

3.3 Super Rich Ecosystem

① shadcn/ui Component Library

The ecosystem has ElementUI, ANTD... but shadcn/ui is a different kind of thing: it's not "npm install and you have components" , but rather copies the component source code into your project, allowing you to modify it however you want. The component code sits right in components/ui/button.tsx.

For example, in our project, we use shadcn/ui's Button to replace all buttons:

import { Button } from "@/components/ui/button";

// The most basic button
<Button>Confirm</Button>

// Variant + Size
<Button variant="outline" size="sm">Read Full Article →</Button>

// Use the render prop to render it as a <Link>, turning the button into a link
<Button render={<Link href="/blog/what-is-nextjs" />}>Back to Blog List</Button>

A single Button, through variant (default / outline / secondary / ghost / destructive / link) and size, can combine into various styles, managed with tailwindcss + cva (class-variance-authority). This is "vibe coding writing components, importing components": AI writes the component, you import the component, smooth.

② tailwindcss: Atomic Class Names with Inherent Semantics

text-sm, font-medium, bg-zinc-50... each class name does one thing and carries its own semantics. AI's semantic understanding is very strong; seeing a class name basically allows it to guess the styling intent, so tailwind is particularly suitable for AI learning/generation.

③ Vercel Company

Next.js is maintained by Vercel, which is the world's only JS stack AI coding Agent + AI ecosystem technology company. The benefits are very practical: quick publishing, subdomains, domain binding, one-click deployment after development, no need to fiddle with servers.


Four: Practical: File-System Based Routing (Directory is URL)

Original notes:

  1. File-system based route mapping: page.tsx / layout.tsx shared layout / loading.tsx loading UI / not-found.tsx 404 / error.tsx error UI
  2. Directory mapping: directory names directly map to URL paths

4.1 Directory Names Directly Become URLs

This is the biggest feature of the Next.js App Router: no need to write any route configuration manually, create a folder + create a page.tsx = a page.

app/
├── page.tsx              →  /             Homepage
├── about/
│   └── page.tsx          →  /about        About page
└── blog/
    ├── page.tsx          →  /blog         Blog list
    └── [slug]/           →  /blog/xxx     Blog detail (dynamic)

[slug] is a dynamic route segment — the name inside the brackets is the parameter in the URL. When a user visits /blog/what-is-nextjs, the slug is what-is-nextjs.

4.2 Several "Convention Files" Each Have Their Own Role

File Name Role
page.tsx Page content
layout.tsx Layout, shared by all child pages (the navbar goes here)
loading.tsx Loading UI
not-found.tsx 404 page
error.tsx Error UI

4.3 Interpreting This Code with "Three Stylistic Requirements" (Key Point)

When generating this project, I proposed three stylistic requirements: ① interface Props ② Function Components ③ TypeScript Type System. Below, I'll use the real code from the blog detail page to explain these three points thoroughly.

① interface / type Props: Constrain Component Parameters with Types

On a dynamic route page, the slug comes from the URL, and Next.js passes the URL parameters in via params. We use a Props type to constrain it:

// ① Define the Props type: params is a Promise containing { slug }
type Props = {
  params: Promise<{ slug: string }>;
};

// ② Function component signature: { params }: Props  —— parameters are "locked" by the type
export default async function BlogPostPage({ params }: Props) {
  const { slug } = await params;   // await to get the slug
  const post = posts.find((p) => p.slug === slug);
  // ...
}

Why write this Props type? Because of type safety — the compiler checks in advance "what the component's required parameters look like," reporting errors immediately if written incorrectly, without waiting for a runtime crash. Also note that params is a Promise, so you must await it inside the component — this is a new convention for dynamic routes in Next.js 15+, forcing you to read parameters asynchronously.

② Function Components: A Component is a "Function that Returns JSX"

Pay attention to the syntax: export default function BlogPostPage(...). No class, no this, just a regular function + props destructuring. This is exactly the "function that returns JSX" mentioned in Chapter One. The previously popular React.FC syntax is outdated; the official recommendation now is to write functions directly with explicit type annotations — this is more AI-friendly because the function signature itself is documentation.

③ TS Type System: Making Data and "Interfaces" Trustworthy

The mock data for the two articles is defined with types:

export type BlogPost = {
  slug: string;
  title: string;
  date: string;
  description: string;
  content: string[]; // Body text stored as an array of paragraphs
};

Because findPost might not find anything (returning BlogPost | undefined), the component must check for null, calling notFound() if nothing is found. This layer of the type system makes the entire data flow "trustworthy" from start to finish.

4.4 Two Articles: Rendering with slug + mock data

This is the requirement of "clicking two articles, rendering the article using slug mock data."

// posts.ts —— mock data for two articles
export const posts: BlogPost[] = [
  { slug: "what-is-nextjs", title: "What is Next.js?", content: ["...", "..."] },
  { slug: "app-router-vs-pages-router", title: "App Router vs Pages Router", content: ["...", "..."] },
];

Plus, with generateStaticParams, these two articles will be pre-generated into static HTML at build time:

export function generateStaticParams() {
  return posts.map((post) => ({ slug: post.slug }));
}

User visits /blog/what-is-nextjs → directly hits the pre-built static page, instant open. Flowchart:

/blog List Page (Static) ──click──▶ /blog/[slug] Detail Page
                              │
                        slug lookup mock data
                        ┌────┴────┐
                      Found       Not Found
                        │           │
                     Render Body     notFound() 404

Five: The Link Component: The Secret to No Page Refresh

Original notes:

Link component —— It's client-side navigation, no need to refresh the page. (Frontend routing) Hash, History Router partial refresh still needs to request the backend, just doesn't refresh the whole page (white flash). During frontend navigation, next.js automatically sends an RSC payload, the data is fetched from the backend, just via an Ajax request. Preloads linkable pages to improve speed: the browser downloads the target page data in advance during idle time, "instant open."

5.1 What is Link

<Link> provided by next/link. Using it for page navigation = client-side navigation: clicking it does not refresh the page, no white flash, as smooth as a single-page application.

5.2 The Underlying Truth: It Still Requests the Backend, Just "No Full Page Refresh"

Note that Link does not mean no data is requested, but rather no full page refresh. When clicked, Next.js automatically sends an RSC payload (serialized data of a React Server Component) — the data still comes from the backend, just via an Ajax request, rather than the browser's traditional full-page reload navigation. This is the same principle as frontend routing (Hash / History Router's partial refresh).

Traditional Navigation:  Click → Full page request → White flash → Full re-render
Link Navigation:         Click → Ajax sends RSC payload → Partial update → No white flash

5.3 prefetch: The Browser "Sneaks Ahead" During Idle Time

Next.js automatically adds prefetching to Links visible within the viewport:

<link rel="prefetch" href="/blog" />

The browser will download the target page's data in advance during idle time, so when you actually click in, the content is already there → "instant open" . This is resource preloading.


Six: Bottom-Layer Easter Egg: What Exactly is DNS?

dns domain system key:value distributed database domain -> ip query (telecom service provider), resolution time

This is a question I asked in class, and I'll dedicate a separate chapter to explain it clearly: "DNS Domain Name System = a key:value distributed database" .

6.1 The Domain Name You Type, the Browser Doesn't Understand

The browser actually connects to the internet using an IP address (a string of numbers). But you type baidu.com. So you need a "translator" to translate the domain name into an IP — this process is called domain name resolution.

6.2 It's Just a key:value Database

A database, after all, stores "key-value pair" records:

key (domain name)        value (IP address)
baidu.com    →    39.156.66.10
github.com   →    140.82.112.3

Written as JSON, it's { "baidu.com": "39.156.66.10" }. This is a key:value database — the key is the domain name, the value is the IP.

6.3 Why is it Called "Distributed"?

Because there isn't just one DNS server in the world. There are thousands of DNS servers globally, deployed in layers, queried nearby, each with its own cache, to prevent a single point of failure:

User's Browser
   │ ① "What is the IP for baidu.com?"
   ▼
Local DNS Server (provided by telecom operators like China Telecom/Unicom)
   │ ② No local cache → Query upwards level by level
   ▼
Root Server ──▶ .com Top-Level Domain Server ──▶ Authoritative DNS Server
   │ ③ Found 39.156.66.10, returns along the original path
   ▼
User gets the IP, starts actually visiting the website

6.4 What Does This Have to Do with Web Performance? — dns-prefetch

There's a trick in web performance optimization called dns-prefetch:

<link data-n-head="ssr" rel="dns-prefetch" href="//lf3-short.ibytedapm.com">

Its meaning is: "Resolve the IP for this domain name for me in advance." When you actually need a resource from this domain, you don't have to wait for the resolution temporarily; you connect directly — saving the resolution time. This is the same underlying principle as the prefetch mentioned in the previous chapter: prepare what you'll need in the future, in advance.


Seven: Summary: One Diagram to String the Whole Article Together

Layer ①  JS + React       Declarative + Reactive, solves the pain of "imperative DOM manipulation"
Layer ②  Framework        Scattered blocks → Pre-made Lego, constraints + best practices, AI also benefits
Layer ③  Next.js          React full-stack + AI-friendly + rich ecosystem
Layer ④  Routing          Directory is URL, page/layout/loading/not-found/error
Layer ⑤  Link             Client-side navigation without white flash, RSC payload + prefetch for instant open
Layer ⑥  DNS              key:value distributed database + dns-prefetch for early resolution

Implementation of the three stylistic requirements:

Stylistic Requirement Corresponding Code Value in One Sentence
interface Props type Props = { params: Promise<{slug: string}> } Type safety, errors reported immediately if wrong
Function Component export default function BlogPostPage({ params }: Props) Component is a function returning JSX, signature is documentation
TS Type System type BlogPost = {...} / generateStaticParams Data flow is trustworthy end-to-end, easier for AI to understand

One sentence to wrap up: What a framework solves isn't "whether you can write code," but "where the code goes and how to write it correctly" — this is true for people, and even more so for AI. This is why Next.js has become the "default full-stack choice" in the AI era.


If you follow along hands-on, the recommended order is: npx create-next-app to create the project → build the /blog list page → add the /blog/[slug] detail page → unify buttons using shadcn/ui's Button → play around with Link's prefetch. Each step corresponds to one of the sections above; after learning, you'll have a real blog that can be deployed.

(Note: The flowcharts in the article are ASCII diagrams, which display normally on Juejin as well; if you want to replace them with more polished graphics, you can draw and upload them yourself based on the diagram structure.)


That's the article. If you need me to: adjust the length (too long/too short), change to a more conversational or more hardcore style, supplement a specific subsection (like the cva principle of shadcn/ui, deeper serialization details of RSC), or turn an ASCII diagram into a text-based step list, just tell me directly.