How to add a blog to Next.js using Hyvor Blogs?
Tags: nextjs, blog, react
Published: 2023-07-27 07:22:43

This is a tutorial on how to add a blog to your [Next.js](https://nextjs.org/) application using [Hyvor Blogs](https://blogs.hyvor.com/), an all-in-one blogging platform. We'll be adding a fully-functional blog with a custom theme to your Next.js app's `/blog` (you can customize this) using [Next.js Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/router-handlers).

> This tutorial focuses on adding a "complete" blog to your app. However, if you like to create your own blog and use Hyvor Blogs only as a headless CMS, see our [Data API](https://blogs.hyvor.com/docs/api-data). (We will write a guide on this in the future)

How it works
------------

We will use Hyvor Blogs for everything, except serving the blog. By default, your blog is hosted on a subdomain or hyvorblogs.io. You can easily set up a custom domain like blog.mycompany.com as well. Here, we are going to host it on mycompany.com/blog, using Next.js Route Handlers, which will dynamically process all `/blog/*` routes.

When we receive a request to `/blog/*`, we'll call Hyvor Blogs [Delivery API](https://blogs.hyvor.com/docs/api-delivery) to "learn" how to send a response back. Then, we will save that response in a cache so that subsequent requests can be served from the cache. Finally, we will use webhooks to clear the cache.

It might sound complicated, but we have abstracted most of the tasks into a library. You only have to write a couple of lines of code.

Step 1: Set up Hyvor Blogs
--------------------------

### Create a blog & get the subdomain

First, create a blog from the [Hyvor Blogs Console](https://blogs.hyvor.com/console/new). You will be asked to create a HYVOR account. Then, choose a subdomain. You will need this in the next steps.

![Create a blog in Hyvor Blogs](https://hyvor.com/blog/media/STa4xTVJFkUDmO1XlDAPHvjfirxI9JtaN8BhRcCa.png)

### Change hosting URL

Next, go to Settings -> Hosting, and change "Hosting At" to Self-hosting, and the URL to your self-serving URL. In this case, I am using `{next-app-url}/blog`

![Change Hosting](https://hyvor.com/blog/media/tw7mZ9BeklSstq0gYoW7a4woi8MvXJNfzhkhoY9h.png)

> Important: To test webhooks, this URL should be publicly accessible. Therefore, if you are testing locally, use a tool like [ngrok](https://ngrok.com/) to expose your next app on the internet.

### Create a Delivery API Key

Then, go to Settings -> API Keys and create a Delivery API key. You will need this in the next step.

![Create a Delivery API key](https://hyvor.com/blog/media/WAMgKOEvrIOQDyp1R0A66mqYcAPwcZDGCx6hKli7.png)

Create a Delivery API key

### Set up webhook URL

Finally, go to Settings -> Webhooks and create a new entry.

-   URL: `your-app-url/blog/_hb_webhook`
-   Events
    -   `cache.single`
    -   `cache.templates`
    -   `cache.all`

![Create a webhook](https://hyvor.com/blog/media/12Q1frFdFlkQhOTx2ZApr5BBDM8miPOkUhe0fpYN.png)

We'll need the Webhook Secret in the next step.

![Copy webhook secret](https://hyvor.com/blog/media/RgchfFocCctleFxKobjIHve7QOP5vBuuRbLZIRPy.png)

Step 2: Set up Next.js
----------------------

### Install the helper library

We'll be using helper methods from the [@hyvor/hyvor-blogs-serve-web](https://github.com/hyvor/hyvor-blogs-serve-web) library in the next steps. Install that package using your package manager.

```bash
npm install @hyvor/hyvor-blogs-serve-web
```

### Set up App Routes

As mentioned earlier, we'll be using [Next.js Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/router-handlers), which comes with the app router.

You will need a directory structure like this:

![NextJS directory structure](https://hyvor.com/blog/media/cDAR34K0QsBdML8SjLIk16OOHjnzKhTJyyJPhRSO.png)

```
blog
    [[..paths]]
        route.ts
```

> Note: `[[..paths]]` optionally matches any nested path.

Here's the full code of `route.ts`

```ts
import { Blog } from '@hyvor/hyvor-blogs-serve-web';
export function getBlog() {
    return new Blog({
        subdomain: 'my-next-js-app',
        deliveryApiKey: 'my-delivery-api-key',
        webhookSecret: 'my-webhook-secret',
    });
}
export async function GET(_: Request, {params}: {params: {paths: string[]|undefined}}) {
    const path = '/' + (params.paths?.join('/') || '');
    return await getBlog().handleBlogRequest(path);
}
export async function POST(request: Request, {params} : {params: {paths: string[]|undefined}}) {
    if (params.paths?.[0] !== '_hb_webhook') {
        return new Response('Not Found', {status: 404});
    }
    const data = await request.json();
    const signature = request.headers.get('X-Signature') || '';
    return await getBlog().handleWebhookRequest(data, signature);
}
```

Replace `subdomain`, `deliveryApiKey`, and `webhookSecret` values from the previous in the `getBlog()` function.

- `GET` handles HTTP GET requests to any `/blog/*` route
- `POST` handles only `/_hb_webhook` path

### Set up cache

@hyvor/hyvor-blogs-serve-web library uses [Keyv](https://keyvhq.js.org/#/) as the cache layer. By default, the cache is saved in memory. It is highly recommended to set up a custom cache (ex: Redis, Vercel KV, etc.)

Here is an example using Redis:

```ts
return new Blog({
    // ...other config
    cache: {
        store: new KeyvRedis('redis://user:pass@localhost:6379')
    }
})
```

See [Keyv documentation](https://keyvhq.js.org/#/?id=all-the-adapters) for other available adapters.

That's all! Try visiting `/blog` path of your blog. Then, try updating one of your posts to verify that the cache is cleared using Webhooks.

Finally
-------

If you have any issues, feel free to comment below.

Resources:

-   [Helper library on Github](https://github.com/hyvor/hyvor-blogs-serve-web)
-   [Delivery API docs](https://blogs.hyvor.com/docs/api-delivery)
-   [Hyvor Blogs](https://blogs.hyvor.com/)