Type-Safe Backend Requests with tRPC
The boilerplate project includes tRPC, a framework for building type-safe APIs that ensures your front-end and back-end remain in sync. With tRPC, any changes in the backend will break the front-end during development, notifying you to make the necessary updates. This guide will help you understand how to add a new router and ensure your backend requests are type-safe.
Key Features
- Type-Safe Requests: Ensures synchronization between front-end and back-end types.
- Automatic Error Detection: Front-end will break during development if there are mismatches, alerting you to update your code.
- Simple Router Configuration: Easily add new routers and procedures.
Setup
Step 1: Create a New Router
To add a new router, create a file in the src/server/routers
directory. Here is an example of how to create a simple post
router.
import { z } from "zod";
import { createPost } from "../service/post-service";
import { protectedProcedure, router } from "../trpc";
export const createPostRouter = () => {
return router({
createPost: protectedProcedure
.input(
z.object({
text: z.string(),
image: z.string().optional(),
})
)
.mutation(async (opts) => {
const userId = opts.ctx.session.user.id;
const { image, text } = opts.input;
try {
const newPost = await createPost({
text,
image,
userId,
});
return newPost;
} catch (error: any) {
throw new Error("Error creating post: " + error.message);
}
}),
});
};
You can define your procedures as protectedProcedure
or publicProcedure
based on the requirement.
- protectedProcedure: Requires authentication.
- publicProcedure: Does not require authentication.
Step 2: Add the Router to _app.tsx
After creating the router, add it to your application by modifying src/server/routers/_app.tsx
.
import { router } from "../trpc";
import { createPostRouter } from "./post";
// Combine your routers
export const appRouter = router({
post: createPostRouter(),
// Add more routers here
});
// Export type definition of API
export type AppRouter = typeof appRouter;
Step 3: Use Your Route in the Front-End
Here is an example of how you might use the createPost
procedure in your front-end code:
import { trpc } from "../shared/utils/trpc";
const { mutateAsync: createPost } = trpc.post.createPost.useMutation();
const handleCreatePost = async (text: string, image?: string) => {
try {
await createPost({ text, image });
console.log("Post created successfully");
} catch (error) {
console.error("Error creating post:", error);
}
};
// Call this function as needed in your component
Summary
By following these steps, you can quickly and easily set up type-safe backend requests in your project using tRPC. This system ensures that any changes in the backend are reflected in the front-end, helping you maintain consistency and catch errors early in the development process.