nextjs-shadcn
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNext.js 16 + shadcn/ui
Next.js 16 + shadcn/ui
Build distinctive, production-grade interfaces that avoid generic "AI slop" aesthetics.
打造独特的、生产级别的界面,避免千篇一律的「AI流水线风格」美学。
Core Principles
核心原则
- Minimize noise - Icons communicate; excessive labels don't
- No generic AI-UI - Avoid purple gradients, excessive shadows, predictable layouts
- Context over decoration - Every element serves a purpose
- Theme consistency - Use CSS variables from , never hardcode colors
globals.css
- 减少冗余 - 图标传递信息;过多的标签则无需存在
- 拒绝通用AI界面 - 避免紫色渐变、过度阴影、可预测的布局
- 功能优先于装饰 - 每个元素都有明确用途
- 主题一致性 - 使用中的CSS变量,绝不硬编码颜色
globals.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 nextbash
bunx --bun shadcn@latest create --preset "https://ui.shadcn.com/init?base=radix&style=nova&baseColor=neutral&iconLibrary=lucide&font=geist-sans" --template nextComponent 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
客户端边界
- only at leaf components (smallest boundary)
"use client" - 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., ) instead of relative paths ().
@/@/lib/utils../../lib/utils始终使用别名(例如),而非相对路径()。
@/@/lib/utils../../lib/utilsStyle 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 functions
'use cache'
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 for request interception (replaces middleware). Place at project root:
proxy.tstsx
// 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.tstsx
// 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/ui:llms.txt - 官方AI优化参考
Package Manager
包管理器
Always use bun, never npm or npx:
- (not npm install)
bun install - (not npm install package)
bun add - (not npx)
bunx --bun
始终使用bun,绝不要使用npm或npx:
- (替代npm install)
bun install - (替代npm install package)
bun add - (替代npx)
bunx --bun