nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Structured error collection, deduplication, and blast radius analysis. Catches errors from L5 error boundaries, enriches them with component backlinks (data-portal), calculates which mini-apps and layers are affected. Competitors: Sentry, Datadog Error Tracking.
No interactive demo is registered for this component yet — the source is shown directly.
"use client"
import * as React from "react"
/* ═══════════════════════════════════════════════════════════════
NYUCHI ERROR TRACKER — N8 Assurance (Z-axis)
Structured error collection + blast radius analysis.
═══════════════════════════════════════════════════════════════ */
export interface TrackedError {
id: string
message: string
stack?: string
componentName?: string
portalUrl?: string
layer?: number
miniApp?: string
url: string
timestamp: string
count: number
firstSeen: string
lastSeen: string
/** Components in the same render tree that might be affected */
blastRadius: string[]
severity: "low" | "medium" | "high" | "critical"
resolved: boolean
}
export interface ErrorTrackerConfig {
/** Max errors to keep in memory */
maxErrors?: number
/** Group similar errors (dedup) */
dedup?: boolean
/** Auto-resolve after N minutes without recurrence */
autoResolveMinutes?: number
onError?: (error: TrackedError) => void
onCritical?: (error: TrackedError) => void
}
// L9 INTEGRATION: Critical errors are reported to Fundi via GitHub issues
// import { getFundiReporter } from "@/lib/fundi/nyuchi-fundi-reporter"
// On critical error: getFundiReporter().report({ component, layer, severity, errorType, source: "error-tracker", ... })
class ErrorTrackerCore {
private errors = new Map<string, TrackedError>()
private config: Required<ErrorTrackerConfig>
constructor(config: ErrorTrackerConfig = {}) {
this.config = {
maxErrors: config.maxErrors ?? 500,
dedup: config.dedup ?? true,
autoResolveMinutes: config.autoResolveMinutes ?? 60,
onError: config.onError ?? (() => {}),
onCritical: config.onCritical ?? (() => {}),
}
}
track(error: Error, context?: { componentName?: string; layer?: number; miniApp?: string }) {
const key = this.config.dedup ? `${error.message}:${context?.componentName || "unknown"}` : Date.now().toString()
const existing = this.errors.get(key)
// Find blast radius via DOM backlinks
const blastRadius = this.findBlastRadius(context?.componentName)
// Determine severity
const severity = this.classifySeverity(error, context, blastRadius)
if (existing) {
existing.count++
existing.lastSeen = new Date().toISOString()
existing.resolved = false
if (severity === "critical") this.config.onCritical(existing)
return existing
}
const portalEl = context?.componentName ? document.querySelector(`[data-slot="${context.componentName}"]`) : null
const tracked: TrackedError = {
id: key,
message: error.message,
stack: error.stack,
componentName: context?.componentName,
portalUrl: portalEl?.getAttribute("data-portal") || undefined,
layer: context?.layer,
miniApp: context?.miniApp,
url: typeof window !== "undefined" ? window.location.pathname : "",
timestamp: new Date().toISOString(),
count: 1,
firstSeen: new Date().toISOString(),
lastSeen: new Date().toISOString(),
blastRadius,
severity,
resolved: false,
}
this.errors.set(key, tracked)
this.config.onError(tracked)
if (severity === "critical") this.config.onCritical(tracked)
// Evict old errors
if (this.errors.size > this.config.maxErrors) {
const oldest = [...this.errors.entries()].sort((a, b) => a[1].lastSeen.localeCompare(b[1].lastSeen))[0]
if (oldest) this.errors.delete(oldest[0])
}
return tracked
}
private findBlastRadius(componentName?: string): string[] {
if (!componentName || typeof document === "undefined") return []
const el = document.querySelector(`[data-slot="${componentName}"]`)
if (!el) return []
const parent = el.closest("[data-slot]")
const siblings = parent ? parent.querySelectorAll("[data-slot]") : []
return Array.from(siblings).map(s => s.getAttribute("data-slot") || "").filter(s => s && s !== componentName)
}
private classifySeverity(error: Error, ctx?: { layer?: number }, blastRadius?: string[]): TrackedError["severity"] {
if (ctx?.layer === 1 || ctx?.layer === 4) return "critical" // Token or safety layer failure
if (ctx?.layer === 7) return "high" // Shell failure
if ((blastRadius?.length || 0) > 10) return "high" // Wide blast radius
if (error.message.includes("TypeError") || error.message.includes("Cannot read")) return "medium"
return "low"
}
getErrors(): TrackedError[] { return [...this.errors.values()] }
getUnresolved(): TrackedError[] { return [...this.errors.values()].filter(e => !e.resolved) }
resolve(id: string) { const e = this.errors.get(id); if (e) e.resolved = true }
clear() { this.errors.clear() }
}
/** Global error tracker singleton */
let _tracker: ErrorTrackerCore | null = null
export function getErrorTracker(config?: ErrorTrackerConfig): ErrorTrackerCore {
if (!_tracker) _tracker = new ErrorTrackerCore(config)
return _tracker
}
/** React hook to access error tracker */
export function useErrorTracker(config?: ErrorTrackerConfig) {
const tracker = React.useMemo(() => getErrorTracker(config), [])
return tracker
}
The variants, sizes, and props surfaced by the registry. Each is sourced from the Supabase component_docs table.
Hit the registry API live and see the JSON the shadcn CLI consumes when it installs this component.
/api/v1/ui/mzizi-error-trackernpx shadcn@latest add https://mzizi.dev/api/v1/ui/mzizi-error-trackerlib/mzizi-error-tracker.ts