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.jsactions, 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):
- Install
@sentry/vue(or@sentry/browser) and configure with the project DSN. - Add a Vue
errorHandlerthat forwards to Sentry. - Upload source maps in CI to Sentry's API; remove from served
dist/. - Add
errorCapturedlifecycle to top-level layout components for component-level errors. - 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):
- Install
web-vitals(~2 KB). - Send each metric via GTM (already configured) to GA, or to Sentry's RUM if Sentry is adopted.
- Add Lighthouse-CI to GitHub Actions on PR; track regressions.
WC-OBS-3 — Production console logging¶
Severity: Low–Medium.
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.mdor01-local-setup.md. - If not intended, delete
plugins/fullstory.js,plugins/hotjar.js,plugins/hotjar2.js, and removeLOGROCKET_PROJECT_IDfrom.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-IDcorrelation header. - Add
noConsoleESLint 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