nextjs-shadcn

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Next.js 16 + shadcn/ui

Next.js 16 + shadcn/ui

Build distinctive, production-grade interfaces that avoid generic "AI slop" aesthetics.
打造独特的、生产级别的界面,避免千篇一律的「AI流水线风格」美学。

Core Principles

核心原则

  1. Minimize noise - Icons communicate; excessive labels don't
  2. No generic AI-UI - Avoid purple gradients, excessive shadows, predictable layouts
  3. Context over decoration - Every element serves a purpose
  4. Theme consistency - Use CSS variables from
    globals.css
    , never hardcode colors
  1. 减少冗余 - 图标传递信息;过多的标签则无需存在
  2. 拒绝通用AI界面 - 避免紫色渐变、过度阴影、可预测的布局
  3. 功能优先于装饰 - 每个元素都有明确用途
  4. 主题一致性 - 使用
    globals.css
    中的CSS变量,绝不硬编码颜色

Quick Start

快速开始

bash
bunx --bun shadcn@latest create --preset "https://ui.shadcn.com/init?base=radix&style=nova&baseColor=neutral&iconLibrary=lucide&font=geist-sans" --template next
bash
bunx --bun shadcn@latest create --preset "https://ui.shadcn.com/init?base=radix&style=nova&baseColor=neutral&iconLibrary=lucide&font=geist-sans" --template next

Component Rules

组件规则

Page Structure

页面结构

tsx
// page.tsx - content only, no layout chrome
export default function Page() {
  return (
    <>
      <HeroSection />
      <Features />
      <Testimonials />
    </>
  );
}

// layout.tsx - shared UI (header, footer, sidebar)
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  );
}
tsx
// page.tsx - 仅包含内容,无布局框架
export default function Page() {
  return (
    <>
      <HeroSection />
      <Features />
      <Testimonials />
    </>
  );
}

// layout.tsx - 共享UI(页眉、页脚、侧边栏)
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  );
}

Client Boundaries

客户端边界

  • "use client"
    only at leaf components (smallest boundary)
  • Props must be serializable (data or Server Actions, no functions/classes)
  • Pass server content via
    children
  • "use client"
    仅用于叶子组件(最小边界)
  • Props必须可序列化(数据或Server Actions,不能是函数/类)
  • 通过
    children
    传递服务端内容

Import Aliases

导入别名

Always use
@/
alias (e.g.,
@/lib/utils
) instead of relative paths (
../../lib/utils
).
始终使用
@/
别名(例如
@/lib/utils
),而非相对路径(
../../lib/utils
)。

Style Merging

样式合并

tsx
import { cn } from "@/lib/utils";

function Button({ className, ...props }) {
  return <button className={cn("px-4 py-2 rounded", className)} {...props} />;
}
tsx
import { cn } from "@/lib/utils";

function Button({ className, ...props }) {
  return <button className={cn("px-4 py-2 rounded", className)} {...props} />;
}

File Organization

文件组织

app/
├── (protected)/         # Auth required routes
│   ├── dashboard/
│   ├── settings/
│   ├── components/      # Route-specific components
│   └── lib/             # Route-specific utils/types
├── (public)/            # Public routes
│   ├── login/
│   └── register/
├── actions/             # Server Actions (global)
├── api/                 # API routes
├── layout.tsx           # Root layout
└── globals.css          # Theme tokens
components/              # Shared components
├── ui/                  # shadcn primitives
└── shared/              # Business components
hooks/                   # Custom React hooks
lib/                     # Shared utils
data/                    # Database queries
ai/                      # AI logic (tools, agents, prompts)
app/
├── (protected)/         # 需要认证的路由
│   ├── dashboard/
│   ├── settings/
│   ├── components/      # 路由专属组件
│   └── lib/             # 路由专属工具/类型
├── (public)/            # 公开路由
│   ├── login/
│   └── register/
├── actions/             # 全局Server Actions
├── api/                 # API路由
├── layout.tsx           # 根布局
└── globals.css          # 主题令牌
components/              # 共享组件
├── ui/                  # shadcn基础组件
└── shared/              # 业务组件
hooks/                   # 自定义React hooks
lib/                     # 共享工具
data/                    # 数据库查询
ai/                      # AI逻辑(工具、Agent、提示词)

Next.js 16 Features

Next.js 16特性

Async Params

异步参数

tsx
export default async function Page({
  params,
  searchParams,
}: {
  params: Promise<{ id: string }>;
  searchParams: Promise<{ q?: string }>;
}) {
  const { id } = await params;
  const { q } = await searchParams;
}
tsx
export default async function Page({
  params,
  searchParams,
}: {
  params: Promise<{ id: string }>;
  searchParams: Promise<{ q?: string }>;
}) {
  const { id } = await params;
  const { q } = await searchParams;
}

