DEV Community

Cover image for PM2 has no web UI. Every open source alternative is dead. So I built one.
Orchid Files
Orchid Files

Posted on

PM2 has no web UI. Every open source alternative is dead. So I built one.

Why I started this project

PM2 is the most popular process manager for Node.js, with 2 million downloads per week, but it's provided as a CLI tool. If you want to view processes in a browser, manage them, and receive notifications via Slack or email, you need to use PM2 Plus. This is a paid, subscription-based cloud service.

All open-source alternatives are built using JS+HTML. They lack modules, type safety, tests, and an architecture designed for extensibility. They are difficult to maintain and develop. You can't simply fork them and add new features without rewriting most of the code. And since they lack tests, you can break anything with your changes.

Almost all open-source solutions have been abandoned. The most popular ones, based on star count, haven't been updated in 2 to 10 years. Some have issues that have been open for years, and pull requests aren't accepted. The authors have abandoned these projects. Yet new repositories pop up every few months, but they're still just plain JS with a single routes file and a few pages on the frontend. Without any well-thought-out architecture.

I've been using pm2 for about 10 years now, and I've wanted to create a pm2 dashboard for a long time. AI agents make this kind of project much faster to build. That doesn't mean this is just some vibe-coding project where I simply asked the AI to create a dashboard and dumped the code into Git. I make 100% of the architectural decisions, review 100% of the code, and I write each new task for it in a new chat. The AI agent doesn't make decisions; it only handles the routine tasks: writing code, tests, and markup.

Fun fact. When I started brainstorming a name for the npm package, I went through dozens of options and settled on pm2-dashboard. It had been taken by an inactive package for 11 years and became available 11 days before I started choosing a project name. I managed to grab it and publish a placeholder. It seems like a huge coincidence that the best possible name for the project became available at just the right moment.


How the project is structured

I decided to build a project that would be very easy to extend and maintain — with full TypeScript coverage, test coverage, linters, and a modular architecture. For the structure, I chose a monorepo approach: apps, packages, scripts, and docs. As usual, packages/shared contains shared modules, constants, types, and helpers.

For the frontend, I chose between Vue, React, and Svelte. I'm familiar with all of them, but I chose Svelte because I prefer its style over React's, and I haven't worked with Vue in a long time. Fewer developers are familiar with it, which might complicate maintenance, but if you work with AI agents and know Tailwind, there won't be any issues.

On the backend, I immediately chose NestJS for its dependency injection and modular architecture; it's better for scalability than Express or Fastify. I also considered AdonisJS, but it's less popular. It might take longer to set up initially, but I simply asked an AI agent to port the existing NestJS code from my other projects. But it pays off in both maintenance and extensibility.

For the database, I chose between PostgreSQL and SQLite. I chose SQLite because so the package can be installed with a single command from npm, and there's no need to spin up a Docker container for the database — the entire database is in a single file. For the ORM, I chose between TypeORM and Drizzle. I chose Drizzle because I hadn't worked with it yet and wanted to gain some experience, and it seems like most new projects are choosing it now.

Between JWT and cookie-based sessions, I chose the latter because JWT offers no advantages for a self-hosted tool with a few users, but it complicates logout and token deletion. Surprisingly, I couldn't find a library that works with express-session and better-sqlite3 and writes sessions to the same database file. connect-sqlite3 writes sessions to a separate file, and better-sqlite3-session-store has a license incompatible with MIT. I built my own session solution in 30 lines of code.

On first launch, a setup wizard appears, prompting you to create a user; after that, access to the interface is available only via username and password. No .env or other configuration files.

It took 5 days from the project idea to a working version and writing this post. Without AI agents, it would have taken much longer. And without AI agents, I probably wouldn't have even started this project.


What's already working

  • List of processes with CPU, RAM, and status
  • Start, stop, and restart for each process, as well as bulk operations
  • Uptime and restart counters
  • Authentication
  • Setup wizard on first launch
  • A single npm package with API and web interface

Next priorities

  • Real-time updates via WebSocket
  • Log viewer
  • Metrics history with graphs
  • Alerts

How to try it

npx pm2-dashboard
Enter fullscreen mode Exit fullscreen mode

It will open at http://localhost:3000. On first run, the CLI prints a setup link.

GitHub: https://github.com/orchidfiles/pm2-dashboard


If you use PM2, I'd love to hear your feedback.
Leave a comment or open an issue on GitHub.

Top comments (1)

Collapse
 
klement_gunndu profile image
klement Gunndu

Been using PM2 for years and the lack of a proper web dashboard is a real pain point. The fact that you're making 100% of the architecture decisions yourself while using AI for code gen is the right call -- that's how these projects should work.