6 min read

Moving Blog Comments From Disqus to Waline: Free Setup With Vercel + Neon, and What Went Wrong

I replaced Disqus with Waline on my blog, hosted for free on Vercel and Neon. Here is why I switched, how I set it up, and where I got stuck on Netlify.

While rebuilding my blog, I also replaced Disqus, which I had used for years, with Waline.

It was bumpier than I expected, including a long detour on Netlify. This post covers why I chose Waline, the setup steps, and the traps I fell into.

Why I left Disqus

  • Ads: the free plan puts ads in the comment section, and there are more of them every year.
  • Slow: it loads a lot of extra tracking scripts.
  • Can't be restyled: my new blog has a notebook look, and Disqus sticks out.
  • The comments aren't mine: they all live on Disqus's platform.

Options I considered

OptionDo readers need to log in?Downsides
Disqus with guest commentsNoAds, slow, doesn't match the site
GiscusYes, a GitHub accountMost of my readers don't have one
Google Form + a sheetNoNo threads, no notifications, spam is on you
WalineNo, just a nicknameYou host the backend yourself

Many of my readers arrive from searches about visas and working holidays, so the lower the barrier to commenting, the better. That ruled out anything that needs a GitHub account.

I went with Waline because:

  • A nickname is all you need to comment
  • No ads
  • Comments are stored in my own database and can be exported any time
  • Replies, email notifications, spam filtering and a moderation panel are built in
  • The look can be changed with CSS to match the site

How Waline is put together

Waline has three parts:

  1. Client: the comment box under each post (@waline/client)
  2. Server: the program that handles comments, deployed on Vercel
  3. Database: where comments are stored — I use Neon (free PostgreSQL)

Waline itself is free and open source, and the free plans of Vercel and Neon are enough for a personal blog's comments.

Setup

1. Create the database on Neon

Create a project on Neon. Postgres is the only service you need.

Then open the SQL Editor, paste Waline's official PostgreSQL schema (waline.pgsql) and run it. You end up with three tables: wl_comment, wl_counter and wl_users.

2. Deploy the server to Vercel

Use the Deploy button in Waline's official docs. It creates a new repo and a Vercel project for you.

3. Add environment variables

In the Vercel project, go to Settings → Environment Variables and add the database connection details:

PG_HOST=your host
PG_DB=database name
PG_USER=user
PG_PASSWORD=password
PG_PORT=5432
PG_SSL=true

The values come from splitting Neon's connection string:

postgresql://user:password@host/database?sslmode=require

Afterwards, go to Deployments and hit Redeploy — the variables only take effect after a redeploy.

4. Register the admin account

Open your-server-url/ui/register and sign up. The first person to register becomes the admin, so do it right after deploying. From then on you moderate and delete comments at /ui.

5. Connect it to the blog

Install the client:

npm install @waline/client

Put a container on the post page and only load Waline when it is about to scroll into view, so it doesn't slow down the post itself:

import('@waline/client').then(({ init }) => {
  init({
    el: container,
    serverURL: 'https://your-server.vercel.app',
    path: '/en/blog/nz/buy-car', // each post's URL path is its thread key
    lang: 'en',
    meta: ['nick', 'mail'],
    requiredMeta: ['nick'], // only the nickname is required
  })
})

The styling is done through Waline's CSS variables: swap the borders and button colour for the site's ink lines and red, and it fits right into the notebook look.

I also kept a fallback: if the Waline server URL isn't configured, the post page shows the old Disqus embed, so comments never break during the switch.

What went wrong

Trap 1: on Netlify, everything was Not Found

My blog is hosted on Netlify, so at first I wanted the Waline server there as well and followed the official Netlify guide.

The deploy succeeded, but opening the server URL showed a single line: Not Found. Same for the admin page.

It took a long time to find the cause. Netlify bundles the server into a single file, but Waline reads its own source files at runtime — after bundling those files are gone, so it doesn't recognise any URL. Telling Netlify not to bundle it and ship everything as-is fixed the routing, but the package was close to 400MB, over Netlify's 250MB function limit, so it still couldn't deploy.

In the end I switched to Vercel and it worked first time. Waline's server package is literally called @waline/vercel — that is the platform it mainly supports.

Takeaway: put the Waline server on Vercel and don't waste time on Netlify. Hosting the blog itself on Netlify is fine; just keep the two separate.

Trap 2: PG_PORT is not optional

Neon's connection string doesn't include a port, because 5432 is PostgreSQL's default. But Waline's default port is not 5432, so you have to add PG_PORT=5432 yourself.

Trap 3: a stray line break in an environment variable

The server was running but comments wouldn't save. The error was:

database "
neondb" does not exist

Look closely and there is a line break before neondb. I had picked it up while pasting the variable, so the database name became "line break + neondb" — which of course doesn't exist. Clearing the value and typing it by hand fixed it.

Trap 4: you don't need Neon's setup commands

After creating a project, Neon shows a list of commands for "setting up Neon in your project". Those are for people who connect to the database from their own code. The blog never talks to the database — the Waline server does — so you can skip them.

Settings worth adding

  • SECURE_DOMAINS: set it to your own domain so other sites can't use your server.
  • COMMENT_AUDIT=true: turn this on if you want to approve comments before they appear.

Was it worth it

The comment section finally looks like the rest of the site, and nobody has to log in to leave a comment.

The only cost is that the server is mine to look after: every so often I need to update it on Vercel. Compared with seeing ads every time I open a post, I think that's a good trade.

If you're thinking of leaving Disqus too, I hope this saves you a few wrong turns. Feel free to try out the new comment box below!

Related Posts

Comments