快速开始
让我们构建一个简单的功能来理解 NextShip 的工作原理。
理解技术栈
NextShip 使用以下核心技术:
| 层级 | 技术 | 用途 |
|---|---|---|
| 前端 | React 19 + Next.js 15 | UI 和路由 |
| 样式 | Tailwind CSS v4 + shadcn/ui | 组件和样式 |
| API | tRPC + Server Actions | 类型安全的 API 调用 |
| 数据库 | Drizzle ORM + PostgreSQL | 数据持久化 |
| 认证 | Better Auth | 用户认证 |
添加新页面
- 在
src/app/[locale]/(dashboard)/中创建新文件:
// src/app/[locale]/(dashboard)/my-page/page.tsx
import { setRequestLocale } from "next-intl/server";
export default async function MyPage({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
setRequestLocale(locale);
return (
<div className="container py-8">
<h1 className="text-2xl font-bold">我的新页面</h1>
</div>
);
}添加数据库表
- 在
src/lib/db/schema.ts中定义表结构:
export const projects = pgTable("projects", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
name: text("name").notNull(),
userId: text("user_id").references(() => users.id),
createdAt: timestamp("created_at").defaultNow(),
});- 推送更改:
pnpm db:push创建 tRPC 路由
- 在
src/server/trpc/routers/中添加新路由:
// src/server/trpc/routers/project.ts
import { z } from "zod";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { projects } from "@/lib/db/schema";
export const projectRouter = createTRPCRouter({
list: protectedProcedure.query(async ({ ctx }) => {
return ctx.db
.select()
.from(projects)
.where(eq(projects.userId, ctx.user.id));
}),
create: protectedProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ ctx, input }) => {
return ctx.db.insert(projects).values({
name: input.name,
userId: ctx.user.id,
});
}),
});- 在根路由(
src/server/trpc/router.ts)中注册。
在组件中使用 API
"use client";
import { trpc } from "@/lib/trpc/client";
export function ProjectList() {
const { data: projects, isLoading } = trpc.project.list.useQuery();
if (isLoading) return <div>加载中...</div>;
return (
<ul>
{projects?.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
);
}