{"id":5272,"date":"2022-07-22T22:04:01","date_gmt":"2022-07-22T22:04:01","guid":{"rendered":"https:\/\/codevoweb.com\/?p=5272"},"modified":"2022-10-27T16:23:37","modified_gmt":"2022-10-27T16:23:37","slug":"setup-trpc-api-with-prisma-postgresql-nodejs-reactjs","status":"publish","type":"post","link":"https:\/\/codevoweb.com\/setup-trpc-api-with-prisma-postgresql-nodejs-reactjs\/","title":{"rendered":"How to Setup tRPC API with Prisma, PostgreSQL, Node &#038; React"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.npmjs.com\/package\/create-t3-app\" target=\"_blank\" rel=\"noreferrer noopener\">t3-stack<\/a> popularly known as <a href=\"https:\/\/trpc.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">tRPC<\/a> is a lightweight library tailored specifically for building end-to-end typesafe APIs without the need for defined schemas or extra dependencies for code generation. This article will teach you how to use <a href=\"https:\/\/classic.yarnpkg.com\/en\/docs\/workspaces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Yarn Workspaces<\/a> to set up <strong><a href=\"https:\/\/trpc.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">tRPC<\/a><\/strong> with React.js, Express, Prisma, PostgreSQL, and Node.js.<\/p>\n\n\n\n<p>At the time of writing this article, <strong>@tRPC\/server<\/strong> now has adaptors for AWS Lambda, Express, and Fastify. Whereas the <strong>@tRPC\/client<\/strong> can be used to create  Vanilla, React.js, and Next.js clients.<\/p>\n\n\n\n<p>In addition, the developer communities are working hard to create tRPC extensions for other frameworks, like Vue.js, Svelte, and many more.<\/p>\n\n\n\n<p>tRPC API with React.js, Express, Prisma, Postgres, and Node.js Series:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"\/setup-trpc-api-with-prisma-postgresql-nodejs-reactjs\">How to Setup tRPC API with Prisma, PostgreSQL, Node &amp; React<\/a><\/li><li><a href=\"\/trpc-api-with-postgres-prisma-nodejs-jwt-authentication\">tRPC API with PostgreSQL, Prisma, Redis, &amp; Node.js: JWT Authentication<\/a><\/li><\/ol>\n\n\n\n<p>Read more articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"\/trpc-api-reactjs-nodejs-mongodb-project-setup\">Build tRPC API with React.js, Express &amp; Node.js: Project Setup<\/a><\/li><li><a href=\"\/golang-mongodb-jwt-authentication-authorization\">Golang &amp; MongoDB: JWT Authentication and Authorization<\/a><\/li><li><a href=\"\/api-golang-mongodb-send-html-emails-gomail\">API with Golang + MongoDB: Send HTML Emails with Gomail<\/a><\/li><li><a href=\"\/api-golang-gin-gonic-mongodb-forget-reset-password\">API with Golang, Gin Gonic &amp; MongoDB: Forget\/Reset Password<\/a><\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"850\" height=\"478\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/How-to-Setup-tRPC-API-with-Prisma-PostgreSQL-Node-React.webp\" alt=\"How to Setup tRPC API with Prisma, PostgreSQL, Node &amp; React\" class=\"wp-image-5360\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/How-to-Setup-tRPC-API-with-Prisma-PostgreSQL-Node-React.webp 850w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/How-to-Setup-tRPC-API-with-Prisma-PostgreSQL-Node-React-300x169.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/How-to-Setup-tRPC-API-with-Prisma-PostgreSQL-Node-React-768x432.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/How-to-Setup-tRPC-API-with-Prisma-PostgreSQL-Node-React-100x56.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/How-to-Setup-tRPC-API-with-Prisma-PostgreSQL-Node-React-700x394.webp 700w\" sizes=\"auto, (max-width: 850px) 100vw, 850px\" \/><\/figure>\n\n\n<style>.kb-table-of-content-nav.kb-table-of-content-id_5dd6d4-ad .kb-table-of-content-wrap{padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;border-color:#abb8c3;border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;}.kb-table-of-content-nav.kb-table-of-content-id_5dd6d4-ad .kb-table-of-contents-title-wrap{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id_5dd6d4-ad .kb-table-of-contents-title-wrap{color:#ffffff;}.kb-table-of-content-nav.kb-table-of-content-id_5dd6d4-ad .kb-table-of-contents-title{color:#ffffff;font-weight:regular;font-style:normal;}.kb-table-of-content-nav.kb-table-of-content-id_5dd6d4-ad .kb-table-of-content-wrap .kb-table-of-content-list{color:#ffffff;font-weight:regular;font-style:normal;margin-top:10px;margin-right:0px;margin-bottom:0px;margin-left:-5px;}<\/style>\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before you begin, you should:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Have <a href=\"https:\/\/nodejs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Node.js installed<\/a> on your system<\/li><li>Be comfortable with Node.js and Express<\/li><li>Be comfortable with React.js<\/li><\/ul>\n\n\n\n<span id=\"ezoic-pub-video-placeholder-38\"><\/span>\n\n\n\n<h2 class=\"wp-block-heading\">What is tRPC?<\/h2>\n\n\n\n<p><a href=\"https:\/\/trpc.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">tRPC<\/a> is a lightweight toolkit that allows developers to use the power of TypeScript to build end-to-end typesafe APIs with Express, Fastify, AWS Lambda, and more without the need to create schemas or install extra dependencies for code generation.<\/p>\n\n\n\n<p>Whether you are new to this web development ecosystem or you are a veteran player, you may have noticed that GraphQL is the dominant library for building type-safety APIs using a query language.<\/p>\n\n\n\n<p>GraphQL is amazing and solved most of our miseries, however, it doesn&#8217;t take full advantage of TypeScript to write type-safety APIs.<\/p>\n\n\n\n<p>For this reason, <a href=\"https:\/\/trpc.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">tRPC<\/a> was introduced to use the full power of TypeScript to build full-stack type-safety applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setup PostgreSQL and Redis with Docker<\/h2>\n\n\n\n<p>PostgreSQL is a powerful, free, and open-source relational database management system used as the primary data store for web, and mobile applications.<\/p>\n\n\n\n<p>Running PostgreSQL with Docker and docker-compose gives you the ability to easily run and maintain it, especially in a development environment.<\/p>\n\n\n\n<p>To simply run the containers using the Postgres and Redis Docker images we can create a <code>docker-compose.yml<\/code> file with the required configurations.<\/p>\n\n\n\n<p>First, create a project folder named <code>trpc-prisma-react<\/code> and open it with your preferred IDE or text editor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ mkdir trpc-prisma-react<\/code><\/pre>\n\n\n\n<p>Next, create a <code>docker-compose.yml<\/code> in the project directory and add the following configurations to set up the Redis and PostgreSQL containers.<\/p>\n\n\n\n<p> <strong>docker-compose.yml<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nversion: '3'\nservices:\n  postgres:\n    image: postgres\n    container_name: postgres\n    ports:\n      - '6500:5432'\n    restart: always\n    env_file:\n      - .\/.env\n    volumes:\n      - postgres-db:\/var\/lib\/postgresql\/data\n  redis:\n    image: redis:latest\n    container_name: redis\n    ports:\n      - '6379:6379'\n    volumes:\n      - redis:\/data\nvolumes:\n  postgres-db:\n  redis:\n<\/code>\n<\/pre>\n\n\n\n<p>Create a <code>.env<\/code> file and add the following environment variables to send in the Postgres user, database name, and password.<\/p>\n\n\n\n<p><strong>.env<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nDATABASE_PORT=6500\nPOSTGRES_PASSWORD=password123\nPOSTGRES_USER=postgres\nPOSTGRES_DB=trpc_prisma\nPOSTGRES_HOST=postgres\nPOSTGRES_HOSTNAME=127.0.0.1\n<\/code>\n<\/pre>\n\n\n\n<p>After this quick setup, start the containers with this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose up -d<\/code><\/pre>\n\n\n\n<p>Execute this command to stop the containers: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose down<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Use Yarn Workspaces to Setup Monolithic Repository<\/h2>\n\n\n\n<p>First, let&#8217;s build a monorepo for the tRPC project with Yarn. For those who are new to the web and mobile development ecosystem, Yarn is simply a package manager developed by the guys at Facebook. It has a tool called&nbsp;<a href=\"https:\/\/yarnpkg.com\/lang\/en\/docs\/workspaces\/\" target=\"_blank\" rel=\"noopener\">Yarn workspaces<\/a>, for organizing a project codebase into a monolithic repository.<\/p>\n\n\n\n<p>With the explanation above, create a <code>package.json<\/code> file in the root workspace:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>touch package.json<\/code><\/pre>\n\n\n\n<p>Next, add the following code to the newly-created&nbsp;<code>package.json<\/code>&nbsp;file:<\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n  \"name\": \"trpc-node-react\",\n  \"private\": \"true\",\n  \"scripts\": {},\n  \"workspaces\": [\n    \"packages\/*\"\n  ]\n}\n<\/code>\n<\/pre>\n\n\n\n<p>Workspaces are not meant to be published so we need to set the private property to <strong>true<\/strong> in the <strong>package.json<\/strong> file to avoid publishing the root workspace by mistake.<\/p>\n\n\n\n<p>Next, we used wildcard (*) in the &#8220;<strong>workspaces<\/strong>&#8221; array for Yarn to recognize the folders in the &#8220;<strong>packages<\/strong>&#8221; directory as packages.<\/p>\n\n\n\n<p>Don&#8217;t be anxious, we will create the &#8220;<strong>packages<\/strong>&#8221; folder in a moment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create a Script to Start the tRPC client and server<\/h3>\n\n\n\n<p>Now let&#8217;s install the&nbsp;<a href=\"https:\/\/www.npmjs.com\/package\/concurrently\" target=\"_blank\" rel=\"noopener\"><code>concurrently<\/code><\/a> and <code>wsrun<\/code> packages help us start the <strong>tRPC<\/strong> client and server in parallel.<\/p>\n\n\n\n<p>Using this approach will save us a lot of time since we do not have to manually change directories in the terminal to run the start scripts of the tRPC client and server.<\/p>\n\n\n\n<p>Install the <code>concurrently<\/code> and <code>wsrun<\/code> packages with this command:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn add -W -D concurrently wsrun\n<\/code>\n<\/pre>\n\n\n\n<p>The &#8220;<strong>-W<\/strong>&#8221; flag tells Yarn to add the dependencies to the workspace itself. Whereas the &#8220;<strong>-D<\/strong>&#8221; flag tells Yarn to add the packages as dev-dependencies.<\/p>\n\n\n\n<p>Update the&nbsp;<strong>package.json<\/strong> file in the root workspace with the following:<\/p>\n\n\n\n<p><strong>package.json<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n  \"name\": \"trpc-prisma-react\",\n  \"private\": \"true\",\n  \"scripts\": {\n    \"start\": \"concurrently \\\"wsrun --parallel start\\\"\"\n  },\n  \"workspaces\": [\n    \"packages\/*\"\n  ],\n  \"devDependencies\": {\n    \"concurrently\": \"^7.3.0\",\n    \"wsrun\": \"^5.2.4\"\n  }\n}\n\n<\/code>\n<\/pre>\n\n\n\n<p>The start script in the above will help us execute the start scripts in the tRPC client and server in parallel.<\/p>\n\n\n\n<p>Since we will be pushing the project to GitHub, create a <code>.gitignore<\/code> file in the root workspace and exclude the <strong>node_modules<\/strong>.<\/p>\n\n\n\n<p><strong>.gitignore<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nnode_modules\n<\/code>\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the tRPC Node.js Server in Express<\/h2>\n\n\n\n<p>We are now ready to set up the <strong>tRPC<\/strong> Express Node.js server. <\/p>\n\n\n\n<p>First, create a &#8220;<strong>server<\/strong>&#8221; folder in the &#8220;<strong>packages<\/strong>&#8221; folder then open the integrated terminal and change the directory into it <code>cd packages\/server<\/code> .<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd packages\/server<\/code><\/pre>\n\n\n\n<p>Now run the command below to initialize a Node.js TypeScript project with Yarn:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn init -y &amp;&amp; yarn add -D typescript &amp;&amp; npx tsc --init \n<\/code>\n<\/pre>\n\n\n\n<p>Next, open the newly-created &#8220;<strong>tsconfig.json<\/strong>&#8221; file and replace its content with the following configurations:<\/p>\n\n\n\n<p><strong>packages\/server\/tsconfig.json<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n  \"compilerOptions\": {\n    \"target\": \"es2018\",\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true,\n    \"module\": \"commonjs\",\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"strictPropertyInitialization\": false,\n    \"skipLibCheck\": true\n  }\n}\n<\/code>\n<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><code>experimentalDecorators<\/code> &#8211; allows you to set <a href=\"https:\/\/github.com\/tc39\/proposal-decorators\" target=\"_blank\" rel=\"noreferrer noopener\">experimental support for decorators<\/a>.<\/li><li><code>emitDecoratorMetadata<\/code> &#8211; allows you to enable experimental support for emitting type metadata for the decorators.<\/li><li><code>strictPropertyInitialization<\/code> &#8211; needed to prevent Typescript from raising errors when we declare the Typegoose class attributes without initializing them.<\/li><\/ul>\n\n\n\n<p>Add the dependencies required to set up the <strong>tRPC<\/strong> server with Express:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn add @trpc\/server@next cors dotenv express @prisma\/client redis &amp;&amp; yarn add -D prisma @types\/cors @types\/express @types\/node morgan @types\/morgan ts-node-dev\n<\/code>\n<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><code><a href=\"https:\/\/www.npmjs.com\/package\/@trpc\/server\" target=\"_blank\" rel=\"noreferrer noopener\">@trpc\/server<\/a><\/code> &#8211; has tools for building the <strong>tRPC<\/strong> endpoints and routers<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/cors\" target=\"_blank\" rel=\"noreferrer noopener\">cors<\/a><\/code> &#8211; needed to configure the <strong>tRPC<\/strong> Express server to accept requests from cross-origin domains.<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/dotenv\" target=\"_blank\" rel=\"noreferrer noopener\">dotenv<\/a><\/code> &#8211; loads the environment variables from a configuration file into the Node.js environment.<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/express\" target=\"_blank\" rel=\"noreferrer noopener\">express<\/a><\/code> &#8211; a lightweight Node.js framework for building web and mobile applications.<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/@prisma\/client\" target=\"_blank\" rel=\"noreferrer noopener\">@prisma\/client<\/a><\/code> &#8211; the query builder for Prisma<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/prisma\" target=\"_blank\" rel=\"noreferrer noopener\">prisma<\/a><\/code> &#8211; the CLI for running Prisma commands<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/redis\" target=\"_blank\" rel=\"noreferrer noopener\">redis<\/a><\/code> &#8211; a JavaScript library for accessing and mutating the Redis database<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/ts-node-dev\" target=\"_blank\" rel=\"noreferrer noopener\">ts-node-dev<\/a><\/code> &#8211; to hot-reload the <strong>tRPC<\/strong> Express server upon every file change.<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/morgan\" target=\"_blank\" rel=\"noreferrer noopener\">morgan<\/a><\/code> &#8211; an HTTP logger middleware<\/li><\/ul>\n\n\n\n<p>The security of the <strong>tRPC<\/strong> application is very important and it&#8217;s always a best practice to store sensitive data in an environment variables file. Create a <code>packages\/server\/.env<\/code> file and add the following credentials:<\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nNODE_ENV=development\n\nORIGIN=http:\/\/127.0.0.1:3000\n\nDATABASE_URL=\"postgresql:\/\/postgres:password123@localhost:6500\/trpc_prisma?schema=public\"\n<\/code>\n<\/pre>\n\n\n\n<p>Open the <code>packages\/server\/package.json<\/code> file and add the start script to help us start the tRPC Express server.<\/p>\n\n\n\n<p><strong>packages\/server\/package.json<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n\"scripts\": {\n    \"start\": \"ts-node-dev --respawn --transpile-only src\/app.ts\"\n  }\n}\n<\/code>\n<\/pre>\n\n\n\n<p>Within the <code>packages\/server<\/code> folder, create an &#8220;<strong>src<\/strong>&#8221; folder. Next, create two folders named &#8220;<strong>config<\/strong>&#8221; and &#8220;<strong>utils<\/strong>&#8221; in the &#8220;<strong>src<\/strong>&#8221; directory.<\/p>\n\n\n\n<p>Next, create a <code>default.ts<\/code> file in the &#8220;<strong>config<\/strong>&#8221; directory to enable us to load and export the environment variables.<\/p>\n\n\n\n<p><strong>packages\/server\/src\/config\/default.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport path from 'path';\nrequire('dotenv').config({ path: path.join(__dirname, '..\/..\/.env') });\n\nconst customConfig: { port: number; origin: string; dbUri: string } = {\n  port: 8000,\n  origin: process.env.ORIGIN as unknown as string,\n\n  dbUri: process.env.DATABASE_URL as unknown as string,\n};\n\nexport default customConfig;\n\n<\/code>\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Connect the tRPC Server to PostgreSQL and Redis<\/h3>\n\n\n\n<p>Now that we have the Redis and PostgreSQL servers running in the Docker containers, let&#8217;s define some utility functions to connect them to the <strong>tRPC<\/strong> server.<\/p>\n\n\n\n<p><strong>packages\/server\/src\/utils\/prisma.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport { PrismaClient } from '@prisma\/client';\n\ndeclare global {\n  var prisma: PrismaClient | undefined;\n}\n\nexport const prisma =\n  global.prisma || new PrismaClient({ log: ['query', 'info'] });\n\nif (process.env.NODE_ENV !== 'production') {\n  global.prisma = prisma;\n}\n\nasync function connectDB() {\n  try {\n    await prisma.$connect();\n    console.log('? Database connected successfully');\n  } catch (error) {\n    console.log(error);\n    process.exit(1);\n  } finally {\n    await prisma.$disconnect();\n  }\n}\n\nexport default connectDB;\n<\/code>\n<\/pre>\n\n\n\n<p><strong>packages\/server\/src\/utils\/connectRedis.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport { createClient } from 'redis';\n\nconst redisUrl = `redis:\/\/localhost:6379`;\nconst redisClient = createClient({\n  url: redisUrl,\n});\n\nconst connectRedis = async () =&gt; {\n  try {\n    await redisClient.connect();\n    console.log('? Redis client connected...');\n    redisClient.set(\n      'tRPC',\n      '??Welcome to tRPC with React.js, Express and Typescript!'\n    );\n  } catch (err: any) {\n    console.log(err.message);\n    process.exit(1);\n  }\n};\n\nconnectRedis();\n\nredisClient.on('error', (err) =&gt; console.log(err));\n\nexport default redisClient;\n<\/code>\n<\/pre>\n\n\n\n<p>In the above, we created a function to connect to the Redis server and evoked the <code>redisClient.set()<\/code> function returned by calling the <code>createClient()<\/code> function to add a message to the Redis database with a &#8220;<strong>tRPC<\/strong>&#8221; key.<\/p>\n\n\n\n<p>Later, we will request the message from the Redis database and send it to the <strong>tRPC<\/strong> React.js client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Starting the tRPC Express Server<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Creating the tRPC Context<\/h4>\n\n\n\n<p>Now let&#8217;s create a context function that will be called for every incoming request and the results will be passed as contextual data to all the resolvers. <\/p>\n\n\n\n<p><strong>packages\/server\/src\/app.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport path from 'path';\nimport dotenv from 'dotenv';\nimport express from 'express';\nimport morgan from 'morgan';\nimport cors from 'cors';\nimport { inferAsyncReturnType, initTRPC, TRPCError } from \"@trpc\/server\";\nimport * as trpcExpress from '@trpc\/server\/adapters\/express';\nimport redisClient from '.\/utils\/connectRedis';\nimport customConfig from '.\/config\/default';\nimport connectDB from '.\/utils\/prisma';\n\ndotenv.config({ path: path.join(__dirname, '.\/.env') });\n\nconst createContext = ({\n  req,\n  res,\n}: trpcExpress.CreateExpressContextOptions) =&gt; ({ req, res });\n\nexport type Context = inferAsyncReturnType&lt;typeof createContext&gt;;\n\/\/ [...]\n<\/code>\n<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Creating the tRPC Router<\/h4>\n\n\n\n<p>Next, let&#8217;s use the &#8220;<strong>router()<\/strong>&#8221; function provided by <strong>tRPC<\/strong> to create a router to manage the <strong>tRPC<\/strong> endpoints. This will allow us to add:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Query endpoints &#8211; for requesting data <\/li><li>Mutation endpoints &#8211; to perform the <strong>Create<\/strong>, <strong>Update<\/strong>,<strong> <\/strong>and <strong>Delete<\/strong> operations.<\/li><li>Subscription endpoints &#8211; used to subscribe to data over WebSockets.<\/li><\/ul>\n\n\n\n<p><strong>packages\/server\/src\/app.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\n\/\/ [...]\nconst t = initTRPC.context&lt;Context&gt;().create();\n\nconst appRouter = t.router({\n  sayHello: t.procedure.query(async () =&gt; {\n    const message = await redisClient.get(\"tRPC\");\n    return { message };\n  }),\n});\n\nexport type AppRouter = typeof appRouter;\n<\/code>\n<\/pre>\n\n\n\n<p>Let\u2019s evaluate the code above:<\/p>\n\n\n\n<p>First, we initialized the tRPC server by evoking the <code>.context&lt;Context&gt;()<\/code> and <code>.create()<\/code> methods. Then, we created the tRPC router and added a <strong>sayHello<\/strong> procedure call. The sayHello query will be evoked by the tRPC client to return the message stored in the Redis database.<\/p>\n\n\n\n<p>The <code>appRouter<\/code> returned by evoking <code>t.router()<\/code> function maintains all the endpoints, including what the routes accept as inputs, and their outputs.<\/p>\n\n\n\n<p>Next, we exported the <strong>AppRouter<\/strong> type from the <code>packages\/server\/src\/app.ts<\/code> file. This will allow us to install the <strong>tRPC<\/strong> server as a package in the tRPC client in order for the React client to know the different queries, mutations, and subscriptions available on the <strong>tRPC<\/strong> server.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Configuring the Express tRPC Server<\/h4>\n\n\n\n<p><strong>packages\/server\/src\/app.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\n\/\/ [...]\nconst app = express();\nif (process.env.NODE_ENV !== \"production\") app.use(morgan(\"dev\"));\n\napp.use(\n  cors({\n    origin: [customConfig.origin, \"http:\/\/localhost:3000\"],\n    credentials: true,\n  })\n);\napp.use(\n  \"\/api\/trpc\",\n  trpcExpress.createExpressMiddleware({\n    router: appRouter,\n    createContext,\n  })\n);\n\nconst port = customConfig.port;\napp.listen(port, () =&gt; {\n  console.log(`\ud83d\ude80 Server listening on port ${port}`);\n\n  \/\/ CONNECT DB\n  connectDB();\n});\n<\/code>\n<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Complete Express tRPC Server Code<\/h4>\n\n\n\n<p><strong>packages\/server\/src\/app.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport path from \"path\";\nimport dotenv from \"dotenv\";\nimport express from \"express\";\nimport morgan from \"morgan\";\nimport cors from \"cors\";\nimport { inferAsyncReturnType, initTRPC } from \"@trpc\/server\";\nimport * as trpcExpress from \"@trpc\/server\/adapters\/express\";\nimport redisClient from \".\/utils\/connectRedis\";\nimport customConfig from \".\/config\/default\";\nimport connectDB from \".\/utils\/prisma\";\n\ndotenv.config({ path: path.join(__dirname, \".\/.env\") });\n\nconst createContext = ({\n  req,\n  res,\n}: trpcExpress.CreateExpressContextOptions) =&gt; ({ req, res });\n\nexport type Context = inferAsyncReturnType&lt;typeof createContext&gt;;\n\nconst t = initTRPC.context&lt;Context&gt;().create();\n\nconst appRouter = t.router({\n  sayHello: t.procedure.query(async () =&gt; {\n    const message = await redisClient.get(\"tRPC\");\n    return { message };\n  }),\n});\n\nexport type AppRouter = typeof appRouter;\n\nconst app = express();\nif (process.env.NODE_ENV !== \"production\") app.use(morgan(\"dev\"));\n\napp.use(\n  cors({\n    origin: [customConfig.origin, \"http:\/\/localhost:3000\"],\n    credentials: true,\n  })\n);\napp.use(\n  \"\/api\/trpc\",\n  trpcExpress.createExpressMiddleware({\n    router: appRouter,\n    createContext,\n  })\n);\n\nconst port = customConfig.port;\napp.listen(port, () =&gt; {\n  console.log(`\ud83d\ude80 Server listening on port ${port}`);\n\n  \/\/ CONNECT DB\n  connectDB();\n});\n<\/code>\n<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Turning the tRPC Express Server into a Library<\/h4>\n\n\n\n<p>To convert the  tRPC server into a library, we need to add <code>\"main\": \"src\/app.ts\"<\/code> to the <code>packages\/server\/package.json<\/code> file. This will allow us to have access to the <strong>AppRouter<\/strong> type when we install the <strong>tRPC<\/strong> server in the <strong>tRPC<\/strong> React.js client.<\/p>\n\n\n\n<p><strong>packages\/server\/package.json<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"866\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma-1024x866.webp\" alt=\"setup express nodejs trpc server with prisma\" class=\"wp-image-5333\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma-1024x866.webp 1024w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma-300x254.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma-768x649.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma-100x85.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma-532x450.webp 532w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/setup-express-nodejs-trpc-server-with-prisma.webp 1081w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><strong>packages\/server\/package.json<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n  \"name\": \"server\",\n  \"version\": \"1.0.0\",\n  \"main\": \"src\/app.ts\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"start\": \"ts-node-dev --respawn --transpile-only src\/app.ts\",\n    \"db:migrate\": \"npx prisma migrate dev --name user-entity --create-only &amp;&amp; yarn prisma generate\",\n    \"db:push\": \"npx prisma db push\"\n  },\n  \"devDependencies\": {\n    \"@types\/cors\": \"^2.8.12\",\n    \"@types\/express\": \"^4.17.14\",\n    \"@types\/morgan\": \"^1.9.3\",\n    \"morgan\": \"^1.10.0\",\n    \"prisma\": \"^4.5.0\",\n    \"ts-node-dev\": \"^2.0.0\",\n    \"typescript\": \"^4.8.4\"\n  },\n  \"dependencies\": {\n    \"@prisma\/client\": \"^4.5.0\",\n    \"@trpc\/server\": \"^10.0.0-proxy-beta.26\",\n    \"cors\": \"^2.8.5\",\n    \"dotenv\": \"^16.0.3\",\n    \"express\": \"^4.18.2\",\n    \"redis\": \"^4.3.1\"\n  }\n}\n<\/code>\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Database Migration with Prisma<\/h2>\n\n\n\n<p>There are other ORMs for Node.js but we are going to use Prisma to query and mutate the database. <\/p>\n\n\n\n<p>To get started, run the following code to initialize a new Prisma project in the <code>packages\/server<\/code> folder.<\/p>\n\n\n\n<p>Change the directory into the <code>packages\/server<\/code> folder and run this command:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nnpx prisma init\n<\/code><\/pre>\n\n\n\n<p>The above command will generate a new <code>packages\/server\/prisma<\/code> folder containing a <code>schema.prisma<\/code> file. Also, when you open the environment variables file in the server folder, you should see a <code>DATABASE_URL<\/code> variable added by the Prisma CLI.<\/p>\n\n\n\n<p>Now replace the content of the <code>packages\/server\/prisma\/schema.prisma<\/code> file with the following code:<\/p>\n\n\n\n<p><strong>packages\/server\/prisma\/schema.prisma<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\ngenerator client {\n  provider = \"prisma-client-js\"\n}\n\ndatasource db {\n  provider = \"postgresql\"\n  url      = env(\"DATABASE_URL\")\n}\n\n\nmodel User{\n  @@map(name: \"users\")\n\n  id String  @id @default(uuid())\n  name String  @db.VarChar(255)\n  email String @unique\n  photo String? @default(\"default.png\")\n  verified Boolean? @default(false) \n  \n  password String\n  role RoleEnumType? @default(user)\n\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n\n  provider String?\n}\n\nenum RoleEnumType {\n  user\n  admin\n}\n<\/code><\/pre>\n\n\n\n<p>Quite a lot going on in the above, let&#8217;s break it down:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>First, we created a <code>User<\/code> model and used the <code>@@map(name: \"users\")<\/code> attribute to change the table name to <code>users<\/code> .<\/li><li>Then we defined the attributes needed to create a new user in the database.<\/li><li>The <code>@default(uuid())<\/code> attribute sets a default <a href=\"https:\/\/www.prisma.io\/docs\/reference\/api-reference\/prisma-schema-reference#uuid\" target=\"_blank\" rel=\"noreferrer noopener\">UUID<\/a> value for the ID field in the database.<\/li><\/ul>\n\n\n\n<p>With the above explanation, add the following scripts to the <code>packages\/server\/package.json<\/code> file.<\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n\"scripts\": {\n    \"start\": \"ts-node-dev --respawn --transpile-only src\/app.ts\",\n    \"db:migrate\": \"npx prisma migrate dev --name user-entity --create-only &amp;&amp; yarn prisma generate\",\n    \"db:push\": \"npx prisma db push\"\n  },\n}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><code>db:migrate<\/code> &#8211; create a new Prisma migration file and generate the TypeScript types based on the defined model.<\/li><li><code>db:push<\/code> &#8211; push the changes to the PostgreSQL database and ensures that the database is in-sync with the schema.<\/li><\/ul>\n\n\n\n<p>Add the PostgreSQL credentials defined in the <code>.env<\/code> file to the <code>DATABASE_URL<\/code> added by the Prisma CLI.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nDATABASE_URL=\"postgresql:\/\/postgres:password123@localhost:6500\/trpc_prisma?schema=public\"\n<\/code><\/pre>\n\n\n\n<p>Now to create the <code>users<\/code> table in the PostgreSQL database, run the following command: <\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn db:migrate &amp;&amp; yarn db:push\n<\/code><\/pre>\n\n\n\n<p>When you log into the PostgreSQL database in pgAdmin with the credentials defined in the <code>.env<\/code> , you should see the <code>users<\/code> table with the following properties.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1005\" height=\"688\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/checking-the-prisma-model-attributes-in-postgresql-using-pgadmin.webp\" alt=\"checking the prisma model attributes in postgresql using pgadmin\" class=\"wp-image-5366\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/checking-the-prisma-model-attributes-in-postgresql-using-pgadmin.webp 1005w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/checking-the-prisma-model-attributes-in-postgresql-using-pgadmin-300x205.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/checking-the-prisma-model-attributes-in-postgresql-using-pgadmin-768x526.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/checking-the-prisma-model-attributes-in-postgresql-using-pgadmin-100x68.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/checking-the-prisma-model-attributes-in-postgresql-using-pgadmin-657x450.webp 657w\" sizes=\"auto, (max-width: 1005px) 100vw, 1005px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the tRPC Client in React.js<\/h2>\n\n\n\n<p>First, open the integrated terminal and change the directory into the &#8220;<strong>packages<\/strong>&#8221; folder to enable us to create a boilerplate React.js app with the <a href=\"https:\/\/vitejs.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">Vite<\/a> scaffolding tool.<\/p>\n\n\n\n<p>Run this command to scaffold a new Vite project with Yarn:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn create vite\n<\/code><\/pre>\n\n\n\n<p>The above command will install and execute the Vite executable from the remote&nbsp;<code>npm<\/code>&nbsp;repository and you will be presented with prompts for a number of features like:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The project name<\/li><li>The type of framework<\/li><li>TypeScript support<\/li><\/ul>\n\n\n\n<p>After the script has been executed, the tool will prompt you to enter a project name:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\n$ yarn create vite\nyarn create v1.22.19\n[1\/4] Resolving packages...\n[2\/4] Fetching packages...\n[3\/4] Linking dependencies...\n[4\/4] Building fresh packages...\n\nsuccess Installed \"create-vite@3.0.0\" with binaries:\n      - create-vite\n      - cva\n? Project name: \u00bb client\n<\/code><\/pre>\n\n\n\n<p>Type &#8220;<strong>client<\/strong>&#8221; as the project name and press the Enter key<\/p>\n\n\n\n<p>After pressing the Enter key, you will be prompted to select a framework<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\n? Select a framework: \u00bb - Use arrow-keys. Return to submit.\n    vanilla\n    vue\n&gt;   react\n    preact\n    lit\n    svelte\n\n<\/code><\/pre>\n\n\n\n<p>After using the arrow keys to select the framework, press the Enter key again and Vite will prompt you to choose the language type.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\n? Select a variant: \u00bb - Use arrow-keys. Return to submit.\n    react\n&gt;   react-ts\n<\/code><\/pre>\n\n\n\n<p>Select <code>react-ts<\/code> from the list and press the Enter key. Vite will then generate the project and instruct you to install the dependencies.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nScaffolding project in C:\\Users\\zidda\\Desktop\\Learn\\Blog\\tRPC\\trpc-prisma-react\\testing\\client...\n\nDone. Now run:\n\n  cd client\n  yarn\n  yarn dev\n\nDone in 544.96s.\n<\/code><\/pre>\n\n\n\n<p>Change the directory into the project folder as directed and run <code>yarn<\/code> to install the dependencies.<\/p>\n\n\n\n<p>Next, open the <code>packages\/client\/package.json<\/code> file and change the dev script to start. Also, add the port flag to start the dev server on port <strong>3000<\/strong>.<\/p>\n\n\n\n<p><strong>packages\/client\/package.json<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-json\"><code>\n{\n\"scripts\": {\n    \"start\": \"vite --port 3000\",\n    \"build\": \"tsc &amp;&amp; vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>We are now ready to install the <strong>tRPC<\/strong> server as a library in the React client. In your terminal, ensure that you are in the client folder and run the command below to install the <strong>tRPC<\/strong> server library.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn add server@1.0.0\n<\/code><\/pre>\n\n\n\n<p><code>server<\/code> &#8211; is the property name in the <code>packages\/server\/package.json<\/code> file<\/p>\n\n\n\n<p><code>@1.0.0<\/code> &#8211; is the corresponding version specified in it.<\/p>\n\n\n\n<p>Next, run the following command to install the dependencies needed to set up the <strong>tRPC<\/strong> client:<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn add @trpc\/client@next @trpc\/server@next @trpc\/react-query@next @tanstack\/react-query @tanstack\/react-query-devtools\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><code><a href=\"https:\/\/react-query.tanstack.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">@tanstack\/react-query<\/a><\/code> &#8211; Library for managing server state in React applications.<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/@trpc\/react\" target=\"_blank\" rel=\"noreferrer noopener\">@trpc\/react-query<\/a><\/code> &#8211; A wrapper around React Query<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/@trpc\/client\" target=\"_blank\" rel=\"noreferrer noopener\">@trpc\/client<\/a><\/code> &#8211; has tools for creating the <strong>tRPC<\/strong> client<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/@trpc\/server\" target=\"_blank\" rel=\"noreferrer noopener\">@trpc\/server<\/a><\/code> &#8211; This is a peer dependency of\u00a0<code>@trpc\/client<\/code>\u00a0so you have to install it again!<\/li><li><code><a href=\"https:\/\/www.npmjs.com\/package\/react-query-devtools\" target=\"_blank\" rel=\"noreferrer noopener\">@tanstack\/react-query-devtools<\/a><\/code> &#8211; A tool for visualizing all the inner workings of React Query.<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Creating the tRPC Client<\/h3>\n\n\n\n<p>Now let&#8217;s use the <code>createTRPCReact()<\/code> function provided by <code>@trpc\/react-query<\/code> binding to generate the React Query hooks based on the queries, mutations, and subscriptions defined on the <strong>tRPC<\/strong> server.<\/p>\n\n\n\n<p><strong>packages\/client\/src\/utils\/trpc.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport { createTRPCReact } from \"@trpc\/react-query\";\nimport type { AppRouter } from \"server\";\n\nexport const trpc = createTRPCReact&lt;AppRouter&gt;();\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the tRPC API Endpoint<\/h3>\n\n\n\n<p>Now let&#8217;s configure the React.js client with <strong>tRPC<\/strong> and <strong>React Query<\/strong> before making our first <strong>tRPC<\/strong> request to our API server.<\/p>\n\n\n\n<p><strong>packages\/client\/src\/App.tsx<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-tsx\"><code>\nimport \".\/global.css\";\nimport { useState } from \"react\";\nimport { QueryClientProvider, QueryClient } from \"@tanstack\/react-query\";\nimport { ReactQueryDevtools } from \"@tanstack\/react-query-devtools\";\nimport { getFetch } from \"@trpc\/client\";\nimport { loggerLink } from \"@trpc\/client\/links\/loggerLink\";\nimport { httpBatchLink } from \"@trpc\/client\/links\/httpBatchLink\";\nimport { trpc } from \".\/utils\/trpc\";\n\nfunction AppContent() {\n  const hello = trpc.sayHello.useQuery();\n  return &lt;main className=\"p-2\"&gt;{JSON.stringify(hello.data, null, 2)}&lt;\/main&gt;;\n}\n\nfunction App() {\n  const [queryClient] = useState(\n    () =&gt;\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            staleTime: 5 * 1000,\n          },\n        },\n      })\n  );\n\n  const [trpcClient] = useState(() =&gt;\n    trpc.createClient({\n      links: [\n        loggerLink(),\n        httpBatchLink({\n          url: \"http:\/\/localhost:8000\/api\/trpc\",\n          fetch: async (input, init?) =&gt; {\n            const fetch = getFetch();\n            return fetch(input, {\n              ...init,\n              credentials: \"include\",\n            });\n          },\n        }),\n      ],\n    })\n  );\n  return (\n    &lt;trpc.Provider client={trpcClient} queryClient={queryClient}&gt;\n      &lt;QueryClientProvider client={queryClient}&gt;\n        &lt;AppContent \/&gt;\n        &lt;ReactQueryDevtools initialIsOpen={false} \/&gt;\n      &lt;\/QueryClientProvider&gt;\n    &lt;\/trpc.Provider&gt;\n  );\n}\n\nexport default App;\n<\/code><\/pre>\n\n\n\n<p>With the above configurations, we are now ready to start the tRPC client and server. Open your terminal and change the directory into the root Yarn workspace and  run <code>yarn start<\/code> to start both the <strong>tRPC<\/strong> client and server.<\/p>\n\n\n\n<p>Enter the <strong>tRPC<\/strong> client URL <code>http:\/\/127.0.0.1:3000\/<\/code> in the browser and you should see the message we stored in the Redis database.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"951\" height=\"753\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/testing-trpc-client-and-server-with-react-and-expressjs.webp\" alt=\"testing trpc client and server with react and expressjs\" class=\"wp-image-5346\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/testing-trpc-client-and-server-with-react-and-expressjs.webp 951w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/testing-trpc-client-and-server-with-react-and-expressjs-300x238.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/testing-trpc-client-and-server-with-react-and-expressjs-768x608.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/testing-trpc-client-and-server-with-react-and-expressjs-100x79.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/testing-trpc-client-and-server-with-react-and-expressjs-568x450.webp 568w\" sizes=\"auto, (max-width: 951px) 100vw, 951px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Adding tailwindCss to the React.js tRPC Client<\/h3>\n\n\n\n<p>In this section, follow the steps below to add tailwindCss to the React.js tRPC client.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Step 1: Install tailwindCss and its dependencies<\/h4>\n\n\n\n<p> Open the integrated terminal and change the directory to the <code>packages\/client<\/code> folder. Run this command to install the tailwindCss library and its peer dependencies via Yarn.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn add -D tailwindcss postcss autoprefixer\n<\/code><\/pre>\n\n\n\n<p>Next, run the init command to generate the <code>tailwind.config.js<\/code> and <code>postcss.config.js<\/code> configuration files.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nnpx tailwindcss init -p\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Step 2: Configure Template Paths<\/h4>\n\n\n\n<p>Next, open the&nbsp;<code>tailwind.config.js<\/code>&nbsp;file and add the path to the React template files. You can also include your custom colors and fonts.<\/p>\n\n\n\n<p><strong>packages\/client\/tailwind.config.js<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\n\/** @type {import('tailwindcss').Config} *\/\nmodule.exports = {\n  content: ['.\/src\/**\/*.{js,jsx,ts,tsx}'],\n  theme: {\n    extend: {\n      colors: {\n        'ct-dark-600': '#222',\n        'ct-dark-200': '#e5e7eb',\n        'ct-dark-100': '#f5f6f7',\n        'ct-blue-600': '#2363eb',\n        'ct-yellow-600': '#f9d13e',\n      },\n      container: {\n        center: true,\n        padding: '1rem',\n        screens: {\n          lg: '1125px',\n          xl: '1125px',\n          '2xl': '1125px',\n        },\n      },\n    },\n  },\n  plugins: [],\n};\n\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Step 3: Adding the tailwindCss directives<\/h4>\n\n\n\n<p>Now create a&nbsp;<code>packages\/client\/src\/global.css<\/code>&nbsp;file and add the TailwindCSS&nbsp;directives.<\/p>\n\n\n\n<p><strong>packages\/client\/src\/global.css<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-css\"><code>\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@300;400;500;600;700&amp;display=swap');\n\n@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  html {\n    font-family: 'Poppins', sans-serif;\n  }\n}\n\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Step 2: Importing the CSS file<\/h4>\n\n\n\n<p>We are now ready to start using the tailwindCss classes but before that let&#8217;s import the <code>packages\/client\/src\/global.css<\/code> file into the <code>App.tsx<\/code> file.<\/p>\n\n\n\n<p><strong>packages\/client\/src\/App.tsx<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport '.\/global.css';\n\/\/ [...] other imports\n<\/code><\/pre>\n\n\n\n<p>Next, replace the content of the <code>AppContent()<\/code> component in the <code>packages\/client\/src\/App.tsx<\/code> file with the following:<\/p>\n\n\n\n<p><strong>packages\/client\/src\/App.tsx<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-tsx\"><code>\nfunction AppContent() {\n  const hello = trpc.sayHello.useQuery();\n  return (\n    &lt;div className=\"container mx-auto bg-ct-dark-200 rounded-xl shadow border p-8 m-10\"&gt;\n      &lt;p className=\"text-3xl text-gray-700 font-bold mb-5\"&gt;Welcome!&lt;\/p&gt;\n      &lt;p className=\"text-ct-blue-600 text-lg\"&gt;{hello.data?.message}&lt;\/p&gt;\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<p>You should now see the following output in the browser:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"756\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/added-tailwindcss-to-the-tRPC-client.webp\" alt=\"added tailwindcss to the tRPC client\" class=\"wp-image-5352\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/added-tailwindcss-to-the-tRPC-client.webp 950w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/added-tailwindcss-to-the-tRPC-client-300x239.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/added-tailwindcss-to-the-tRPC-client-768x611.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/added-tailwindcss-to-the-tRPC-client-100x80.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/07\/added-tailwindcss-to-the-tRPC-client-565x450.webp 565w\" sizes=\"auto, (max-width: 950px) 100vw, 950px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>With this tRPC client and server example, you&#8217;ve learned how to set up tRPC with React.js, PostgreSQL, Prisma, Express, and Redis.<\/p>\n\n\n\n<p>You can find the source code of the tRPC client and server <a href=\"https:\/\/github.com\/wpcodevo\/trpc-react-node-prisma\/tree\/trpc-prisma-react-setup\" target=\"_blank\" rel=\"noreferrer noopener\">on my GitHub<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>t3-stack popularly known as tRPC is a lightweight library tailored specifically for building end-to-end typesafe APIs without the need for defined schemas or extra dependencies&#8230;<\/p>\n","protected":false},"author":1,"featured_media":5360,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[54,47],"tags":[42,56,55],"class_list":["post-5272","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react","category-nodejs","tag-nodejs-api","tag-react","tag-reactjs"],"acf":[],"_links":{"self":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/5272","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/comments?post=5272"}],"version-history":[{"count":0,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/5272\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/media\/5360"}],"wp:attachment":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/media?parent=5272"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/categories?post=5272"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/tags?post=5272"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}