Skip to content

Phantom — Platform Features & UX Review (July 2026)

A deep code analysis of the entire platform (Laravel dashboard + Node bot, ~50 bot modules, ~90 dashboard pages) with concrete, code-grounded recommendations for what to add, improve, and expand. Every "missing" claim below was verified against the actual code, with file references.


Executive summary

Phantom is unusually strong in security (Wick-tier: anti-raid, anti-nuke, firewall, honeypot, phantom-network threat sharing), tickets (transcripts, canned responses, ratings — Ticket Tool-tier), moderation (cases + a full appeals system), and it has several genuinely uncommon modules (reviews, partnerships, interactive panels, custom bots, auto-assist RAG AI). The dashboard already has best-in-class bones: searchable Discord-populated channel/role pickers, live embed previews, placeholder pickers, team-role permission delegation, and an onboarding tour.

The biggest opportunities, in order of impact:

  1. Streamer alerts are global-only — one channel, one message, one ping role shared by all 25 streamers per platform. Per-streamer overrides is the single highest-value upgrade and directly matches what Streamcord/Pingcord users expect.
  2. 28 of the 33 documented outbound webhook events never fire. The whole webhook infrastructure (signing, retries, dashboard UI, docs) exists, but the bot never emits. Finishing this turns a dead feature into a real developer platform.
  3. Economy has no shop, no bank, no activities — the module header itself says "future shop purchases."
  4. Levelling lacks image rank cards and role/channel XP multipliers — table stakes vs MEE6/Arcane, and the canvas infra already exists in welcome/image.js.
  5. Dashboard has no settings change-history and no config export/import — the biggest day-to-day admin pain for team-run and multi-server owners.

1. Streamer alerts — the headline upgrade

Current state (verified)

  • Platforms: Twitch (EventSub push + Helix polling backstop), YouTube (page scrape + Atom feed), Kick (public API), TikTok (multi-fallback scrape). Uploads/VODs announced for all four via a 5-min video sweep.
  • Config is stored per platform as a JSON blob on guild_settings (twitch_config, etc.). Per guild per platform: one channel_id, one ping_role_id, up to 5 live_role_ids, one message template (500 chars), one keyword/game filter set, and a list of up to 25 streamers.
  • Per-streamer, the only stored data is: username/handle, display name, and an optional linked Discord member (used for the live role). Nothing else. (bot/src/streamer-alerts/registry.js:76-140)
  • The embed is fully hardcoded in bot/src/streamer-alerts/announce.js:94-108 — fixed per-platform color, fixed layout, fixed fields. The message template only prepends text above it.
  • Stream-end handling: edits the announcement to a fixed grey "ended" card. No delete option, no VOD link, no duration/peak stats.

1a. Per-streamer overrides (the core ask)

Add an optional overrides object to each entry in streamers[]/creators[], falling back to the platform-level config when unset:

jsonc
{
  "username": "shroud",
  "display_name": "Shroud",
  "discord_user_id": "…",
  "overrides": {
    "channel_id": "…",        // per-streamer announcement channel
    "message": "…",           // per-streamer go-live message
    "ping_role_id": "…",      // per-streamer ping role
    "live_role_ids": ["…"],   // per-streamer live role(s)
    "filters": {  },          // per-streamer title/category filters
    "enabled": true,           // pause one streamer without removing them
    "embed": {  }             // see 1b
  }
}

Implementation notes:

  • registry.js currently builds one slice per (guild, platform) applied to every streamer. Change the slice builders to resolve streamer.overrides ?? platformDefaults per entry — the poller and announce paths already operate per-streamer state row, so the change is contained to slice resolution + controller validation.
  • Dashboard: each row in the "Tracked streamers" list gets an expandable "Customise" section (channel picker, message textarea with placeholder picker, role pickers) that shows "Using server default" until overridden. The existing channel-picker / role-picker / placeholder-picker Blade components drop straight in.
  • Keep controllers' normalize() clamping caps per override (reuse existing limits).

