Nadir Web UI
SvelteKit dashboard for nadir-agent - a central web console that talks to one or many Nadir backend nodes over their typed REST API.
The agent does the system-administration work (systemd services, users, packages, networking, audit, terminal, ...). This UI is the operator's view of it: sign in, register machines with their bearer token, see live host metrics on the dashboard, and drive everyday tasks from the browser.
Stack
- SvelteKit (Svelte 5, adapter-node) + TailwindCSS 4 + shadcn-svelte
- Bun as the runtime / package manager / dev server
- Drizzle ORM on SQLite (libSQL driver) for the UI's own state (users, machines, encrypted tokens)
- Better Auth with email/password, OAuth, optional 2FA, admin & username plugins
- Paraglide for i18n (messages in
messages/) - openapi-fetch + typed client generated from the nadir-agent OpenAPI spec
(
src/lib/server/nadir-agent/schema.d.ts)
Getting started
Prerequisites: Bun and a reachable nadir-agent instance with a machine token (see the agent README's Connecting a dashboard section).
bun install
cp .env.example .env # then edit (see below)
bun run db:push # creates db.sqlite from the Drizzle schema
bun run dev # starts on http://localhost:5173
Environment
Set in .env (validated at startup via src/lib/const/schema.ts):
| Var | Default | Purpose |
|---|---|---|
CRYPTO_SECRET |
(required) | Encrypts machine bearer tokens at rest in the local DB |
DATABASE_URL |
file:db.sqlite |
libSQL connection string |
ORIGIN |
http://localhost:5173 |
Public origin (used by Better Auth) |
DISABLE_SIGNUP |
false |
Lock down registration |
ENABLE_2FA |
false |
Enable the TOTP 2FA flow |
ENABLE_EMAIL_AND_PASSWORD |
true |
Toggle email/password auth |
SMTP_* |
- | Outbound mail for verification / reset / 2FA |
OAuth providers (optional) live in config/oauth.json and are passed straight
to Better Auth's genericOAuth plugin.
Scripts
bun run dev # vite dev server
bun run type:generate # generate typed client for nadir-agent
bun run build # production build (adapter-node -> build/)
bun run preview # preview the production build
bun run check # svelte-check
bun run lint # prettier + eslint
bun run format # prettier --write
bun run db:push # apply schema to the DB
bun run db:generate # generate migration from schema changes
bun run db:migrate # run pending migrations
bun run db:studio # drizzle-kit studio
Project layout
src/
routes/
auth/ sign-in, sign-up, forgot/reset password, 2fa setup
dashboard/ machine list and per-machine live dashboard
system/ date/time, localization
admin/ users, config
api/ internal endpoints (e.g. emailer)
lib/
auth/ Better Auth server + client
components/ shadcn-svelte UI + dashboard panels (cpu, network, storage, ...)
machines/ valibot schemas
remotes/ SvelteKit remote functions (server.remote.ts, machines.remote.ts, ...)
server/
db/ Drizzle schema + custom encrypted column type
emails/ nodemailer + better-svelte-email templates
nadir-agent/ generated OpenAPI types + typed client
paraglide/ generated i18n runtime
messages/ translation source (en, ...)
config/oauth.json optional OAuth providers passed to Better Auth
Deploying
adapter-node produces a plain Node/Bun server under build/:
bun run build
PORT=3000 ORIGIN=https://nadir.example.com bun run build/index.js
Put it behind the same reverse proxy you use for nadir-agent, or co-host them. The agent's CSRF rules apply when the UI calls it cross-origin - see the agent README's Connecting a dashboard section.
License
MIT.