Using Next.js with WordPress and tRPC: A Seamless Integration
In today's web ecosystem, combining the power of different tools and platforms can lead to an incredibly efficient and effective development workflow. In this post, we'll explore how to use Next.js, a popular React framework, in combination with WordPress (as a headless CMS) and tRPC, an end-to-end type-safe API layer. This trio offers a perfect blend of performance, scalability, and developer experience.
Why this combination?
- Next.js: Offers server-side rendering, static site generation, and a host of other features perfect for modern web apps.
- WordPress: A tried-and-true CMS that powers a significant portion of the web. As a headless CMS, it exposes its content via an API, making it perfect for JAMstack applications and Next.js.
- tRPC: Enables type-safe data fetching in Next.js apps, ensuring a seamless and error-free developer experience from the database to the frontend.
Getting Started
1. Setting up WordPress:
- WordPress Installation: Ensure you have a WordPress instance running. You can either use local setups like Local by Flywheel or a live server.
- REST API Access: By default, WordPress provides a REST API at
https://yourwordpresssite.com/wp-json/wp/v2/
. This endpoint will be our data source.
2. Setting Up Next.js with tRPC:
i. Initialize a Next.js Project:
npx create-next-app next-wordpress-trpc
cd next-wordpress-trpc
ii. Install tRPC and Related Dependencies:
npm install @trpc/client @trpc/server react-query
iii. Create a tRPC Router:
Here, we’ll define our data fetching logic.
// routers/wpRouter.ts
import { createRouter } from '@trpc/server';
import fetch from 'node-fetch';
const WORDPRESS_API_ENDPOINT = 'https://yourwordpresssite.com/wp-json/wp/v2/';
export const wpRouter = createRouter()
.query('posts', {
resolve: async () => {
const response = await fetch(`${WORDPRESS_API_ENDPOINT}posts`);
if (!response.ok) {
throw new Error('Failed to fetch posts');
}
return response.json();
},
});
iv. Integrate the tRPC Router with Next.js:
// pages/api/trpc/[trpc].ts
import { createServer } from '@trpc/server';
import { wpRouter } from '../../../routers/wpRouter';
export default createServer({
router: wpRouter,
createContext: () => ({}),
}).createNextApiHandler();
v. Client-side Configuration:
// _app.tsx
import { AppProps } from 'next/app';
import { createReactQueryHooks } from '@trpc/react';
import { wpRouter } from '../routers/wpRouter';
const tRPC = createReactQueryHooks({
router: wpRouter,
fetcher: async ({ input, endpoint, query }) => {
const res = await fetch(endpoint, {
method: 'POST',
body: JSON.stringify({
query,
input,
}),
});
if (!res.ok) {
throw new Error('Network response was not ok');
}
return res.json();
},
});
function MyApp({ Component, pageProps }: AppProps) {
return (
<tRPC.Provider {...pageProps}>
<Component {...pageProps} />
</tRPC.Provider>
);
}
export default MyApp;
vi. Fetch and Display Content:
// pages/index.tsx
import { tRPC } from '../path-to-your-_app-file';
function HomePage() {
const postsQuery = tRPC.useQuery({
query: 'posts',
});
if (postsQuery.isLoading) return <p>Loading...</p>;
if (postsQuery.isError) return <p>Error: {postsQuery.error.message}</p>;
return (
<div>
{postsQuery.data.map(post => (
<div key={post.id}>
<h2>{post.title.rendered}</h2>
<div dangerouslySetInnerHTML={{ __html: post.content.rendered }} />
</div>
))}
</div>
);
}
export default HomePage;
This integration offers the content management prowess of WordPress, the versatility of Next.js, and the type-safety of tRPC. With this setup, developers can rapidly build and deploy performant, scalable web apps with a smooth content update process for content creators.