1b. Custom embed builder for alerts

The repo already has a full Embed Builder (EmbedBuilderController, live Discord-styled preview at resources/views/dashboard/embed-builder/_edit_preview.blade.php) — it just isn't wired to streamer alerts. Let admins either:

  • pick a saved embed template per platform (and per streamer via overrides), with alert placeholders resolved at send time; or
  • use a scoped inline builder: color, title, description, show/hide viewer count & category fields, image vs thumbnail, author icon (streamer avatar — already cached in discord_avatar_url but never used in embeds), footer.

Also add an optional "Watch now" link button (message components) — cheap and looks premium.

1c. Preview / test send

There is currently no way to see an announcement without a real go-live (verified: no test route or UI in any of the four views). Add:

  • a live preview pane (same pattern as the embed builder preview) rendering the message + embed with sample data; and
  • a "Send test alert" button that posts a real test announcement to the configured channel with fake stream data. One route + a buildLivePayload() call with a synthetic stream object.

1d. Richer placeholders & docs

  • Current: {streamer} {title} {game} {url} (Twitch/Kick), {creator} {title} {url} {type} (YT/TikTok). {creator} and {type} work but are undocumented in the UI.
  • Add: {viewers}, {platform}, {member} (mention of the linked Discord member), {timestamp}, {profile_image} (for embed use), and unify {streamer}/{creator} as aliases everywhere.
  • Surface all of them in the existing placeholder-picker component instead of the static hint text.

1e. Stream-end & lifecycle options

  • Per platform (and per-streamer override): on stream end → edit to ended card (current), delete announcement, or leave as-is.
  • Enrich the ended card: stream duration, peak/average viewers (the poller already sees viewer counts every sweep — track max in the state row), and a VOD link when the video sweep finds one.
  • Customisable ended message template (currently a fixed grey card).
  • Optional per-streamer re-announce cooldown (suppress rapid offline/online flaps beyond the existing debounce).

1f. Distribution & platform expansion

  • Crosspost/publish automatically when the alert channel is an Announcement channel (one API call, big multiplier for community servers).
  • Optional auto-thread per stream ("discuss the stream here").
  • Kick webhooks: kick.js:11-13 already notes Kick's official livestream.status webhook as a future option — implement it to cut the 45s poll latency.
  • New platforms, in rough order of demand/effort: Trovo, Rumble, Facebook Gaming.
  • Unify the four dashboard pages (Twitch/YouTube/Kick/TikTok) into one "Streamer Alerts" surface with per-platform tabs — a streamer active on two platforms is currently configured twice with duplicated UI.

1g. Caps as premium levers

25 streamers/platform and 5 live roles are low vs competitor premium tiers (50–100+). Keep 25 for Pro base, sell higher caps in a future tier (see §6).


2. New notification platforms (beyond streamers)

Verified: the only external-content alert system is streamer-alerts. Twitter/X, Reddit, Instagram, RSS etc. appear only as decorative profile links in PublicLinkSanitiser — there is no poller for any of them.

Recommended additions, ordered by effort-to-value:

  1. RSS/Atom feeds — easiest (the YouTube watcher already parses Atom). Generic "post new feed items to a channel" with template + filters. Unlocks blogs, patch notes, subreddits-via-RSS, itch/Steam news.
  2. Reddit — new posts in a subreddit (public JSON API), with flair/keyword filters. Huge for gaming communities.
  3. Bluesky — public firehose/API, trivially pollable, growing creator base.
  4. Twitter/X — high demand but API pricing is hostile; consider only if a paid API budget exists (or accept RSS-bridge fragility).

All of these slot into the existing streamer-alerts architecture (registry → poller sweep → announce with template), so the marginal cost per platform is low.


3. Finish the half-built features (quick wins, verified in code)

