Skip to content

Observability

Status: Audit v0.1 (2026-05-09).

1. Inventory

Tool / capability Wired? Source
Error tracking (Sentry / Bugsnag / Rollbar) No No package in deps; no plugin file uses these names
RUM (Sentry RUM / Datadog / SpeedCurve) No Same
Analytics Yes — Google Tag Manager (@nuxtjs/gtm) nuxt.config.js:268-284
Microsoft Clarity (session replay + heatmaps) Yes nuxt.config.js:23-28; plugins/clarity.js
FullStory (session replay) No (plugin file exists but is not registered) plugins/fullstory.js exists; not in nuxt.config.js → plugins
Hotjar No (plugin files exist but are not registered) plugins/hotjar.js, plugins/hotjar2.js exist; not registered
LogRocket No (LOGROCKET_PROJECT_ID env var exists; no plugin file or init code) .env includes LOGROCKET_PROJECT_ID; no usage site
FirstPromoter (affiliate tracking) Yes nuxt.config.js:30-44; cid 27t8fy1e
Web Vitals RUM No No web-vitals package; no manual reporting
Source-map upload to error tracker No (no error tracker; no upload step in CI) .github/workflows/dev_app.yml does not upload source maps
Performance monitoring No (Lighthouse not run in CI) Same
Feature flag system No No LaunchDarkly / Statsig / Flagsmith / homegrown observed
Console logging in production Yes (46 console.* references in src) grep -rn "console\." pages components store middleware \| wc -l = 46

2. Findings

WC-OBS-1 — No client-side error tracking

Severity: HIGH.

The web client has no error tracking. JavaScript exceptions in production are:

  • Silent (caught by try/catch in store/api.js actions, then dropped)
  • Visible in the user's devtools console (which the user doesn't open) but not reported back
  • Surfaced via the catch-all logout-and-redirect path in middleware/redirect.js (which conflates auth issues with arbitrary errors)

For a B2B SaaS product, this is a critical observability gap. Customers report bugs by emailing support; the engineering team finds out about systemic issues only when many users complain. Mean time to detect for any production frontend bug is hours-to-days at best.

Recommendation (Phase 0):

  1. Install @sentry/vue (or @sentry/browser) and configure with the project DSN.
  2. Add a Vue errorHandler that forwards to Sentry.
  3. Upload source maps in CI to Sentry's API; remove from served dist/.
  4. Add errorCaptured lifecycle to top-level layout components for component-level errors.
  5. Configure release tagging — every Sentry event should know the deploy SHA.

Estimated effort: 1 week, including team training on Sentry alerts.

WC-OBS-2 — No Real User Monitoring of performance

Severity: HIGH.

Microsoft Clarity provides session replay and heatmaps but does not collect Core Web Vitals.

grep "web-vitals" package.json → empty.

LCP, FID, CLS, INP, TBT for production users are unknown. Lighthouse-CI is not configured.

Recommendation (Phase 0):

  1. Install web-vitals (~2 KB).
  2. Send each metric via GTM (already configured) to GA, or to Sentry's RUM if Sentry is adopted.
  3. Add Lighthouse-CI to GitHub Actions on PR; track regressions.

WC-OBS-3 — Production console logging

Severity: Low–Medium.

grep -rn "console\." pages components store middleware 2>/dev/null | wc -l
# 46

46 console.* references in source code. These will run in production browsers, with whatever data they happen to log (sometimes sensitive — auth state, account IDs, etc.). Mirrors the backend audit's console.log finding.

Recommendation (Phase 0): sweep console.log calls. Either remove or wrap in if (process.env.NODE_ENV !== 'production'). Add ESLint rule no-console (with warn/error allowed) to prevent regressions.

WC-OBS-4 — Unwired observability plugins

Severity: Low.

plugins/fullstory.js is a complete FullStory init script with hardcoded org ID o-1C5EVB-na1 but is not registered in nuxt.config.js. Same for plugins/hotjar.js and plugins/hotjar2.js. LOGROCKET_PROJECT_ID is in .env but no LogRocket initialisation code exists.

This is dead code. Either wire them up or delete them. They're confusing — a new developer reading the repo could believe FullStory is active.

Recommendation (Phase 0a):

  • If FullStory / Hotjar / LogRocket are intended, wire them; document org IDs / project IDs in 08-integrations.md or 01-local-setup.md.
  • If not intended, delete plugins/fullstory.js, plugins/hotjar.js, plugins/hotjar2.js, and remove LOGROCKET_PROJECT_ID from .env.

[VERIFY-OBS-1]: team — what is the intent for FullStory, Hotjar, LogRocket? Were they trial-installed and never finished?

WC-OBS-5 — Source maps not uploaded

Severity: Medium.

(Cross-ref build-and-deploy.md § WC-BD-1.) Production source maps are not generated and not uploaded to any service. Stack traces are minified and unusable.

