Documentation

How everything works and how to set it all up, from the Discord bot to Staffly Link and the Studio.

What Staffly is

Staffly is two products that work together.

  • Staffly Bot lives in your Discord server. It counts messages and voice time for your staff, enforces quotas, raises flags, and handles leave, applications and promotions. You control it from the Dashboard (/dashboard).
  • Staffly Link is the workspace (/workspace) for running a team across one or more servers: tasks, approvals, departments, quotas, marketing publishing, and the Studio where you build automations from blocks.

The Bot answers “who is active?”. Link answers “who is doing what, and who signed it off?”. You can use either on its own.

Quick start (10 minutes)

  1. Click Add Staffly to your server on the home page and approve the permissions.
  2. In Discord run /setup (you need Administrator). This connects the server to its dashboard and syncs your members.
  3. Open the Dashboard, sign in with Discord, pick your server, then go to Settings.
  4. Choose your Tracked roles (who counts as staff) and a Quota report channel and Flags channel.
  5. Go to the Quota tab and set targets per role.
  6. Optional: open Staffly Link, sign in with Discord as the server owner, and create a workspace for the server.
If something does not work, jump to Troubleshooting.

Setting up the Bot

Add it

Use the invite button on the site. The person adding it needs the Manage Server permission. Keep the Bot's role high enough to manage the roles you want it to give (applications and promotions).

Connect it

Run /setup. Only a user with Administrator can. It links the server to its dashboard and syncs tracked members. Run /sync any time to force a refresh.

Give people dashboard access

/addadmin and /removeadmin (Administrator) grant or revoke dashboard access for a user. The Access tab does the same by role or user ID. Admins cannot add other admins; only the owner can.

Command reference

CommandWhoWhat it does
/setupAdministratorConnects the server and syncs tracked members.
/syncAdminsForces a refresh.
/myquotaStaffShows your own progress this period.
/quota-resetLeadership / Timeout MembersResets one person's quota.
/quota-reset-allManage ServerResets everyone and posts a pass/fail report.
/addadmin /removeadminAdministratorGrant or revoke dashboard access.
/loa start end reasonStaffRequest leave of absence.
/applyAnyoneApply for a position (needs Applications switched on).
/promote /demoteManage Roles or a promotion manager roleMove someone along your rank order. Options: user, ranks (1 to 10), reason. Needs Promotions switched on.
/workspaceWorkspace membersYour Link tasks, waiting requests and quotas, inside Discord.

Tracking, quotas and flags

What is counted

Messages and voice minutes, for members who hold a tracked role, in channels that are tracked (or not ignored). Message content is never stored, only counts.

Quotas

Set targets per role in the Quota tab. The Quota period in Settings is DAILY, WEEKLY, MONTHLY or MANUAL. When a period ends, Staffly posts who met quota and who did not in the quota report channel and resets the counters. People on approved leave are skipped.

Flags

AutoFlagging raises flags for you:

  • Inactivity: no activity for the number of days you set.
  • Spam: max messages inside a time window. The member gets a friendly reminder in channel first; a flag only after the number of warnings you set, with a cooldown between warnings.
  • Voice AFK: idle for the seconds you set. A DM warning first, then a flag and removal from voice.

Each flag posts in the flags channel with an ID and a button to mark it reviewed or reopen it.

Leave, applications, promotions

Leave of absence

Staff run /loa. The request goes to the leave request channel; approved leave shows on the dashboard and exempts the person from quota and inactivity flags. Admins can cancel it.

Applications (beta)

Turn on in Settings. Set the review channel, whether the Bot DMs the applicant, a cooldown in days, the positions and up to five questions. Applications post with Accept and Deny buttons; accepting gives the role.

Promotions (beta)

Turn on in Settings. Set the rank order (the roles, lowest to highest), grants, max ranks per use, cooldown, whether a reason is required, whether the old rank is removed, whether grants are removed on demotion, an announce channel, DM, and the manager roles allowed to use the commands.

Every dashboard tab

TabUse it to
OverviewSee what needs attention right now.
StaffBrowse tracked staff and their numbers.
QuotaSet targets per role, see progress.
FlagsReview and close flags.
Leave of absenceSee, add or cancel leave.
Applications (beta)Review applications and set questions.
Promotions (beta)Rank order and promotion history.
RecognitionPraise staff.
HR, Recruitment, IncidentsOptional suites for records, hiring, and incident reports.
Community, ShowcaseCommunity features and your server's public showcase.
PremiumUpgrade and plan details.
AccessWho may edit the dashboard.
SettingsAll the options above.
The old Scheduling tab and shift DMs were removed. Use Link tasks instead.

Studio: building with blocks

The Studio makes automations. You do not need to code: you snap blocks together.

Make one

  1. Open Studio in the workspace and choose New script.
  2. Pick Blocks and optionally a starter (“Thank people who finish a task”, “Follow up on a missed quota”, “Weekly quiet staff report”).
  3. On the Build tab add blocks from the + Add a block menu. Fill in the fields. Use Insert… to drop in details like the person's name, {{event.task.title}} style.
  4. Open When it starts and choose the trigger (below).
  5. Press Test run. You can edit the “pretend details” the test uses. Nothing real is sent to people from a test, and the log shows what would happen.
  6. Save draft, then Publish. Publishing goes to approval; approvers see a plain-English summary of what the automation does.

