Pular para o conteúdo
He4rt / Docs
Toggle sidebar
Interno noindex

Referência técnica — acessível, mas fora dos buscadores.

Discord
Engenharia Leitura · 4 min Panel Admin
Aceito
19/05/2026 documento interno · noindex

Discord Dashboard Architecture

Deciders: danielhe4rt danielhe4rt

Status: Accepted Date: 2026-05-19 Deciders: danielhe4rt

Context

The He4rt Developers community needs visibility into Discord activity patterns for two purposes:

  1. Scheduling events — knowing when the community is most active (day-of-week × hour) to pick optimal times for lives, workshops, and meetings
  2. Measuring community health — tracking whether engagement (messages, voice, unique users) is growing or declining over time

The data already exists in the messages and voice_messages tables (from the activity module), but there is no way to visualize trends, compare periods, or identify peak hours without running raw SQL.

Decision

Dashboard structure

A single Filament Page (DiscordDashboard) under a new MarketingCluster, with the following widgets top-to-bottom:

Widget Purpose Implementation
Stats overview Quick KPIs with sparklines Filament StatsOverviewWidget with ->chart()
Period breakdown Rolling comparison between sub-periods Custom Blade with 5 switchable views (summary, table, cards, bars, donut)
Activity timeline Daily trend over the full range Chart.js line chart (msgs + voice + users)
Heatmap Peak hours identification x-he4rt::dashboard.heatmap component (SVG, week variant)
Activity by DOW Best day-of-week for events x-he4rt::dashboard.bar-chart with stacked mode toggle (All/Msgs/Voice)
Top channels Most active channels x-he4rt::dashboard.bar-chart ranked

Rolling comparison pattern

Instead of fixed calendar quarters, the selected time range is subdivided into equal sub-periods:

Range Subdivision
90d 3 × 30d
60d 2 × 30d
30d 4 × ~7d
14d 2 × 7d
7d 7 × 1d
1d 24 × 1h

Why: Rolling comparison adapts to any range and avoids the problem of incomplete quarters. Stats cards show last sub-period vs previous; period breakdown shows all sub-periods.

Query layer

Each widget has a dedicated final readonly query class with a builder() method, located in Marketing/Discord/Queries/. The Page instantiates queries and passes results to the view. Heatmap data for messages and voice comes from separate query classes — the Page combines them.

PeriodStats is a single class with private methods per metric to keep cohesion while avoiding class explosion.

Summary view design

The period breakdown's "summary" mode uses a 50/50 layout:

Channel names deferred

Channel IDs are stored as Discord snowflakes with no name resolution. Dedicated Discord entity tables (channels, roles, members) are a separate future initiative. The dashboard shows channel IDs for now.

Timezone

Fixed to America/Sao_Paulo. The community is Brazilian and there is no use case for other timezones. Consistent with the existing Meeting Showcase page.

Component extensions

The x-he4rt::dashboard.bar-chart Blade component was extended with backward-compatible props:

All existing usages remain unaffected.

Alternatives Considered

A — Filament Widgets for everything

Use ChartWidget and StatsOverviewWidget for all visualizations. Rejected because: heatmap has no native widget, period breakdown needs 5 switchable views that don't map to any widget, and mixing native widgets with custom Blade creates inconsistent layout control.

B — Fixed quarter comparison

Compare Q1 vs Q2 vs Q3 with calendar-aligned periods. Rejected because: the current quarter is always incomplete, making the comparison misleading. Rolling comparison is more flexible and avoids this problem.

C — He4rt design system components for stats

Use x-he4rt::dashboard.stat-card instead of Filament's StatsOverviewWidget. Rejected because: Filament's widget has built-in sparklines via ->chart(), lazy loading, and polling — reimplementing these in custom Blade would be wasted effort.

Consequences

Positive

Negative

Risks