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.
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.