Waline: three clients, nine server hosts, seven databases, and a typo in the env template
💬 A Simple, Safe Comment System
At a glance
- What is it?
- A comment system with a backend, published as a pnpm and turbo monorepo. The README is a marketing page, so the specifics live in the root package scripts, the OpenAPI file and the environment template, one of which misspells the PostgreSQL port variable.
- Who is it for?
- Pick Waline if you want comments with markdown support and a backend you host yourself, and you are willing to assemble the three pieces it names: a client, a server host and a storage engine. The matrix is broad enough that a Vercel plus PostgreSQL setup is a routine choice, and the mini clients let you test before you commit.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- walinejs/waline3,157 ★ · +41
| Repository | 2026-09-11 | 2026-11-14 |
|---|---|---|
| walinejs/waline | 3.1k | 3.2k |
41 Stars in the last 64 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Three layers, and you choose one of each
Waline is presented as three separable layers, and the README's table is the fastest way to see the choices.
On the client side there are three: `@waline/client`, MiniValine and sodesu. On the server side there are nine: Vercel, CloudBase, Railway, Render, Zeabur, Netlify, Alibaba Cloud ComputeNest, Docker, and plain self hosting. On the storage side there are seven engines: PostgreSQL, MySQL, SQLite, TiDB, MongoDB, CloudBase and GitHub.
The headline number attached to that matrix is a claim rather than a count anyone can check: at least 243 deployment choices, which comes from combining the layers with each other. The feature list around it is short: fast, full markdown syntax, lightweight, free to deploy, and safe, with safe given the boldest typography on the page.
The env template spells the port variable wrong
The repository ships a seven line environment template for the PostgreSQL path, and it is worth reading before you copy it:
POSTGRES_DATABASE=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_HOST=
PORSTGRES_PORT=
POSTGRES_PREFIX=
POSTGRES_SSL=Five of the seven names are the obvious ones. The port is not: the template writes `PORSTGRES_PORT`, with the S and the P transposed, while every neighbouring variable spells PostgreSQL correctly. A template is exactly the thing people paste into a hosting dashboard without reading, so a database that refuses to connect on a first deploy is a foreseeable outcome of shipping this file as it stands.
`POSTGRES_PREFIX` and `POSTGRES_SSL` are the two that are less obvious in purpose, and the template gives no defaults for any of them.
A pnpm and turbo monorepo with four package directories
The root `package.json` is `waline-root`, marked private, with workspaces covering `packages/*` and `docs` and turbo as its only real dependency. The scripts name the packages: `admin:build` and `admin:dev` point at `packages/admin`, `client:build` and `client:dev` at `packages/client`, `server:dev` at `packages/server`, and `api:build` at `packages/api`.
Everything generic goes through turbo, so `build`, `clean` and `dev` are single commands that fan out across the workspace, and `pnpm-lock.yaml` with `pnpm-workspace.yaml` place pnpm as the package manager. Dependency maintenance has its own pair of scripts: `packages:check-update` runs `npm-check-updates` through `pnpm dlx`, and `packages:update` runs it and then `pnpm -r up`.
Tests are `vitest`, with `@vitest/coverage-v8` in the dev dependencies and a `vitest.config.ts` at the root, so the suites run per package rather than from a single global harness.
One OpenAPI file feeds both the lint and the docs page
The server's interface is described once, in `packages/server/openapi.yaml`, and two scripts read that same file. `api:lint` runs `redocly lint packages/server/openapi.yaml`, and `api:docs` builds it into a page at `docs/src/.vuepress/dist/api/index.html` with `--disableGoogleFont`, after creating the output directory.
That arrangement has a practical consequence for anyone automating against Waline: the specification is a file in the repository rather than a description on a website, so you can diff it, lint it in a pull request and generate clients from it. It also means a stale spec is a real risk, since nothing in the build forces the YAML to match the running server.
The `@redocly/cli` version is pinned in devDependencies, and documentation builds are composed rather than separate: `docs:build` runs the docs workspace build and then `api:docs`.
Four linters, and husky runs them before a commit
Linting here is four tools in a fixed order. `lint` runs `oxlint --fix`, then `oxfmt`, then `stylelint packages/*/src/**/*.scss --fix`. Markdown has its own pass, `lint:md`, running `markdownlint-cli2` over every markdown file, configured by `.markdownlint-cli2.mjs` with an ignore file beside it and by a `markdownlint-disable` comment at the top of the English README itself.
`prepare` runs `husky install`, and `nano-staged` plus a commit message checker, `@mr-hope/verify-commit-message`, sit in devDependencies, so these commands are meant to run at commit time rather than from a CI dashboard.
There are two config files for the JavaScript side, `oxlint.config.ts` and `oxfmt.config.ts`, which is the shape you get when a project has moved from one linter to another and kept the old formatter's slot as a config. Editors get `.vscode/` and `.devcontainer/`, so a new contributor is expected to run this in a container.
server:vercel runs the example app on port 9090
The fastest local loop is one script: `server:vercel` runs `vercel dev ./example --listen 9090`, which starts the example application through the Vercel CLI rather than a plain Node server, so the request environment matches a real deployment.
The `example/` directory is a complete small project rather than a snippet: `index.cjs`, its own `package.json`, its own `.env.example` and `.gitignore`, a `vercel.json` for platform configuration, and a `robots.txt`. Having `robots.txt` there says the example is meant to be reachable, not just importable.
Note what is not in the scripts: there is no root `start` or `serve` command. Development goes through turbo for packages, through the Vercel CLI for the example, and the server package has its own `server:dev`.
Releases are tagged per package, minutes apart
The three newest releases are all `@waline/vercel` builds published on 2026-09-30 at 04:39:11, 04:39:14 and 04:39:16, versions 1.43.2 through 1.43.4. Three tags for one repository inside six seconds is what a publish step across a workspace looks like, and it means the version number on one package says nothing about the others. Pin the package you depend on, not the repository.
Two smaller things to notice. The README links its GPL-2.0 licence to `github.com/lizheming/Waline`, an older organisation path, so follow the `LICENSE` file in this repository rather than the link. And the feature checklist is honest about what is missing: every item is checked except deployment support for AWS, GCP and Azure, so those three remain the gap in an otherwise long list of notifications, moderation and login options.
The last commit in this snapshot is dated 2026-10-03, and the documentation lives at waline.js.org with a Chinese README kept separately as README_CN.md.
Editorial conclusion
Pick Waline if you want comments with markdown support and a backend you host yourself, and you are willing to assemble the three pieces it names: a client, a server host and a storage engine. The matrix is broad enough that a Vercel plus PostgreSQL setup is a routine choice, and the mini clients let you test before you commit. Decide early whether you need the moderation surface, because IP rate limiting, keyword restrictions, an IP disallow list and Akismet are separate switches you configure rather than defaults you inherit. Before you deploy, check the variable names in the environment template against your provider's settings, read the OpenAPI file if you plan to automate anything against the server, and note that AWS, GCP and Azure deployment support is still an unchecked item.
Frequently asked questions
Which storage backends can Waline use?
Seven are listed: PostgreSQL, MySQL, SQLite, TiDB, MongoDB, CloudBase and GitHub. A seven line .env.example in the repository root configures the PostgreSQL path with database, user, password, host, port, prefix and SSL.
Can I use something other than the Waline client?
Yes. Three clients are named in the deployment matrix: @waline/client, MiniValine and sodesu. Any of them pairs with the same server hosts and storage engines, since the layers are described separately.
How do I run the Waline example project locally?
The server:vercel script runs vercel dev ./example --listen 9090, which starts the example through the Vercel CLI. Package level work goes through turbo, the server package has server:dev, and the test runner is vitest.
Does Waline have spam filtering and moderation tools?
The checked feature list includes Akismet, login support, social account login, comment management, deleting comments, limiting comment frequency by IP, comment keyword restrictions, an IP disallow list and duplicate content checks.
Which cloud providers does Waline not support yet?
Deployment support for AWS, GCP and Azure is the one unchecked item in the feature list, alongside everything else being marked complete. The listed server options are Vercel, CloudBase, Railway, Render, Zeabur, Netlify, Alibaba Cloud ComputeNest, Docker and self hosting.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/walinejs-waline)Star history chart for your README
[](https://hysenlabs.com/projects/walinejs-waline)Was this useful?