Now to get the basics of Next.js and a simple custom integration, we will build an SSG blog by pulling data from a WordPress blog (thanks to WordPress built-in REST APIs).
The objectives are:
- the blog will be server side rendered at build time, so that the final output could be eventually published on any hosting (static or not)
- the post will be dynamically generated from the source
-
first of all, copy the
types/pages.ts
file from this repo since it contains a rough typing of the WordPress post entity, and it's quite annoying to write it from scratch. -
In Next.js we create React component as pages and the routing is handled using the file system folder structure.
So we will start from the already existing /pages/index.tsx
as it is the main page in a Next.js application. Let's "reset" the content of the page apply the Tailwind styles and prepare it for what's to come:
import Head from "next/head";
export default function Home() {
return (
<div className="container mx-auto py-5">
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="py-5">
<h1 className="font-bold text-3xl my-5">
Impariamo <a href="https://nextjs.org">Next.js!</a>
</h1>
<p className="my-2">
Contenuti <i>presi in prestito</i> da <code>{URL}</code>
</p>
<h3 className="font-bold text-2xl my-2">Articoli</h3>
<div className="grid md:grid-cols-3 gap-4 mb-5">
{// Content here}
</div>
</main>
</div>
);
}
- This is not a mandatory step, but in order to centralize the endpoint that we are going to use, we can store it in an internal "library"
// libs/url.ts
export const URL: string = "https://www.moholepeople.it/fuorimohole";
export const WP_REST: string = URL + "/wp-json/wp/v2";
- Now we need to get the WordPress posts data from the endpoint and inject it into the page to be rendered.
Next.js give us a utility function that is executed before the page component is mounted and pass the return value as props for the component.
So let's add a getStaticProps()
in the file, before the component code (and update some imports), and add the fetch
code within it
export async function getStaticProps() {
const src = await fetch(WP_REST + "/posts");
const resp = await src.json();
const posts: Post[] = await [...resp];
return {
props: {
posts,
},
};
}
this fetch could have been executed during the mounting lifecycle event of the component, but by running it in this function allows Next.js to execute it on server side instead of the client.
- Now we can update the page component to receive data from props, and add a type for them
type Props = {
posts: Post[];
};
export default function Home({ posts }: Props) {
and in the template part of the component add a basic .map()
to iterate throught the posts data and render them in the page
<div className="grid md:grid-cols-3 gap-4 mb-5">
{posts.map((post, i) => (
<Card key={i} link={"/post/" + post.id} title={post.title.rendered}>
<div
dangerouslySetInnerHTML={{
__html: sanitizeHtml(post.excerpt.rendered),
}}
></div>
</Card>
))}
</div>
a couple of things to note here:
- the
<Card />
component is a simple stateless component that use the DaisyUI Card classes and markup, you can copy it directly from the source of this repo - the content of the post is exposed as an HTML string by WordPress, so to inject it within a tag we need to use the dangerouslySetInnerHTML React utility and to avoid potentially dangerous code we are using the
sanitize-html
library before injecting to return a clean HTML string
now if you run the npm run dev
from the terminal you should see your Next.js website rendering the content imported from WordPress REST API!