Documentation
How everything works and how to set it all up, from the Discord bot to Staffly Link and the Studio.
Start here
What Staffly isQuick start (10 minutes)Staffly Bot
Setting up the BotCommand referenceTracking, quotas and flagsLeave, applications, promotionsEvery dashboard tabStaffly Link
Creating a workspacePeople, departments and rolesTasksApprovalsQuotas and reportsMarketing and publishingPlans and limitsStudio
Studio: building with blocksStudio: writing code (advanced)Running it yourself
Operator setup (self-hosting)Help
Cheat sheetTroubleshootingGlossaryWhat 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)
- Click Add Staffly to your server on the home page and approve the permissions.
- In Discord run
/setup(you need Administrator). This connects the server to its dashboard and syncs your members. - Open the Dashboard, sign in with Discord, pick your server, then go to Settings.
- Choose your Tracked roles (who counts as staff) and a Quota report channel and Flags channel.
- Go to the Quota tab and set targets per role.
- Optional: open Staffly Link, sign in with Discord as the server owner, and create a workspace for the server.
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
| Command | Who | What it does |
|---|---|---|
/setup | Administrator | Connects the server and syncs tracked members. |
/sync | Admins | Forces a refresh. |
/myquota | Staff | Shows your own progress this period. |
/quota-reset | Leadership / Timeout Members | Resets one person's quota. |
/quota-reset-all | Manage Server | Resets everyone and posts a pass/fail report. |
/addadmin /removeadmin | Administrator | Grant or revoke dashboard access. |
/loa start end reason | Staff | Request leave of absence. |
/apply | Anyone | Apply for a position (needs Applications switched on). |
/promote /demote | Manage Roles or a promotion manager role | Move someone along your rank order. Options: user, ranks (1 to 10), reason. Needs Promotions switched on. |
/workspace | Workspace members | Your 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
| Tab | Use it to |
|---|---|
| Overview | See what needs attention right now. |
| Staff | Browse tracked staff and their numbers. |
| Quota | Set targets per role, see progress. |
| Flags | Review and close flags. |
| Leave of absence | See, add or cancel leave. |
| Applications (beta) | Review applications and set questions. |
| Promotions (beta) | Rank order and promotion history. |
| Recognition | Praise staff. |
| HR, Recruitment, Incidents | Optional suites for records, hiring, and incident reports. |
| Community, Showcase | Community features and your server's public showcase. |
| Premium | Upgrade and plan details. |
| Access | Who may edit the dashboard. |
| Settings | All the options above. |
Creating a workspace
A server owner opens /workspace, signs in with Discord, and creates a workspace from a server they own. The owner is the workspace Owner. A workspace can include several servers.
People, departments and roles
Members have a workspace role: owner, admin or member. Departments group people (Moderation, Marketing...). Each department role carries permissions:
view create edit approve publish admin finance
Settings can be set at the workspace level and overridden per server or department; the most specific one wins.
Tasks
A task has a scope: workspace, chosen servers, or a department. Assignment modes:
- users: named people, shared.
- each: every named person must finish it separately.
- claim: the first person to claim it owns it.
- open: anyone in scope can do it.
Tasks can have a due date, priority, checklist, links, and can require approval before they count as done.
Approvals
Anything that needs sign-off goes through a chain. Default chains exist for task, content, budget, config, script and general requests. Budget chains go through department leadership then the Owner always. A chain has up to 6 steps and nobody approves their own request. Pending approvals also show in /workspace on Discord.
Quotas and reports
Workspace quotas have requirements measured by: messages, voiceMinutes, tasksCompleted, contentPublished, manual (someone ticks it off) or script (a Studio automation records it). Presets: general, moderation, tickets, training, tasks, marketing, community.
Marketing and publishing
Videos move through statuses with approval before publishing, and can be published to TikTok and YouTube. Failed posts retry after 5, 30 and 120 minutes (3 attempts). A post stuck for 45 minutes is marked stale. Default max video size is 100 MB (MP4, MOV, WebM). Budgets are tracked too, and approving a budget is not the same as releasing money.
Connecting accounts (operator)
Create apps with TikTok and Google, put their keys in the web .env (see Operator setup), and register these redirect URIs exactly:
PUBLIC_URL/api/org/oauth/tiktok/callback PUBLIC_URL/api/org/oauth/youtube/callback
Plans and limits
Staffly Link is in beta and free to use. Leave of Absence is always free. When Link plans open, a free workspace can include 2 servers, and a Link plan (or a connected server with Staffly Premium) allows up to 50 and adds combined reports and the Studio. Owners buy and manage the plan on the workspace Plan page, and can ask for a refund there.
Studio: building with blocks
The Studio makes automations. You do not need to code: you snap blocks together.
Make one
- Open Studio in the workspace and choose New script.
- Pick Blocks and optionally a starter (“Thank people who finish a task”, “Follow up on a missed quota”, “Weekly quiet staff report”).
- 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. - Open When it starts and choose the trigger (below).
- 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.
- Save draft, then Publish. Publishing goes to approval; approvers see a plain-English summary of what the automation does.
Blocks
| Block | What it does |
|---|---|
| Send a notification | Notifies a person. |
| Create a task | Makes a task. |
| Record quota progress | Ticks off a requirement for a person. |
| Raise an event | Starts other automations. |
| Write to the log | Adds a line to the run log. |
| For each staff member | Repeats the blocks inside for everyone. |
| Look up activity | Gets someone's messages and voice minutes. |
| Load / Save / Add to a remembered value | Remembers things between runs. |
| Set a variable, Do math | Keep and calculate values. |
| If / Otherwise | Do different things depending on a check. |
| Stop | Ends 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).
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.
| Limit | Value |
|---|---|
| Scripts per workspace | 50 |
| Source size | 20,000 characters |
| Saved versions | 30 |
| Run records kept | 50 |
| Run time | 10 seconds |
| API calls per run | 150 |
| Notifications / tasks / events per run | 20 / 10 / 5 |
| Stored data | 16,384 characters |
| At once | 2 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
- 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.
- Under OAuth2 add the redirect URI that matches
DISCORD_REDIRECT_URI. - If you use the separate Link bot (
linkBot.js), create a second application for it.
Web app apps/web/.env
| Key | Meaning |
|---|---|
| PORT, PUBLIC_URL | Port and public https address. |
| API_KEY | Shared secret between web and bot. |
| SESSION_SECRET | Long random string for logins. |
| DISCORD_CLIENT_ID / SECRET / REDIRECT_URI | Discord login. |
| SUPER_ADMIN_IDS | Discord IDs of Staffly's own operators. |
| DISCORD_BOT_TOKEN | Bot 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_ID | The Link bot. |
| TIKTOK_CLIENT_KEY / SECRET, GOOGLE_CLIENT_ID / SECRET | Publishing (optional). |
| ORG_MAX_VIDEO_MB | Video size cap (default 100). |
| RESTART_DAY / RESTART_HOUR | Optional 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
| Problem | Try |
|---|---|
| Slash commands missing | Run npm run deploy-commands, wait a minute, restart Discord. |
| Dashboard says the server is not set up | Run /setup as an Administrator. |
| Nobody's activity is counted | Check 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 out | The plan needs the scripting entitlement. |
| A script won't publish | It is waiting for approval. Check Approvals. |
| Video upload fails | Check size (100 MB), format, and nginx/Cloudflare limits. |
| Site won't start after an update | pm2 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.
