这是一个基于 Next.js 16 + shadcn/ui 的全栈应用项目,由扣子编程 CLI 创建。
coze dev
启动后,在浏览器中打开 http://localhost:5000 查看应用。
开发服务器支持热更新,修改代码后页面会自动刷新。
coze build
coze start
src/
├── app/ # Next.js App Router 目录
│ ├── layout.tsx # 根布局组件
│ ├── page.tsx # 首页
│ ├── globals.css # 全局样式(包含 shadcn 主题变量)
│ └── [route]/ # 其他路由页面
├── components/ # React 组件目录
│ └── ui/ # shadcn/ui 基础组件(优先使用)
│ ├── button.tsx
│ ├── card.tsx
│ └── ...
├── lib/ # 工具函数库
│ └── utils.ts # cn() 等工具函数
└── hooks/ # 自定义 React Hooks(可选)
server/
├── index.ts # 自定义服务器入口
├── tsconfig.json # Server TypeScript 配置
└── dist/ # 编译输出目录(自动生成)
优先使用 shadcn/ui 基础组件
本项目已预装完整的 shadcn/ui 组件库,位于 src/components/ui/ 目录。开发时应优先使用这些组件作为基础:
// ✅ 推荐:使用 shadcn 基础组件
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
export default function MyComponent() {
return (
<Card>
<CardHeader>标题</CardHeader>
<CardContent>
<Input placeholder="输入内容" />
<Button>提交</Button>
</CardContent>
</Card>
);
}
可用的 shadcn 组件清单
button, input, textarea, select, checkbox, radio-group, switch, slidercard, separator, tabs, accordion, collapsible, scroll-areaalert, alert-dialog, dialog, toast, sonner, progressdropdown-menu, menubar, navigation-menu, context-menutable, avatar, badge, hover-card, tooltip, popovercalendar, command, carousel, resizable, sidebar详见 src/components/ui/ 目录下的具体组件实现。
Next.js 使用文件系统路由,在 src/app/ 目录下创建文件夹即可添加路由:
# 创建新路由 /about
src/app/about/page.tsx
# 创建动态路由 /posts/[id]
src/app/posts/[id]/page.tsx
# 创建路由组(不影响 URL)
src/app/(marketing)/about/page.tsx
# 创建 API 路由
src/app/api/users/route.ts
页面组件示例
// src/app/about/page.tsx
import { Button } from '@/components/ui/button';
export const metadata = {
title: '关于我们',
description: '关于页面描述',
};
export default function AboutPage() {
return (
<div>
<h1>关于我们</h1>
<Button>了解更多</Button>
</div>
);
}
动态路由示例
// src/app/posts/[id]/page.tsx
export default async function PostPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
return <div>文章 ID: {id}</div>;
}
API 路由示例
// src/app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
return NextResponse.json({ users: [] });
}
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json({ success: true });
}
必须使用 pnpm 管理依赖
# ✅ 安装依赖
pnpm install
# ✅ 添加新依赖
pnpm add package-name
# ✅ 添加开发依赖
pnpm add -D package-name
# ❌ 禁止使用 npm 或 yarn
# npm install # 错误!
# yarn add # 错误!
项目已配置 preinstall 脚本,使用其他包管理器会报错。
使用 Tailwind CSS v4
本项目使用 Tailwind CSS v4 进行样式开发,并已配置 shadcn 主题变量。
// 使用 Tailwind 类名
<div className="flex items-center gap-4 p-4 rounded-lg bg-background">
<Button className="bg-primary text-primary-foreground">
主要按钮
</Button>
</div>
// 使用 cn() 工具函数合并类名
import { cn } from '@/lib/utils';
<div className={cn(
"base-class",
condition && "conditional-class",
className
)}>
内容
</div>
主题变量
主题变量定义在 src/app/globals.css 中,支持亮色/暗色模式:
--background, --foreground--primary, --primary-foreground--secondary, --secondary-foreground--muted, --muted-foreground--accent, --accent-foreground--destructive, --destructive-foreground--border, --input, --ring推荐使用 react-hook-form + zod 进行表单开发:
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
const formSchema = z.object({
username: z.string().min(2, '用户名至少 2 个字符'),
email: z.string().email('请输入有效的邮箱'),
});
export default function MyForm() {
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: { username: '', email: '' },
});
const onSubmit = (data: z.infer<typeof formSchema>) => {
console.log(data);
};
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
<Input {...form.register('username')} />
<Input {...form.register('email')} />
<Button type="submit">提交</Button>
</form>
);
}
服务端组件(推荐)
// src/app/posts/page.tsx
async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
cache: 'no-store', // 或 'force-cache'
});
return res.json();
}
export default async function PostsPage() {
const posts = await getPosts();
return (
<div>
{posts.map(post => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
}
客户端组件
'use client';
import { useEffect, useState } from 'react';
export default function ClientComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
}, []);
return <div>{JSON.stringify(data)}</div>;
}
src/app/ 下创建文件夹和 page.tsxlayout.tsx 和 loading.tsxsrc/components/ 下创建组件文件(非 UI 组件)src/components/ui/ 中的基础组件推荐使用 React Context 或 Zustand:
// src/lib/store.ts
import { create } from 'zustand';
interface Store {
count: number;
increment: () => void;
}
export const useStore = create<Store>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
推荐使用 Prisma 或 Drizzle ORM,在 src/lib/db.ts 中配置。
@/ 路径别名 导入模块(已配置)