Data Fetching vs Server Actions

数据获取 vs Server Actions

CRITICAL RULE:
  • Server Actions = ONLY for mutations (create, update, delete)
  • Data fetching = In Server Components or
    'use cache'
    functions
tsx
// ❌ WRONG: Server Action for data fetching
"use server"
export async function getUsers() {
  return await db.users.findMany()
}

// ✅ CORRECT: Data function with caching
// data/users.ts
export async function getUsers() {
  "use cache"
  cacheTag("users")
  cacheLife("hours")
  return await db.users.findMany()
}

// ✅ CORRECT: Read cookies in Server Component directly
export default async function Page() {
  const theme = (await cookies()).get("theme")?.value ?? "light"
  return <App theme={theme} />
}
关键规则:
  • Server Actions = 仅用于数据变更(创建、更新、删除)
  • 数据获取 = 在Server Components或
    'use cache'
    函数中进行
tsx
// ❌ 错误:使用Server Actions进行数据获取
"use server"
export async function getUsers() {
  return await db.users.findMany()
}

// ✅ 正确:带缓存的数据函数
// data/users.ts
export async function getUsers() {
  "use cache"
  cacheTag("users")
  cacheLife("hours")
  return await db.users.findMany()
}

// ✅ 正确:在Server Component中直接读取Cookie
export default async function Page() {
  const theme = (await cookies()).get("theme")?.value ?? "light"
  return <App theme={theme} />
}

Caching

缓存

tsx
"use cache";

import { cacheTag, cacheLife } from "next/cache";

export async function getProducts() {
  cacheTag("products");
  cacheLife("hours");
  return await db.products.findMany();
}
tsx
"use cache";

import { cacheTag, cacheLife } from "next/cache";

export async function getProducts() {
  cacheTag("products");
  cacheLife("hours");
  return await db.products.findMany();
}

Server Actions (Mutations Only)

Server Actions(仅用于数据变更)

tsx
"use server";

import { updateTag, revalidateTag } from "next/cache";
import { z } from "zod";

const schema = z.object({
  title: z.string().min(1),
  content: z.string(),
});

export async function createPost(formData: FormData) {
  // Always validate input
  const parsed = schema.parse({
    title: formData.get("title"),
    content: formData.get("content"),
  });

  await db.insert(posts).values(parsed);
  updateTag("posts"); // Read-your-writes
}
tsx
"use server";

import { updateTag, revalidateTag } from "next/cache";
import { z } from "zod";

const schema = z.object({
  title: z.string().min(1),
  content: z.string(),
});

export async function createPost(formData: FormData) {
  // 始终验证输入
  const parsed = schema.parse({
    title: formData.get("title"),
    content: formData.get("content"),
  });

  await db.insert(posts).values(parsed);
  updateTag("posts"); // 读写一致性
}

Proxy API

代理API

Use
proxy.ts
for request interception (replaces middleware). Place at project root:
tsx
// proxy.ts (project root, same level as app/)
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

export function proxy(request: NextRequest) {
  // Auth checks, redirects, etc.
}

export const config = {
  matcher: ['/dashboard/:path*'],
}
使用
proxy.ts
进行请求拦截(替代中间件)。放置在项目根目录:
tsx
// proxy.ts(项目根目录,与app/同级)
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

export function proxy(request: NextRequest) {
  // 权限校验、重定向等
}

export const config = {
  matcher: ['/dashboard/:path*'],
}

References

参考资料

  • Architecture: references/architecture.md - Components, routing, Suspense, data patterns, AI directory structure
  • Styling: references/styling.md - Themes, fonts, radius, animations, CSS variables
  • Sidebar: references/sidebar.md - shadcn sidebar with nested layouts
  • Project Setup: references/project-setup.md - bun commands, presets
  • shadcn/ui: llms.txt - Official AI-optimized reference
  • 架构references/architecture.md - 组件、路由、Suspense、数据模式、AI目录结构
  • 样式references/styling.md - 主题、字体、圆角、动画、CSS变量
  • 侧边栏references/sidebar.md - 带嵌套布局的shadcn侧边栏
  • 项目设置references/project-setup.md - bun命令、预设
  • shadcn/uillms.txt - 官方AI优化参考

Package Manager

包管理器

Always use bun, never npm or npx:
  • bun install
    (not npm install)
  • bun add
    (not npm install package)
  • bunx --bun
    (not npx)
始终使用bun,绝不要使用npm或npx:
  • bun install
    (替代npm install)
  • bun add
    (替代npm install package)
  • bunx --bun
    (替代npx)