frontend — Dashboard SPA
The customer-facing dashboard: live session monitoring, recordings replay, chats/ calls, leads, identity-graph admin, agency portal, billing, and the Nox surfaces.
- Stack: Vue 3 (Composition API) + Vite, Pinia, vue-router, TanStack Vue Query, vee-validate + zod, Socket.IO client, Twilio Video, rrweb, PostHog, Tailwind.
- Dev server:
:4000. The same source is wrapped bydesktop.
Build & release
scripts/bump-version.js drives build:release (patch), build:minor,
build:major. Vite injects __APP_VERSION__, __BUILD_DATE__, __GIT_COMMIT__,
__WHITE_LABEL__. Rollup splits ~14 manual chunks (vue, rrweb, twilio, charts,
quill, …). Containerized via Dockerfile.azure (multi-stage → nginx).
App structure (src/)
main.js Pinia + VueQuery + router + axios interceptors
router/ index.js (50+ routes, guards), admin.js, agency.js
store/ Pinia stores (persisted)
repositories/ API layer — plain async axios fns, grouped by area
composables/ useLiveSocket, useLiveReplayer, useKnoxVoice, usePostHog, …
views/ page components
components/ SessionPlayer (rrweb), form/ (vee-validate wrappers), knox/, …
layouts/ AppLayout (sidebar/header)
config/ env.config.js (API URLs, Stripe, Firebase)
utils/ platform.js (isElectron), socketManager.js, twilioCall.js
State (Pinia)
Stores persist to local/session storage via pinia-plugin-persistedstate. Main
ones: app (user/company/auth/theme/subscription/branding), sessions, chats,
calls, knox, nox* (noxActions, noxInsights, noxSettings,
noxRecentConversations), briefSession, notifications, onboarding,
update (Electron auto-updater).
GHL OAuth flows store auth in sessionStorage instead of localStorage — see the dynamic storage wrapper in
store/app.js.
Data layer
Repository functions in repositories/<area>/ call axios; TanStack Query wraps
them with keys from @lukemorales/query-key-factory (queryKeys.js per area).
QueryClient defaults: 5 min stale, 30 min gc, 1 retry, no refetch-on-focus. The
IDE-open file repositories/admin/identity.js is the identity-graph admin API
(persons, profiles, form submissions, maintenance, GHL reconcile) — note it uses
NDJSON streaming responses with an onProgress callback for long maintenance jobs.
Routing & auth
router/index.js guards: requiresAuth → redirect to /login; role redirects
(admin → /admin, agency → /agency, owner → /dashboard); meta.permission
checked via memberHasPermission(); meta.feature gated against subscription
(appStore.isAllowInPackage); meta.ownerOnly; onboarding redirect. Axios
interceptors attach the bearer token and clear storage + redirect on 401. Electron
uses hash history; web uses HTML5 history.
Realtime
Two sockets: window.main_socket (agent/internal notifications) and
window.socket (calls/chats/sessions). Notable events: update-live-session,
online-session/offline-session, twilio-webrtc-call-response,
new-call-request, new-session-message, session-page-context; emits
agent-available-for-call, call-accepted-by-agent, inbound-takeover events.
useLiveSocket.js and LiveCallListener.vue own the wiring.
Feature areas
| Feature | Where |
|---|---|
| Live sessions | LiveSessionsView.vue + useLiveSocket/useLiveSessionDetails/useLiveReplayer |
| Recorded replay | RecordedSessionsView.vue + components/SessionPlayer/ (rrweb) |
| Twilio video | call panel + utils/twilioCall.js + LiveCallListener.vue |
| Knox voice | views/settings/nox/ + useKnoxVoice + store/knox |
| Identity graph admin | /admin/identity-graph + repositories/admin/identity.js (super-admin) |
| Agency portal | /agency/* |
| Billing | views/packages/* (Stripe) |
| Nox surfaces | settings/nox/ + nox* stores |
Recent additions (2026-07)
- Dashboard restructure —
/dashboardand/reportsrender beta-gated switchers (DashboardHome.vue/ReportsHome.vue, keyed oncompany.agent_k_beta_enabled): beta gets the "Today on Knock Knock" command center (views/Dashboard/Index.vue, tabs Today/Impact/Visitors/Funnel/Campaigns) at/, with the six-tab analytics moved toviews/Reports/Index.vueat/reports; non-beta keeps the old screens./funnelredirects to/dashboard?tab=funnel. - Wallet UI — sidebar wallet pill (
CompanyNavigationSidebar.vue),views/packages/Wallet.vuetransactions page,PackagesTabs.vue(Wallet/Add-ons/Payment Methods),composables/useBalanceAccess.js(now grants full self-service to agency sub-accounts). - Members layout —
views/members/MembersLayout.vuewith People/Teams/Branches tabs. - Playground — public
views/playground/+views/simple-playground/(no-login demo sandbox, shareable), agency lists underviews/agency/{playground,simple-playground}/, admin list with credits column. - PWA — installable with a per-tenant manifest (
App.vue,public/sw.js). - Admin surfaces —
views/admin/StorageMaintenance.vue, cost-tracking unit-economics cards, Nox funnel audit logs + contact trace, identity maintenance panels, visitor-watch History tab, playground credits column. - Startup perf — heavy chunks (charts, Knox tree) deferred out of startup; vite build warnings cleaned.
Recent additions (2026-08)
- Agent K standalone page — Agent K moved from a dashboard tab to its own
/agent-kpage (views/agentk/Index.vue: Feed with channel sub-filters + Reports with drill-down; stage narrative via itsSTAGE_WORDSmap; shared lead/stage formatting incommon/helpers/agentK.js). Settings split into 7 URL-synced tabs (views/settings/ai/agents/AgentK/index.vue— overview / icp / traffic / outreach / channels / delivery / dnc,?tab=+?highlight=), plus a standalone setup route (agent-k-setup→AgentK/Setup.vue) and a pricing modal (PricingModal.vue/PricingTable.vue+useAgentKPricing). - Nox Activity —
views/NoxActivityView.vue(in-app history) andviews/NoxActivityReportView.vue(authed print view — no share tokens). - Session details redesign —
components/sessions/SessionMoreInfoPanel.vue+SessionAgentKOutreach.vue(Agent K outreach shown in the panel). - Engage live visitor —
components/sessions/EngageVisitorModal.vuefrom the live session view; live sessions hide bot traffic by default. vitest is established (src/**/*.test.js): this window addedAgentKInbox.test.js,AgentKPanes.test.js,useLiveSocket.test.js,useLiveReplayer.test.js(+liveSessionTestKit.js),socketManager.reconnect.test.js,clipboard.test.js,ScheduleCallDialog.test.js,NoxTaskHistory.test.js,canvasOrder.test.js, and playground/integration tests. - 2026-08/09 — Calls screen rewritten as rail/thread/contact
(
components/calls/,useCallsFeed.js); Agent K three-pane inbox (views/agentk/); Nox Live standup mode, Task sheet, Scheduled overlay (components/knox/live/),KnoxConfigCard.vue; partner portal (views/partner/— invites, listing editor, sign-up links) and onboardingPartnerStep.vue; admin identity repair screens, Integrations Maintenance, Identity Maintenance cards (CRM smoke, crm_links backfill), Call Duration Backfill;utils/clipboard.js; 20 admin views on reactive route-param query keys; version 1.7.0;Dockerfile.azureon node:24-alpine (npm 10.9.8edgesOutcrash on vitest 5 peers — there is no lockfile by design, so CI re-resolves every build). - Integrations screen split —
views/settings/integrations/Index broken into ~24 per-card components insrc/components/integrations/; the old dashboard Campaigns tab now lives onManyReachCard.vue/ManyReachCampaigns.vue. - Platform APIs (agency) —
views/agency/settings/PlatformApis.vue,PlatformWebhookManager.vue+ deliveries view, andviews/auth/PlatformLoginView.vueat/platform-login/:code. - Partner certification — partner portal
views/partner/+ admin suiteviews/admin/certification/(Queue/Students/Tests/Settings, wallet rewards in dollars). - Push notifications — user push preferences + admin push tester; new
components/form/FormSearchSelect.vue. - Misc UI — Wallet shows Agent K line items; shared
components/DateRangeButton.vue; Quill rich-text standardized across Agent K drafts, Nox drafts, and the email signature editor. - Cross-tab session sync —
utils/sessionChannel.js(BroadcastChannel): stale tabs freeze when another tab switches user or logs out; app-store persist config fixed (field list was silently ignored); axios interceptors moved out ofmain.js. - GHL iframe silent re-auth — 401 inside the GHL iframe re-authenticates via
the stored secret instead of logging out (
views/auth/GoHighLevelAuthView.vue,store/app.js). - Dashboard tabs —
VALID_TABS = ['today', 'impact', 'visitors', 'funnel'](views/Dashboard/Index.vue); Campaigns tab removed; Nox briefing strip removed from the dashboard (Reports still rendersNoxStrip). - Traffic-source labels —
common/helpers/session.js:agent_k→ "Agent K Outreach",manyreach→ "ManyReach Campaign",ghl_backfill→ "CRM Email Link". - Route gates are data-driven —
company.agent_k_beta_enabled,nox_activity_enabled,partner_certification_enabled(+webOwnerOnlymeta); theLINKEDIN_CHANNEL_UIbuild flag was removed.
Analytics
PostHog (prod only, EU host) via usePostHog.js; pageview/pageleave on route
change; start_trial / subscribe events. Meta Pixel on register/onboarding.
Relationship to desktop & widget
Same source as desktop (Electron) — utils/platform.js isElectron() toggles
platform behavior. Widget setup/codegen lives in components/Widget/ and
settings/widget/, but the actual visitor widget is the separate
widget repo.