Market Flash
Mega-cap AI budgets are moving from pilot projects to core planning cycles
Cyber resilience spending is climbing as boards rethink operational risk
CEO succession is turning into a valuation issue for large public companies
Payments and software deal talk is heating up again across the market
Margin discipline is still winning earnings season when demand stays intact
TypeScriptMike Rodriguez

Building Type-Safe APIs with TypeScript and tRPC

Type safety across the full stack eliminates an entire class of bugs. Learn how to build end-to-end type-safe APIs using TypeScript, tRPC, and Zod validation.

import { initTRPC, TRPCError } from "@trpc/server";
import { z } from "zod";

const t = initTRPC.context<Context>().create();

const postRouter = t.router({
  list: t.procedure
    .input(z.object({
      limit: z.number().min(1).max(100).default(20),
      cursor: z.string().optional(),
    }))
    .query(async ({ input, ctx }) => {
      const posts = await ctx.db.post.findMany({
        take: input.limit + 1,
        cursor: input.cursor ? { id: input.cursor } : undefined,
        orderBy: { createdAt: "desc" },
      });

      let nextCursor: string | undefined;
      if (posts.length > input.limit) {
        const nextItem = posts.pop();
        nextCursor = nextItem?.id;
      }

      return { posts, nextCursor };
    }),

  create: t.procedure
    .input(z.object({
      title: z.string().min(1).max(200),
      content: z.string().min(1),
      tags: z.array(z.string()).max(5),
    }))
    .mutation(async ({ input, ctx }) => {
      if (!ctx.session?.user) {
        throw new TRPCError({ code: "UNAUTHORIZED" });
      }
      return ctx.db.post.create({
        data: { ...input, authorId: ctx.session.user.id },
      });
    }),
});

More Stories