Published on

Configure Waline on a Next.js site deployed on Vercel

Authors

💬 Introduction

If you want to allow your readers to leave comments on your Next.js blog, without relying on an external service like Disqus, Waline is an excellent solution.

Waline is:

  • 🧩 Self-hosted — you retain control of the data
  • Fast — based on a serverless backend (ideal for Vercel)
  • 🌍 Internationalizable
  • 🧠 Markdown, avatars, and wq2 reactions compatible

In this article, we will configure Waline step by step on a Next.js site deployed on Vercel.


LeanCloud

🧩 LeanCloud Configuration (Database)

  1. Log in or sign up to the LeanCloud Console.
  2. Click Create app to create a new application. Give it a name and select the Developer plan.
conf-waline1
  1. Once in your app, go to Settings → App Keys (bottom left). Note the following values:
  • APP ID
  • APP Key
  • Master Key
  • Server Url
conf-waline2 You will need this for server configuration.

Vercel

Deploy to Vercel (Server)

  1. Click the Deploy button above to deploy the Waline template to Vercel.

Deploy

You will need to log in to GitHub to create the repository.

  1. Give your project a name, then click Create and launch the deployment. Vercel will create a new repository based on the Waline template. conf-waline3 conf-waline4 conf-waline5
  2. Once the deployment is complete, access the dashboard.

conf-waline6
  1. Add the environment variables in the Settings → Environment Variables tab:
  • LEAN_ID → value of APP ID
  • LEAN_KEY → value of APP Key`
  • LEAN_MASTER_KEY → value of Master Key
  • LEAN_SERVER → value of REST API Server Url
conf-waline7

👉 You can check the other available variables here.

  1. Next, redeploy your waline server via Deployments → Redeploy.
conf-waline8
  1. When the status changes to Ready, click Visit to open your Waline server.

Retrieving the serverURL for the client

In Settings → Domains, retrieve your domain that represents the serverURL.

conf-waline9

Comment Management (Administration)

Once the deployment is complete, please visit <serverURL>/ui/register to register.

The first person to register will be set as the administrator. After logging in as an administrator, you will have access to the comment management interface. There you can edit, flag, or delete comments. Users can also create an account via the comment box, and they will be redirected to their profile page after logging in.

The waline admin panel is accessible via <serverURL>/ui conf-waline10

🧱 In your project Client-side: Integrate Waline into Next.js

Install the Waline client:

npm install @waline/client

Then create a React component WalineComments.tsx:

'use client'

import { useCallback, useEffect, useState } from 'react'
import { init } from '@waline/client'
import { useParams } from 'next/navigation'
import { useTranslation } from '@/app/i18n/client'
import siteMetadata from '@/data/siteMetadata'
import type { LocaleTypes } from '@/app/i18n/settings'
import type { ReactElement } from 'react'
import '@waline/client/style.css'

export default function WalineComments(): ReactElement {
  const locale = useParams()?.locale as LocaleTypes
  const { t } = useTranslation(locale, 'home')
  const [loadComments, setLoadComments] = useState<boolean>(false)

  const handleLoadComments = useCallback(() => {
    setLoadComments(true)
  }, [])

  useEffect(() => {
    if (loadComments) {
      init({
        el: '#waline',
        lang: locale,
        reaction: true,
        emoji: [
          'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/weibo',
          'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/alus',
        ],
        requiredMeta: ['nick'],
        serverURL: siteMetadata.walineServer,
      })
    }
  }, [loadComments, locale])

  return (
    <>
      {!loadComments && (
        <button
          className="bg-primary-500 mb-6 rounded p-2 text-white hover:opacity-80 dark:hover:opacity-80"
          onClick={handleLoadComments}
        >
          {t('comment')}
        </button>
      )}
      {loadComments ? <div className="mt-6 mb-6" id="waline" /> : null}
    </>
  )
}

📁 Configure siteMetadata.js

Add your Waline server URL:

// data/siteMetadata.js
const siteMetadata = {
...
walineServer: '<serverURL>', //
}
export default siteMetadata

🌐 Display comments in your posts

In your post template:

import WalineComments from '@/components/WalineComments'

export default function BlogPost({ post }) {
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
<WalineComments />
</article>
)
}

✅ Result

You now have :

💬 A functional and multilingual comment system

☁️ A free LeanCloud database

🚀 A server hosted on Vercel

🔐 Secure configuration via environment variables