No description
  • TypeScript 96%
  • Dockerfile 4%
Find a file
2026-06-27 21:41:56 +02:00
src first commit 2026-06-27 21:41:56 +02:00
.dockerignore first commit 2026-06-27 21:41:56 +02:00
.env.example first commit 2026-06-27 21:41:56 +02:00
.gitignore first commit 2026-06-27 21:41:56 +02:00
docker-compose.yml first commit 2026-06-27 21:41:56 +02:00
Dockerfile first commit 2026-06-27 21:41:56 +02:00
package-lock.json first commit 2026-06-27 21:41:56 +02:00
package.json first commit 2026-06-27 21:41:56 +02:00
README.md first commit 2026-06-27 21:41:56 +02:00
tsconfig.json first commit 2026-06-27 21:41:56 +02:00

dokcord 🐾

A Discord widgets v2 profile widget + bot that shows your live Dokploy stats — projects, apps, databases, running/stopped counts, recent deployments and server metrics — right on your Discord profile.

It's a user-installable bot: anyone can install it, run /widget setup with their own Dokploy URL + API key, authorize the widget, and their profile widget fills with their infra stats. A background scheduler keeps every linked widget refreshed.

panel.example.com — All systems go
📦 4 projects · 🚀 11 apps · 🗄️ 3 dbs
🟢 12 running · 🔴 0 down · 🖥️ 2 servers
✅ last deploy: my-api · 5 today
📊 CPU 23% · RAM 52% · Disk 61%

Heads up: Discord "widgets v2" is an experimental feature gated behind the Social SDK / a Developer Portal experiment. The portal side is fiddly and manual — this repo gives you the whole code side (Dokploy client, bot, refresher), but you still have to design the widget and flip the experiment yourself. The flow below is based on Chloe Cinders' guide (thank you!).


How it fits together

 Dokploy API ──(x-api-key)──▶ DokployClient ──▶ stats ──▶ buildIdentityProfile
                                                                  │
 Discord user ──/widget setup──▶ bot (discord.js)                 ▼
                                          PATCH /applications/{app}/users/{user}/identities/0/profile
                                                                  │
 scheduler (every N s) ───────────────────────────────────────────┘  ──▶ widget renders on profile
  • src/dokploy.ts — reads project.all, deployment.allCentralized, server.all, metrics.
  • src/widget.ts — folds stats into the Discord widget dynamic fields.
  • src/discordIdentity.ts — the PATCH that actually fills a user's widget.
  • src/commands.ts / src/bot.ts/widget setup|refresh|status|unlink.
  • src/scheduler.ts — periodic refresh of every linked user.
  • src/db.ts — SQLite (node:sqlite, no native build) storing links; API keys encrypted at rest.

Prerequisites

  • Node.js 20+ (uses the built-in node:sqlite; tested on Node 26).
  • A Dokploy instance and an API key (Settings → Profile → API/CLI).
  • A Discord application with Social SDK access.

Part 1 — Discord Developer Portal (manual, one-time)

