Skip to main content

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 });
}

API Documentation​