Zeus is a self hosted license management system for teams selling private products, subscriptions, or access controlled resources. It combines an admin dashboard, a Discord authenticated client portal, a Discord bot, and a small set of automation endpoints for validation and provisioning.
The project is intentionally simple to run. The web app is built on Next.js App Router, the bot is built on Discord.js, and persistent state lives in JSON files under data/. That makes local setup fast and keeps single instance deployments straightforward. It also means the current storage model is designed around one deployed instance with data/ treated as the source of truth.
Note
Zeus is still moving quickly. If you run into a bug or an edge case, open an issue.
The product direction takes cues from panels like Phantom and Sun Licenses, but the implementation here is focused on a smaller operational footprint, simpler setup, and clearer extension points.
Small thanks to Sun Licenses and Ember for some of the early inspiration behind the project.
- Product management
- License creation, renewal, activation, deactivation, and deletion
- Customer records with owner and sub user relationships
- Voucher generation and redemption flows
- IP, HWID, and Discord based blacklist controls
- License validation with configurable response payloads
- BuiltByBit webhook and placeholder purchase flows
- Discord bot commands for staff and end users
- Dashboard reporting for validations, new customers, webhook activity, and bot usage
Zeus ships as two cooperating parts:
- A Next.js app that serves the admin dashboard, client portal, and API routes
- A Discord bot process that handles slash commands and reports usage back to the panel
When you run bun run dev, the supervisor script does three things before the web server comes up:
- Syncs
data/settings.jsonintosrc/bot/config.json - Deploys enabled guild slash commands if the bot is configured
- Starts the bot if
discordBot.enabledistrueandDISCORD_BOT_TOKENis present
The web app runs on port 9002 by default in both development and production. bun start starts the web server and bot as one supervised process, so shutdown and failure handling stay linked. You can override the port with PORT.
The current persistence layer is file based and lives entirely under data/. Writes are done atomically, and the app uses in process file locks to avoid clobbering concurrent updates inside a single runtime. That is a good fit for local development and small to medium single host deployments.
If you need horizontal scaling, shared storage, or higher write throughput, the place to swap persistence is src/lib/data.ts. The rest of the codebase is already structured so the data layer is reasonably isolated.
src/app Next.js routes, pages, layouts, and API endpoints
src/components UI components for the dashboard, client portal, and integrations
src/lib Auth, data access, server actions, settings validation, and utilities
src/bot Discord bot runtime, command handlers, and bot config
data JSON backed application state
scripts Startup, config sync, and maintenance helpers
public Static assets
The most important files if you are extending the project are:
src/lib/data.tsfor persistencesrc/lib/actions.tsfor server side mutationssrc/lib/auth.tsfor admin and client session handlingsrc/lib/settings-validation.tsfor settings shape and validation rulessrc/bot/commands/for slash command behavior
- Clone the repository and install dependencies.
git clone https://github.com/unt1tler/Zeus.git
cd Zeus
bun install-
Copy
.env.exampleto.envand set the required values. -
Start the app.
bun run dev-
Open
http://localhost:9002/admin/loginand sign in withLOGIN_EMAILandLOGIN_PASSWORD. -
Configure the runtime settings from the dashboard, especially
panelUrl, admin API settings, and Discord settings if you plan to use the bot or client portal.
If you only want the panel, the Discord bot can stay disabled. If you want the client portal or slash commands, finish the Discord configuration in settings and provide a valid DISCORD_BOT_TOKEN.
These values are required for a usable local setup:
LOGIN_EMAILLOGIN_PASSWORDSESSION_SECRET
These values are optional, depending on how much of the stack you want to enable:
DISCORD_BOT_TOKENfor the bot runtime, slash command deployment, and Discord user enrichmentPORTto run the panel and bot bridge on a port other than9002TRUST_X_FORWARDED_FOR=trueif you are behind a trusted reverse proxy and want the app to readX-Forwarded-ForSESSION_COOKIE_SECURE=true|falseif you want to explicitly override secure cookie behavior
Two values deserve a note:
INTERNAL_PANEL_URLAPI_KEY
If you start the project through the bundled scripts, both are injected into the bot automatically from panel settings. If you run the bot separately, set them yourself.
Operational settings that change per deployment live in data/settings.json and can be managed from the dashboard. That includes:
- Admin API enablement and per endpoint toggles
- Client portal enablement and accent color
- Validation response shape
- BuiltByBit webhook mode and placeholder mode settings
- Discord bot client ID, guild ID, client secret, admin IDs, command toggles, and presence
- Webhook based audit logging
The bot configuration is synced into src/bot/config.json on startup, so the panel remains the main control surface.
Admin access is handled with signed HTTP only session cookies and credentials from the environment. The admin entry point is /admin/login.
Client access is handled through Discord OAuth. The public client login route is /login, and authenticated users land on /client. If the client portal is disabled in settings, those routes stay out of the way.
The main external surfaces are:
POST /api/validatefor license validationGET /api/admin/licensesandPOST /api/admin/licensesfor admin API listing and creationPATCHandDELETE /api/admin/licenses/[key]for admin lifecycle actionsPATCH /api/admin/licenses/[key]/renewfor renewalsPATCH /api/admin/licenses/[key]/identitiesandPOSTorDELETE /api/admin/licenses/[key]/sub-usersfor identity managementPOST /api/webhooks/builtbybitfor BuiltByBit automationPOST /api/webhooks/builtbybit/placeholderfor the placeholder flow
The admin API is guarded by x-api-key, rate limited, and individually switchable per endpoint from settings.
- Validation logs include IP address, HWID, Discord ID, product context, result, and optional geolocation data for public IPs.
- Slash commands are deployed as guild commands, so command updates apply quickly once the bot is configured.
- The dashboard uses the local bot status endpoint on
http://localhost:8081/statusto report whether the bot is online. - Your actual application state lives in
data/. Back that directory up.
Use the standard scripts:
bun run build
bun run startbun run build attempts slash command deployment first and still completes the Next.js build if Discord credentials are missing or invalid. bun start starts the panel and attempts to start the bot under one supervisor process. If the bot cannot start, the panel stays online and continues running on port 9002 unless PORT is set.
Before putting Zeus behind a public domain, make sure these are set correctly:
panelUrlin settings matches the public origin- Discord OAuth credentials are valid if the client portal is enabled
- BuiltByBit secrets are configured if webhook automation is enabled
- Proxy header trust is configured intentionally
Common extension points are straightforward:
- Add routes or server endpoints under
src/app - Add bot commands under
src/bot/commands - Replace the file store in
src/lib/data.ts - Extend settings validation in
src/lib/settings-validation.ts - Add new admin actions in
src/lib/actions.ts
If you are adapting Zeus to a database backed deployment, start with the data layer first. Most of the rest of the application already consumes that layer instead of reading files directly.
Pull requests are welcome. If you are planning a larger behavioral change, open an issue first so the direction is clear before code starts moving.