This is the part no script can do for you. Follow Chloe's guide closely; the short version:

  1. Create an application at the Developer Portal.

  2. Get Social SDK access: sidebar → Games → Social SDK, fill the form, submit (instant).

  3. Unlock the widget editor (experiment override). Open DevTools console on the Developer Portal and run the snippet from the guide that calls createOverride("2026-03-widget-config-editor", 1). Click the back arrow, reopen your app — a Widget entry appears under Games. (Don't refresh, it clears the override.)

  4. Create your widget in the editor. Add a Widget Top, Widget Bottom, and Add-Widget Preview. For every stat, add a User Data field whose Data Field name matches exactly one of dokcord's field names below (and matching value type). Give each a fallback. Style it, add Sample Data, Save + Publish.

    Field name (Data Field) Type Meaning
    instance Text Dokploy host, e.g. panel.example.com
    status Text Headline, e.g. All systems go / 2 errored
    projects Number Project count
    apps Number Applications + compose stacks
    databases Number DB count (pg/mysql/mariadb/mongo/redis/libsql)
    running Number Services running
    stopped Number Services stopped or errored
    servers Number Connected servers
    deploys_today Number Deployments since local midnight
    last_deploy Text e.g. ✅ my-api
    metrics Text e.g. CPU 23% · RAM 52% · Disk 61%

    You don't have to use all of them — only the fields you put in the widget get rendered. The names live in WIDGET_FIELDS in src/widget.ts; keep the two in sync if you rename anything.

  5. OAuth2: sidebar → OAuth2. Add a redirect URI (e.g. https://discord.com). In the URL Generator pick scopes openid + sdk.social_layer, select your redirect, copy the URL, and change response_type=coderesponse_type=token. This is your DISCORD_AUTHORIZE_URL.

  6. Bot token: sidebar → Bot → Reset Token. That's DISCORD_BOT_TOKEN. Your Application ID (General Information) is DISCORD_APP_ID.

  7. Add the widget to a profile via the snippets in the Discord Previews thread (and set the 2026-03-application-widget-v2-renderer experiment to Variant 1).


Part 2 — Run dokcord

cp .env.example .env
# fill in DISCORD_APP_ID, DISCORD_BOT_TOKEN, DISCORD_AUTHORIZE_URL
openssl rand -hex 32   # paste into ENCRYPTION_KEY

npm install
npm run register       # publish the /widget slash command (once, and after edits)
npm run dev            # or: npm start

.env keys are documented in .env.example. Notable ones:

  • ENCRYPTION_KEY — 32-byte hex; encrypts stored Dokploy keys (AES-256-GCM).
  • REFRESH_INTERVAL_SECONDS — auto-refresh cadence (default 300; 0 disables).
  • REFRESH_STAGGER_MS — delay between users in a sweep so we don't hammer APIs.
  • REGISTER_ON_STARTtrue to publish /widget on boot (skips npm run register).

Running with Docker

The image is a multi-stage build that compiles to dist/ and runs on plain Node (no tsx at runtime), as a non-root user, with the SQLite DB persisted on a named volume.

cp .env.example .env          # fill it in; set REGISTER_ON_START=true for first boot
docker compose up -d --build  # build + run
docker compose logs -f        # watch it come up

Or with plain Docker:

docker build -t dokcord .
docker run -d --name dokcord --restart unless-stopped \
  --env-file .env \
  -v dokcord-data:/app/data \
  dokcord

Notes:

  • Needs Node 24+ for the built-in node:sqlite; the image defaults to node:24-slim (override with the NODE_VERSION build arg).
  • The DB lives at /app/data/dokcord.sqlite inside the container — the dokcord-data volume keeps your links across restarts/rebuilds. Back up that volume (it holds your encrypted links), and keep ENCRYPTION_KEY stable or you won't be able to decrypt stored keys.
  • After the first successful boot you can set REGISTER_ON_START=false again to avoid re-publishing the command every restart.

Part 3 — Using it

  1. Install the app on your account (user-install) from its install link.
  2. Run /widget setup url:https://panel.example.com key:<dokploy-api-key>. dokcord validates the key, stores it (encrypted), and tries a first push.
  3. Click Authorize widget in the reply and approve the scopes. (It asks for a lot — that's the sdk.social_layer scope; dokcord never acts on those, it only PATCHes your widget identity.)
  4. Run /widget refresh. Your profile widget should now show live stats. The scheduler keeps it updated from here on.

Other commands: /widget status (last refresh + any error), /widget unlink (delete your key, stop refreshing).


Notes & limitations

  • Server metrics require Dokploy's monitoring container; dokcord reads it best-effort via the first server that exposes a metricsConfig. No monitoring set up → the metrics field is simply omitted.
  • The Dokploy JSON shape varies across versions, so the client is defensive (it walks both the newer environments[] nesting and the older flat layout). If a section can't be read it's skipped rather than failing the whole refresh.
  • Security: stored API keys are encrypted at rest, only ever used server-side to read stats, and deletable with /widget unlink. Still — a Dokploy API key grants full control of someone's infra. If you run this publicly, make that trade-off clear to your users and protect the host + .env/database accordingly.
  • Discord's widgets v2 is experimental and undocumented; Discord can change or pull it at any time. Don't abuse it.

Scripts

Command What it does
npm run dev Run with file-watch (tsx).
npm start Run once (tsx).
npm run register Publish/refresh the /widget command globally.
npm run typecheck tsc --noEmit.
npm run build Emit JS to dist/.

Credits: widget technique from Chloe Cinders · xivwidget.