Recommendation: add the source-map upload step to CI when Sentry is added (Phase 0).

WC-OBS-6 — No feature flag system

Severity: Low–Medium.

No LaunchDarkly / Statsig / Flagsmith / Unleash. The codebase relies on Git-branch-based feature delivery: a feature is either merged-and-on or unmerged-and-off. There is no per-user / per-account / canary flag mechanism.

For a multi-tenant SaaS, this is a meaningful gap. Rolling out a risky feature requires either a full deploy or per-user backend gating (which the frontend would honour via a backend-driven /me field).

[VERIFY-OBS-2]: does the backend currently expose any per-account feature gates that the frontend reads?

Recommendation (Phase 1): evaluate Flagsmith (open-source, self-hostable) or LaunchDarkly (commercial) for canary rollouts and instant kill-switch.

WC-OBS-7 — Analytics

GTM is configured (@nuxtjs/gtm), with pageTracking: true (nuxt.config.js:278). The GTM container ID is GTM-KBZLX362 (default if GTM_ID env unset).

This means:

  • Page views are auto-tracked.
  • Custom events must be pushed via this.$gtm.push({ event: '...' }). [VERIFY-OBS-3] how many call sites push events?
  • The GTM container is shared across Microsoft Clarity, possibly Google Analytics 4, and possibly Google Ads conversion tracking. The actual list of tags is in the GTM workspace, not in the repo.

3. Microsoft Clarity

nuxt.config.js:23-28 adds an inline Clarity init script:

{
  hid: 'clarity',
  innerHTML: `(function(c,l,a,r,i,t,y){...})(window,document,"clarity","script","${process.env.CLARITY_PROJECT_ID || 'u1v818dob2'}");`,
  type: 'text/javascript'
}

The default u1v818dob2 is committed in source. Clarity provides:

  • Session recordings
  • Heatmaps
  • Console-error capture (Microsoft's product does some of this)

Clarity is a partial substitute for proper error tracking: it captures clicks, scrolls, and console errors per session. But it doesn't aggregate, doesn't alert, doesn't produce stack traces with source-mapped frames.

[VERIFY-OBS-4]: has the team used Clarity dashboards to find errors? If yes, document the workflow. If no, treat Clarity as analytics-adjacent and add Sentry for actual error tracking.

4. Logging conventions

There is no central logging utility. Loggers in the codebase:

  • console.log / console.error (46 occurrences)
  • this.$snotify.error(...) / this.$toast.error(...) (user-facing toasts)
  • Server-side logging in Nuxt server middleware (api/index.js) uses no logger — res.status(500).send(...) with no log line

Finding [WC-OBS-8] (Severity: Low): No structured logging. A simple helpers/log.js exporting log.info, log.error that conditionally proxies to Sentry would create a clean injection point and make the console.* cleanup straightforward.

5. Backend correlation

The frontend does not appear to send a correlation ID (e.g., X-Request-ID) on outbound requests.

grep -nE "X-Request-ID\|correlation-id\|trace-id" middleware components 2>/dev/null \| head → likely empty.

[VERIFY-OBS-5] confirm. If absent: when a user reports an issue, the support engineer cannot easily correlate the user-side report with backend logs.

Recommendation (Phase 0/1): generate a UUID per session, attach as X-Request-ID header in middleware/axios.js. Backend logs already index by this; the frontend sends it.

6. Recommendations — phased

Phase 0a (this week)

  • Decide intent for FullStory, Hotjar, LogRocket. Delete unwired plugins or wire them up.
  • Document the GTM tag inventory (in GTM, not in repo) — what's currently firing in production?

Phase 0 (months 0–3)

  • Install Sentry, configure errorHandler, errorCaptured, axios response-interceptor → Sentry, source-map upload from CI.
  • Install web-vitals, send via GTM/Sentry RUM.
  • Sweep console.* — remove or guard.
  • Add Lighthouse-CI in PR checks (informational).
  • Add X-Request-ID correlation header.
  • Add noConsole ESLint rule (warn).

Phase 1 (months 3–9)

  • Adopt feature-flag system (Flagsmith or LaunchDarkly).
  • Structured logging helper (helpers/log.js).
  • Sentry release tagging tied to deploy SHA.

Phase 2 (months 9–18)

  • Combine Sentry + backend tracing (the backend audit may have similar findings — cross-component observability narrative goes into the master TDD).

7. Open questions

Tracked in ./verify-markers.md:

  • [VERIFY-OBS-1] FullStory/Hotjar/LogRocket intent
  • [VERIFY-OBS-2] Backend feature-flag exposure
  • [VERIFY-OBS-3] GTM custom-event call site count
  • [VERIFY-OBS-4] Clarity workflow
  • [VERIFY-OBS-5] X-Request-ID header presence