ItemWhereState
Outbound webhook eventsconfig/api.php defines 33 event types; WebhookEvents::emit() called in only 3 PHP places28/33 events never fire. The bot (where joins, tickets, level-ups, giveaways, automod, starboard, modmail happen) emits zero. Recommended: bot-side emission via the existing Postgres NOTIFY pattern → PHP WebhookDispatcher, which already has signing, retries, auto-disable, and dashboard UI.
Giveaway invite-bonus entriesbot/src/giveaways/requirements.js computeBonus case 'invites'Empty branch with a comment saying it awaits an invite tracker — but bot/src/invites/ exists. Wire it up.
Giveaway verified_email requirementrequirements.js:56Always passes (`
First-message-per-user lookupcommands/handlers/info.js:218Replies "coming soon."
Catalog stub auditcommands/handlers/index.js:45Generic stubHandler replies "hasn't landed yet" for any catalog command without a handler — audit catalog keys vs HANDLERS map to find live shells.
API write scopes without routesconfig/api.php vs routes/api.phpScopes exist for cases.update, tickets.message/close, giveaways.end/reroll, levelling.adjust but no routes — add the endpoints or trim the scope catalog.

4. Bot feature expansions (verified absent)

Economy (biggest module gap)

  • Shop + items + inventory — flagged as "future" in economy/engine.js itself. Sellable role rewards, custom items, item-use hooks.
  • Bank / deposit / withdraw / interest — single wallet only today; a vault is prerequisite to…
  • Activities: work / crime / rob / fish / beg with cooldowns and per-role payouts (the per-role earn pattern already exists in resolveEarn). Today, free servers have zero economy games because all gambling is in the premium casino.
  • Level-up currency rewards — trivia already bridges XP↔currency; level-ups only grant roles.

Levelling

  • Image rank cards/level rank is an embed with an ASCII bar; the canvas infra from welcome/image.js is right there. Ship customisable rank cards (background, accent color) matching the welcome-card presets.
  • Per-role / per-channel XP multipliers (boost roles, boosted channels) — single global xp_multiplier today.
  • Seasons / leaderboard resets / prestige — no scheduled resets exist.
  • Voice-only leaderboard — voice XP is tracked but has no dedicated leaderboard or multipliers.

Community & engagement

  • Birthday module — personal birthdays are already stored via /p me birthday-set, but nothing consumes them. Add birthday announcements channel, birthday role for the day, and templated message. Very high demand, low effort given data exists.
  • Autoresponder (keyword → response, no prefix) — custom commands are prefix-only; there is no "reply when a message contains X." Core Carl-bot/Dyno feature.
  • Welcome DMwelcome/sender.js only posts to channels; add an optional private greeting with its own template.
  • Multiple starboards — single channel_id today; support per-emoji boards with distinct thresholds.
  • Slash-registered custom commands — register user-defined commands as guild slash commands instead of prefix-only.
  • Suggestion discussion threads — auto-open a thread per suggestion.
  • Server events / RSVP — extend scheduled-messages + reminder-scheduler into announced events with signups and reminder DMs; integrate Discord native Scheduled Events.
  • Temporary self-roles — wire temp-roles durations into reaction-role panels (e.g. self-assign event role that expires).
  • Counting extras — milestones, per-user counting leaderboard, high-score.
  • AI automod tier — automod is fully deterministic today; an optional AI toxicity classifier is a natural premium add (AI plumbing already exists via auto-assist/trivia).

5. Dashboard & UX improvements (verified)

  1. Settings change-history + rollback. GuildAuditEntry only records bot actions; settings controllers (Welcome, Logging, XP, Economy, Automod…) write no audit entries. Add "who changed what, when" per module with diff view and one-click revert — the single best feature for team-run servers, and it pairs with the existing team-permissions system.
  2. Config export / import / clone-from-server. Guild settings page offers only destructive Reset/Wipe. Add JSON export of module configs and "copy settings from another server I manage." (Server Templates cover structure, not module config.)
  3. Unify the save model. ~10 pages autosave, ~49 use explicit Save buttons, and there is no shared unsaved-changes guard — a big form can be lost by navigating away. Standardise on debounced autosave (the window.Phantom.makeDebouncedSave helper exists) or add a shared dirty-guard.
  4. Global settings search / command palette. Sidebar search only filters nav labels; with ~90 pages, add Ctrl+K search over module names and individual settings ("log channel for bans" → jumps to the field).
  5. True welcome-card preview. The dashboard emulates the canvas card in CSS (noted in-code as approximate). Add a server-rendered PNG preview endpoint using the bot's actual image.js renderer so glow/font/layout tuning is WYSIWYG.
  6. Finish the shared-JS migration. dashboard-helpers.js documents that toast/fetch/save logic is duplicated across 15+ blades with divergent error handling; guild-settings.blade.php still hand-rolls its own fetch. Completing the migration unifies UX and shrinks the 58k-line blade footprint.
  7. Theme option. The dashboard is hard-dark only (no light theme, no prefers-color-scheme handling) — worth at least a contrast/light option for accessibility.
  8. Finer-grained delegation (later). Team permissions are per-module view/edit; per-category scoping (e.g. "manage tickets only in the support category") is a plausible enterprise feature.

6. Integrations, API & monetization

  • Wire bot-side webhook emission first (§3) — everything else (Zapier/Make connector, "server events API" marketing) depends on events actually firing.
  • Zapier / Make connector — near-free once events fire; strong enterprise upsell.
  • Email digests / weekly server reportsconfig/mail.php exists but mail is unwired (MAIL_MAILER=log); the Analytics service already computes growth/retention/insights. A weekly owner digest is a classic premium hook.
  • Premium tier ladder. Today there is a single boolean Pro gate (premium_until) over ~8 features. Given the depth of free modules, there is headroom for Basic/Pro/Enterprise tiers differentiated by caps (streamers per platform, live roles, custom commands, panels, webhook endpoints, API rate limits) rather than by locking whole modules — caps monetize power users without gutting the free experience. Streamer-alert per-streamer overrides, custom alert embeds, AI automod, and email digests are all natural higher-tier features.

7. Suggested priority order

#ItemImpactEffort
1Per-streamer overrides (channel/message/ping/roles/filters/enable)Very highMedium
2Alert preview + test-send buttonHighLow
3Custom alert embeds (wire existing embed builder) + Watch buttonHighMedium
4Wire the 28 dead webhook events bot-sideHighMedium
5Giveaway invite-bonus wiring + verified_email fixMediumLow
6Birthday module (data already exists)HighLow-Med
7Image rank cards + XP role/channel multipliersHighMedium
8Economy shop/bank/activitiesVery highHigh
9Settings change-history + config export/importHighMedium
10Autoresponder + welcome DMMediumLow-Med
11RSS + Reddit alert platformsMediumMedium
12Stream-end options (delete/custom card, duration, peak viewers, VOD link)MediumLow-Med
13Unified streamer-alerts dashboard page + crosspost + auto-threadsMediumMedium
14Save-model unification + global settings searchMediumMedium
15Events/RSVP module, multi-starboard, slash custom commands, seasonsMediumHigh

Key files referenced throughout: bot/src/streamer-alerts/{registry,poller,announce}.js, app/Http/Controllers/{Twitch,YouTube,Kick,TikTok}Controller.php, config/api.php, app/Services/Webhooks/WebhookDispatcher.php, bot/src/economy/engine.js, bot/src/levelling/, bot/src/welcome/image.js, bot/src/giveaways/requirements.js, config/premium.php, config/team-permissions.php, resources/js/dashboard-helpers.js.

Phantom is a product of Hydra Labs. The bot is run as a managed service; you do not need to host it yourself.