nezha-dash: A Next.js Dashboard for Nezha Server Monitoring
A simple dashboard for nezha.
At a glance
- What is it?
- nezha-dash is a dashboard built on Next.js that reads a Nezha monitoring panel over its API and renders the server list, and it can also read Komari and MyNodeQuery panels. It deploys to Vercel, Cloudflare or Docker, is configured entirely through environment variables, and is Apache-2.0 licensed.
- Who is it for?
- nezha-dash fits an operator who wants to present a Nezha monitoring panel to other people, in their own branding, on their own domain, and who wants the same dashboard to work whether the underlying panel is Nezha, Komari or MyNodeQuery.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 16 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Display Layer in Front of a Monitoring Panel
nezha-dash is a dashboard based on Next.js and the Nezha monitoring panel, and it is described simply as a simple dashboard for nezha.
That description is worth expanding into what the tool is and is not. Nezha is the monitoring agent and panel, and nezha-dash is a front end for reading that panel's API and presenting the result. It does not collect metrics and it does not replace the panel, it renders it.
The environment variable file shows the shape of the connection. Two variables are the essentials, NezhaBaseUrl pointing at the panel address and NezhaAuth holding the API token, and the example values are a base URL on port 8008 and a token placeholder. The base URL in the example is a plain http address on a port, which tells you the dashboard expects to be able to reach the panel directly rather than through a proxy, and that the https termination is expected to happen in front of the dashboard.
The rest of the configuration is presentation. There are flags for showing the country flag, the tag, the network transfer figures, the IP information, the server detail summary and the tag count, plus a setting to fix the top server name to the first one, a setting to force SVG flags rather than image flags, and switches to disable the index page and the cartoon. Custom logo, title and description are configurable, and the links block lets you put your own entries in the interface, with the example carrying a GitHub link and a donation link.
Polling Interval, Locale and the Public Flag Prefix
Two of the environment variables are about behaviour rather than appearance, and both are worth understanding before deploying.
NEXT_PUBLIC_NezhaFetchInterval is 5000 in the example, so the dashboard polls the panel every five seconds. Since it is a NEXT_PUBLIC variable it is exposed to the browser, which is what makes the polling happen client side rather than through a server proxy. That has a consequence: the browser has to be able to reach the panel API, so if the panel sits on a private network the dashboard will not work without an arrangement for that.
DefaultLocale is zh in the example, and the repository carries a full internationalisation setup with an i18n/ directory, a messages/ directory and an i18n-metadata.ts file, so the dashboard is localised rather than Chinese only. The locale is a server-side variable, unlike the NEXT_PUBLIC ones.
The public prefix has a second job beyond being readable in the browser. The Komari and MyNodeQuery modes are switched with NEXT_PUBLIC_Komari and NEXT_PUBLIC_MyNodeQuery, which means the data source is chosen by a public variable, and the base URL for each of those is a separate server-side variable. That split is a little unusual, and it is worth checking against the environment variable documentation for the deployment platform you are using, because the ordering of the two kinds of variable determines which one wins.
Komari Compatibility, Labelled Experimental
The first of the two alternative data sources is Komari, and the README is careful about it, marking the section with a caution that the feature is experimental and may be removed in the future.
To enable it you set NEXT_PUBLIC_Komari to true and point KomariBaseUrl at the panel. The dashboard then reads from two endpoints: KomariBaseUrl/api/nodes for the server list, and KomariBaseUrl/api/recent/{uuid} for the real-time monitoring data of each server.
The behaviour on failure is specified, which is the detail that matters for a dashboard. The system fetches the real-time data for all servers concurrently, which gives an accurate current state view, and if the real-time fetch for a particular server fails, it falls back to showing the basic information for that server. So one server that stops responding to the live endpoint does not blank the whole page, it just stops being live for that row.
The concurrency is worth noting too. Fetching the recent endpoint per server means a dashboard with twenty servers makes twenty requests per polling interval, and the interval is five seconds by default, so the load on the panel is proportional to the number of servers times the polling rate.
MyNodeQuery Mode and the Charts It Hides
The second alternative source is MyNodeQuery, and its integration is different in shape from the Komari one.
You enable it with NEXT_PUBLIC_MyNodeQuery set to true and set MyNodeQueryBaseUrl to the panel. The dashboard then calls the panel's own POST endpoints: MyNodeQueryBaseUrl/Dashboard/GetNodes to get the server list, and MyNodeQueryBaseUrl/Detail/GetDetail for the details of a specific server, with a request body of the form {"UniqueID":"<node UniqueID>"}.
The detail endpoint is a POST with a body rather than a GET with a path parameter, which is a consequence of the upstream API shape, and it means the dashboard has to construct a body for every server it wants detail on.
There is one visible consequence for the interface. The README notes that in MyNodeQuery mode the dashboard's network charts are hidden automatically. So the mode is not a complete substitute for the others: you get the server list and the details, but not the traffic history graph, and the dashboard hides the panel rather than showing an empty one.
Together with the Komari mode, this gives the dashboard three possible data sources, and the two compatibility modes are what make it useful for people who moved away from Nezha but still want this particular interface.
Three Deployment Targets and the Container Image
The supported deployment environments are Vercel, Cloudflare and Docker, and the same codebase serves all three because it is a standard Next.js application.
The Dockerfile shows how the container is built. It starts from node:24-alpine, installs pnpm at the pinned version globally, and works through three stages: dependencies installed with a frozen lockfile, the application built with the release tag and commit hash passed in as build arguments, and a runner stage that copies the public directory and the Next.js standalone output into a node:24-alpine image that exposes port 3000 and starts node server.js.
FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]The standalone output is what makes the image small, since Next.js traces the server bundle and only the files actually needed are copied. The build script in package.json has to copy the static assets into the standalone directory manually for that reason, since the trace does not include them.
The build information is embedded at build time through the RELEASE_TAG and COMMIT_SHA arguments, which is how a deployment can show which version it is running. The repository also has a release policy test and a publish release test in the scripts/ directory, run through the test:release script, so the release process itself is covered by tests.
The V0 and V1 Split You Need to Know About
The README opens with a caution that is easy to miss and expensive to ignore. This is the V0 compatibility version, and its functionality may differ from the built-in V1 version. Issues for V0 and V1 should be raised in the current repository, while pull requests for V1 should go to a different repository, hamster1963/nezha-dash-v1, which the README links.
So there are two lines of development. This repository is the V0 line, which is the one that works with a standalone Nezha panel and with the Komari and MyNodeQuery compatibility modes. The V1 line is the built-in version, with its own repository, and the work is split along those lines deliberately.
For anyone about to deploy, the practical sequence is to decide which line you want. This repository is the V0 compatibility line, so a deployment that depends on the Komari or MyNodeQuery modes is a V0 deployment, and the upgrade path to V1 is not a version bump but a migration between two codebases.
The versioning in this repository is at 3.1.13, with tags v3.1.13 on 2026-10-07, v3.1.12 on 2026-06-08 and v3.1.11 on 2026-04-02, and the repository is not archived with the last push on 2026-10-07, so the V0 line is still being worked on.
The Stack Behind the Dashboard
The package.json describes a Next.js 16 application on pnpm 11.28.4, and the dependency list is where most of the feature set is visible.
For the interface, the Radix UI primitives cover the dialog, dropdown menu, label, navigation menu, popover, progress, radio group, separator, slot and switch, with cmdk for the command palette, lucide-react for icons, heroicons and class-variance-authority alongside clsx and tailwind-merge for the styling layer. Tailwind is the styling approach, with a postcss config and a components.json for the component registry.
For data, d3-geo and d3-selection handle the map and the selection behaviour, luxon handles dates and times, maxmind is there for IP information, and country-flag-icons with flag-icons and font-logos supply the country and provider icons. The i18n stack is next-intl with i18n-iso-countries for the country names.
Two dependencies point at features the README does not describe. next-auth at 5.0.0-beta is the authentication layer, and there is an auth.ts at the repository root, so the dashboard can have a login in front of it. And next-pwa makes it installable as a progressive web app, which for a monitoring dashboard is a sensible choice for a phone on a home screen.
The dev server runs on port 3040 with the webpack flag, the linter and formatter are Biome rather than ESLint and Prettier, and the repository also carries a changelogithub configuration, which suggests the changelog is generated from commit messages.
Editorial conclusion
nezha-dash fits an operator who wants to present a Nezha monitoring panel to other people, in their own branding, on their own domain, and who wants the same dashboard to work whether the underlying panel is Nezha, Komari or MyNodeQuery. It is a poor fit if you need the monitoring agent itself, since this is only the display layer, and a poor fit if you need a guarantee that the Komari compatibility will stay, because the README labels it experimental and says it may be removed. Before deploying, read the environment variable reference, and note that the V0 branch you are reading is the compatibility line while V1 work happens in a separate repository, so pull requests for V1 belong there. The project is Apache-2.0 licensed, the current version is 3.1.13, and the last push was on 2026-10-07.
Frequently asked questions
How do I configure nezha-dash to read a Nezha panel?
Set NezhaBaseUrl to the address of the Nezha panel and NezhaAuth to the API token, then set the presentation options you want. The .env.example file in the repository shows a base URL on port 8008 with a token placeholder as the starting point.
Can nezha-dash read a Komari panel?
Yes, in an experimental mode that the README says may be removed. Set NEXT_PUBLIC_Komari to true and KomariBaseUrl to the panel, and the dashboard reads KomariBaseUrl/api/nodes for the list and KomariBaseUrl/api/recent/{uuid} for live data, falling back to basic information if a live fetch fails.
What is different in MyNodeQuery mode?
The dashboard calls POST endpoints on that panel, MyNodeQueryBaseUrl/Dashboard/GetNodes for the list and MyNodeQueryBaseUrl/Detail/GetDetail for the details of a server, with a body of the form {"UniqueID":"<node UniqueID>"}. The network charts are hidden automatically in this mode.
How do I deploy nezha-dash?
The supported environments are Vercel, Cloudflare and Docker. The Dockerfile builds on node:24-alpine and runs the Next.js standalone output on port 3000 with node server.js, and the release tag and commit hash are passed in as build arguments during the build.
What is the difference between the V0 and V1 versions?
The README states that this repository is the V0 compatibility version and that functionality may differ from the built-in V1 version. Issues for both versions go here, but pull requests for V1 should go to the separate hamster1963/nezha-dash-v1 repository.
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/hamster1963-nezha-dash)Was this useful?