Design rationale
Built to be safe in front of strangers
The product and technical design document is the single source of truth for this project. This page is a rendering of its decisions: goals, data flow, the read-only posture, key handling, the theme plugin architecture and the acceptance approach.
Goals
What the product must do
One-line embed
Console-level fidelity
URL-driven view
Graceful failure
Key flexibility
Observable runtime
Non-goals
What is explicitly out of scope
- No user system, SSO or RBAC, and no key issuance or rotation. Key risk stays with the owner.
- No dynamic switching across multiple SigNoz backends: the single upstream is fixed by SIGNOZ_BASE_URL, which prevents SSRF.
- No domain allowlist. The embed is fully public: anyone holding the link can view.
- No dashboard editing, creation, deletion, locking or alert management.
- No dashboard list, playlists or snapshot export.
Phase 1 chrome decision: hide alerts, hide the lock switch and show annotations read-only.
Read-only
Default deny, enforced at the proxy
Read-only is not a UI state; it is an allowlist in the backend. The frontend implements no editing entries, and the proxy forwards only dashboard reads, the v3/v4/v5 query_range family, substitute_vars and the two variable-candidate endpoints. Everything else under /api/* returns 403, including every write interface.
This split matters because the embed is public. A hidden button is still one request away; a blocked route is not.
Key handling
Effective key, memory only
The effective key resolves as x-embed-api-key ?? URL apiKey ?? env.SIGNOZ_API_KEY. The browser keeps the URL key in memory only; it is never written to localStorage, a cookie or serialized back into the URL unless the caller put it there.
Logs and documents may only contain the key source and the first 8 characters of a hash. Query strings are redacted before serialization, so plaintext keys cannot land in logs, bug reports or commits.
Frontend
Core plus a theme plugin architecture
The frontend is split into core/ (stable: routing, auth context, data fetching, time and variables, replaceState, empty-state mapping), signoz/ (query semantics), and themes/<name>/.
A theme implements four components: Tokens, Toolbar, WidgetCard and ErrorState. The shadcn theme (default) uses Tailwind and Recharts; the legacy theme uses antd and ECharts. Unknown theme values fall back to shadcn in one registry lookup.
The rule that keeps this honest: a new theme adds a folder and one registry line, and never touches core. Theme branches inside core are treated as bugs and refactored back to the contract.
Process
Docs first, then code
Any design change (URL params, proxy matrix, trim list, env vars, error codes, deployment shape) updates the design document before the code, and a code change without the document update is invalid. Pitfalls found while developing or debugging are appended as rows to a single bug-track file with fixed columns.
This is deliberately boring: it keeps one source of truth, one TODO list and one pitfall log, so both humans and agents can audit why a decision exists.
Compatibility
Pin the API surface, do not copy the vendor
SigNoz v0.97.0 query semantics are the target. The proxy passes through the v3/v4/v5 query_range APIs and variable endpoints without validating unknown fields, so upstream payloads evolve safely.
The earlier route of copying the SigNoz frontend verbatim was abandoned: the dependency closure and provider-chain cost were too high and it conflicted with the theme extension goal. The vendor snapshot is read-only comparison material only, never built and never copied into the runtime.
Acceptance
Fixed smoke dashboards and a matrix
Four dashboards on the test backend anchor the acceptance runs: a System Overview smoke dashboard, a Kubernetes dashboard with QUERY variables, tables and clickhouse panels, a Postgres dashboard with DYNAMIC variables, and an Elasticsearch dashboard with formulas.
The matrix covers: no key with env default, wrong key, wrong id, full params and replaceState, upstream outage with self-healing retry, iframe-resizer wired or not, Chrome 108, read-only enforcement, health and metrics without plaintext keys, dozens of panels, and unknown theme fallback.
Timeline
Milestones
Proxy foundation
DoneMonorepo skeleton, NestJS /api/signoz/* passthrough, /healthz and /metrics, curl proxy matrix green against a real v0.97.0 backend.
Embed app redo
Donecore/ routing, auth, fetching, time and variables, replaceState and empty-state mapping; signoz/ query semantics; legacy theme; theme registry fallback.
TanStack Query v5
DoneSWR updates, request dedup, placeholder-driven no-flash loading, exponential-backoff retry and focus/reconnect suppression.
shadcn theme
In progressDefault theme with Tailwind and Recharts, implementing the same ThemeModule contract as legacy. Visual polish is ongoing.
Distribution and docs site
DoneGitHub Actions image publish to Docker Hub plus this vinext + Magic UI website with intro, docs and design routes.
Risks
Known risks and mitigations
Full-permission keys plus public iframes invite abuse.
Documented warnings, 120 req/min/IP throttle, refresh floor of 10s, and a recommendation to use read-only short-lived keys.
Theme sprawl: themes leaking branches into core.
A new theme only adds themes/<name>/ plus one registry line. When theme conditionals appear in core, they are refactored back to the contract.
iframe-resizer height jitter under StrictMode and overlays.
lowestElement strategy plus debounce, with internal scroll as the degraded fallback.
Marketing site toolchain breaking the shipped image.
website/ is an isolated pnpm project with its own lockfile; the Docker image and root build never include it.