Skip to content
BurnerByte

frontend

Frontend Overview

Next.js frontend architecture, pages, components, and keyboard shortcuts.

Tech Stack

LibraryPurpose
Next.js 16App Router, RSC, file-based routing
React 19UI rendering
shadcn/uiComponent library (Radix + Tailwind)
Tailwind CSS 4Utility-first styling with OKLCH color tokens
ZustandClient state (auth, org/team selection)
TanStack Query v5Server state, caching, optimistic updates
Recharts 3Dashboard and analytics charts
SonnerToast notifications with severity icons
next-intl 4Internationalization scaffolding (English is the only bundled locale)

Pages

Dashboard
Dashboard
RouteDescription
/Landing page for signed-out visitors; inbox creation hero + active inbox grid once signed in
/tryPublic demo inbox — no account required, gated on the demo_enabled platform setting
/dashboardAdmin dashboard — stats, charts, activity, quick links
/inboxesRedirect to /
/domainsDomain management with DNS verification
/domains/[domainId]Domain detail with team assignments
/teamsTeam list with member/domain/inbox counts
/webhooksWebhook management with delivery logs
/api-keysScoped API key management with permission picker
/auditTimeline audit log with filters and CSV export
/analyticsOrg/team analytics with charts and insights
/settingsOrg settings, users, roles, SSO, system config
/adminRedirect to /settings
/profileUser profile and connected accounts
/profile/sessionsActive session list with per-session revoke
/profile/deleteAccount deletion flow
/inboxes/[id]Inbox detail with real-time email list (WebSocket)
/email/[emailId]Standalone email detail with headers and spam score
/loginSign in with password or SSO
/registerAccount creation with password strength
/forgot-passwordPassword reset request
/reset-passwordPassword reset with emailed token
/verify-emailEmail address verification
/inviteOrganization invitation acceptance
/setupFirst-run setup wizard
/onboardingMandatory org-creation flow — forced redirect for users without an org (system admins exempt)

Keyboard Shortcuts

KeyActionScope
⌘K / Ctrl+KOpen command paletteGlobal
?Show keyboard shortcuts helpGlobal (outside inputs)
nCreate a new inboxHome (/), outside inputs
j / Next email in listInbox detail (/inboxes/[id])
k / Previous email in listInbox detail (/inboxes/[id])
EscDeselect the current emailInbox detail (/inboxes/[id])

Dialogs close on Esc via the Radix primitive, not a registered shortcut.

UX Patterns

Every data page consistently uses:

  • Loading skeletons — Structural placeholders matching the final layout
  • Error statesErrorState component with contextual message and retry button
  • Empty statesEmptyState with a concise message and an optional primary action
  • No-org stateNoOrgState on org-scoped pages when the user has no organization (CTA to create one or request an invite)
  • No-team stateNoTeamState on team-scoped pages (webhooks, API keys) when the org has no teams yet
  • Forced onboardinguseOrgBootstrap hook redirects zero-org users to /onboarding server-authoritatively (system admins exempt)
  • Confirmation dialogsConfirmDialog for all destructive actions
  • PaginationPagination component with page numbers
  • Toast notifications — Sonner with severity icons (success, error, warning, info)
  • Optimistic updates — TanStack Query mutations with rollback on error
  • Pull-to-refresh — Touch gesture on the home inbox grid (/)

Key Components

ComponentPurpose
AppShellLayout wrapper with sidebar (admin) or top nav (member)
SidebarCollapsible navigation with Lucide icons and org card
CommandPalette⌘K quick navigation with search
NotificationCenterReal-time notification popover with grouping
LastUpdatedRelative time indicator for data freshness
ProviderIconSSO provider logos (GitHub, Google, Azure, Okta)
LogoConsistent branding component with size variants
PageProgressRoute-change progress bar
OfflineBannerNetwork status indicator
SkipToContentAccessibility skip link

State Management

Zustand Stores

  • auth-store — User session, login/logout, token refresh
  • org-store — Current org, teams, role, permissions

TanStack Query

Server state is managed with TanStack Query v5. Key patterns:

  • Stale times — 30s default, 60s for notifications, 5min for platform settings
  • Refetch on window focus — Enabled globally for fresh data
  • Optimistic updates — Webhooks and API keys use onMutate mutations with rollback on error; the notification center writes the cache directly with setQueryData
  • Cache invalidation — WebSocket messages trigger targeted query invalidation

Command Palette

Press ⌘K to open the command palette for quick navigation. Features:

  • All sidebar routes with matching Lucide icons
  • Action commands (Create Inbox, Sign Out)
  • Recent actions — last 5 executed commands shown when query is empty (persisted to localStorage)
  • Grouped sections (Recent, Navigation, Actions)
  • Fuzzy search with keyboard navigation (↑/↓/Enter)

Mobile Support

  • Sidebar collapses into a slide-out sheet on screens below md breakpoint
  • Responsive grid breakpoints (grid-cols-1 sm:grid-cols-2 lg:grid-cols-3)
  • Table overflow wrappers with horizontal scroll
  • Responsive column hiding on narrow screens
  • Pull-to-refresh on touch devices (home page only)

Internationalization

Strings go through next-intl, but only one locale ships today:

  • web/src/i18n/request.ts declares locales = ["en"], defaultLocale = "en", and an empty rtlLocales list.
  • web/src/i18n/messages/ contains a single en.json, imported statically.
  • There is no middleware.ts, so there is no locale routing, no /[locale] URL prefix, and no Accept-Language negotiation. Adding a locale means adding a messages file, extending locales, and introducing routing middleware.