API Overview
TrendGate uses multiple API approaches for different use cases.
API Architecture​
Server Actions​
Primary method for client-server communication:
- Type-safe
- Automatic validation
- Built-in error handling
- Optimistic updates
tRPC API​
For complex queries and real-time features:
- End-to-end type safety
- Subscription support
- Batching
- Caching
REST API​
For external integrations:
- Standard HTTP methods
- JSON responses
- API versioning
- Rate limiting
Server Actions​
Basic Action​
"use server";
import { auth } from "@clerk/nextjs";
import { prisma } from "@/lib/db";
export async function createSession(data: SessionData) {
const { userId } = auth();
if (!userId) {
throw new Error("Unauthorized");
}
const session = await prisma.session.create({
data: {
...data,
instructorId: userId,
},
});
return session;
}
Using Actions​
import { createSession } from "@/actions/sessions";
function CreateSessionForm() {
async function handleSubmit(formData: FormData) {
const result = await createSession({
title: formData.get("title") as string,
startTime: new Date(formData.get("startTime") as string),
});
if (result.error) {
// Handle error
} else {
// Handle success
}
}
return <form action={handleSubmit}>{/* Form fields */}</form>;
}
Error Handling​
Action Errors​
export async function updateProfile(data: ProfileData) {
try {
// Validation
const validated = profileSchema.parse(data);
// Update
const profile = await prisma.user.update({
where: { id: userId },
data: validated,
});
return { success: true, data: profile };
} catch (error) {
if (error instanceof ZodError) {
return { success: false, error: "Validation failed" };
}
return { success: false, error: "Update failed" };
}
}
Data Validation​
Using Zod​
import { z } from "zod";
const sessionSchema = z.object({
title: z.string().min(3).max(100),
description: z.string().optional(),
startTime: z.date(),
duration: z.number().min(15).max(480),
maxParticipants: z.number().min(1).max(50),
});
export async function createSession(data: z.infer<typeof sessionSchema>) {
const validated = sessionSchema.parse(data);
// Use validated data
}
API Routes​
For specific needs beyond server actions:
Webhook Handler​
// app/api/webhooks/clerk/route.ts
import { headers } from "next/headers";
import { Webhook } from "svix";
export async function POST(req: Request) {
const webhook = new Webhook(process.env.CLERK_WEBHOOK_SECRET!);
const payload = await req.json();
const heads = headers();
const evt = webhook.verify(payload, {
"svix-id": heads.get("svix-id")!,
"svix-timestamp": heads.get("svix-timestamp")!,
"svix-signature": heads.get("svix-signature")!,
});
// Handle webhook event
return new Response("OK", { status: 200 });
}