Blocks

BlockWhat it does
Send a notificationNotifies a person.
Create a taskMakes a task.
Record quota progressTicks off a requirement for a person.
Raise an eventStarts other automations.
Write to the logAdds a line to the run log.
For each staff memberRepeats the blocks inside for everyone.
Look up activityGets someone's messages and voice minutes.
Load / Save / Add to a remembered valueRemembers things between runs.
Set a variable, Do mathKeep and calculate values.
If / OtherwiseDo different things depending on a check.
StopEnds the run.

Triggers

task.assigned task.completed approval.submitted approval.approved approval.rejected quota.completed quota.missed content.published member.added role.changed schedule webhook and your own custom.* events.

Limits

Up to 60 blocks, nested at most 4 deep, text up to 500 characters. Variable names are letters, numbers and underscores (max 25).

Permissions are worked out from the blocks you use, so you never have to pick them.

Studio: writing code (advanced)

If you know JavaScript you can pick Code instead. Scripts run in a locked-down sandbox (Node 20+, no network or file access). Switching a blocks script to code is one way; blocks are cleared. A code script asks for permissions you list: staff.read quotas.read quotas.write tasks.read tasks.write notify events.emit store.

LimitValue
Scripts per workspace50
Source size20,000 characters
Saved versions30
Run records kept50
Run time10 seconds
API calls per run150
Notifications / tasks / events per run20 / 10 / 5
Stored data16,384 characters
At once2 runs

The in-app Manual button in the Studio lists every function available to code scripts.

Operator setup (self-hosting)

For whoever runs the Staffly servers. Needs Node 20+ and pm2.

Discord developer portal

  1. Create an application and a bot. Under Bot, switch on the privileged intents Server Members, Presence and Message Content (the bot uses all three). Message content is only counted, never stored.
  2. Under OAuth2 add the redirect URI that matches DISCORD_REDIRECT_URI.
  3. If you use the separate Link bot (linkBot.js), create a second application for it.

Web app apps/web/.env

KeyMeaning
PORT, PUBLIC_URLPort and public https address.
API_KEYShared secret between web and bot.
SESSION_SECRETLong random string for logins.
DISCORD_CLIENT_ID / SECRET / REDIRECT_URIDiscord login.
SUPER_ADMIN_IDSDiscord IDs of Staffly's own operators.
DISCORD_BOT_TOKENBot token.
VAULT_KEY (VAULT_KEY_PREVIOUS)Encrypts stored tokens. Generate with npm run vault-key, rotate with npm run vault-rotate. Never lose it.
STRIPE_*Payments.
LINK_BOT_TOKEN, LINK_BOT_CLIENT_IDThe Link bot.
TIKTOK_CLIENT_KEY / SECRET, GOOGLE_CLIENT_ID / SECRETPublishing (optional).
ORG_MAX_VIDEO_MBVideo size cap (default 100).
RESTART_DAY / RESTART_HOUROptional scheduled restart.

Bot apps/bot/.env

DISCORD_BOT_TOKEN, DISCORD_CLIENT_ID, API_BASE_URL (the web app), API_KEY (same as web), DASHBOARD_PUBLIC_URL, SHOWCASE_CHANNEL_ID.

Run it

cd apps/web && npm install --omit=dev
cd ../bot && npm install --omit=dev && npm run deploy-commands
pm2 start ... (names: staffly-web, staffly-bot, staffly-link-bot)
pm2 restart staffly-web staffly-bot staffly-link-bot
pm2 logs

Run npm run deploy-commands whenever commands change.

nginx / Cloudflare

Set client_max_body_size 120m; for video uploads. Cloudflare's free plan caps uploads at 100 MB.

Data and backups

Everything is JSON under the web app's data/ folder (workspaces in data/orgs/). Back up that folder and the .env files, including VAULT_KEY. Other scripts: purge-punishments, cleanup-stale-guilds.

Cheat sheet

  • Free: 2 servers in a workspace. Paid: up to 50.
  • Approval chains: max 6 steps.
  • Applications: up to 5 questions.
  • Promotions: 1 to 10 ranks per use.
  • Studio: 60 blocks, 4 deep, 10 s per run.

Troubleshooting

ProblemTry
Slash commands missingRun npm run deploy-commands, wait a minute, restart Discord.
Dashboard says the server is not set upRun /setup as an Administrator.
Nobody's activity is countedCheck Tracked roles, and that the channel is not ignored. Run /sync.
Can't give a role (promotions, applications)Move the Bot's role above the role it must give.
Studio is greyed outThe plan needs the scripting entitlement.
A script won't publishIt is waiting for approval. Check Approvals.
Video upload failsCheck size (100 MB), format, and nginx/Cloudflare limits.
Site won't start after an updatepm2 logs staffly-web; a missing file usually means an old and new zip were mixed. Re-upload the newest zips.

Still stuck? Join the support server.

Glossary

  • Workspace: your team's home in Link.
  • Department: a group of people with role permissions.
  • Approval chain: ordered sign-offs.
  • Quota: a target for a period.
  • Flag: a Bot warning about a person.
  • Block: a Studio building piece.
  • Trigger: what starts an automation.
  • Studio: where automations are made.

Nothing matches that search.