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
Real User Monitoring. Collects page load timing, interaction delays, network quality, and navigation patterns from actual users. Aggregates by mini-app, page, device, and connection type. Privacy-respecting — no PII, only performance metrics. Competitors: Datadog RUM, Vercel Analytics.
View the full component source code below.
"use client"
import * as React from "react"
/* ═══════════════════════════════════════════════════════════════
NYUCHI RUM — N8 Assurance (Z-axis)
Real User Monitoring. Privacy-first. No PII.
═══════════════════════════════════════════════════════════════ */
export interface RumEvent {
type: "pageload" | "interaction" | "navigation" | "network" | "error"
timestamp: string
url: string
miniApp?: string
/** Device category derived from viewport */
device: "mobile" | "tablet" | "desktop"
/** Connection type from NetworkInformation API */
connection?: "4g" | "3g" | "2g" | "slow-2g" | "wifi" | "unknown"
metrics: Record<string, number>
}
export interface RumConfig {
/** Sample rate 0-1 */
sampleRate?: number
/** Flush interval in ms */
flushInterval?: number
/** Endpoint to POST events to */
endpoint?: string
/** Custom event handler instead of posting */
onEvent?: (event: RumEvent) => void
onFlush?: (events: RumEvent[]) => void
}
// BACKLINKS: RUM events are enriched with data-portal attributes
// to link performance metrics back to specific components in the design portal.
class RumCollector {
private events: RumEvent[] = []
private config: Required<RumConfig>
private flushTimer?: ReturnType<typeof setInterval>
constructor(config: RumConfig = {}) {
this.config = {
sampleRate: config.sampleRate ?? 0.1,
flushInterval: config.flushInterval ?? 30000,
endpoint: config.endpoint ?? "https://design.nyuchi.com/api/rum",
onEvent: config.onEvent ?? (() => {}),
onFlush: config.onFlush ?? (() => {}),
}
if (Math.random() > this.config.sampleRate) return
this.init()
}
private init() {
if (typeof window === "undefined") return
// Page load
window.addEventListener("load", () => {
const nav = performance.getEntriesByType("navigation")[0] as PerformanceNavigationTiming
if (nav) {
this.record({ type: "pageload", metrics: {
dns: nav.domainLookupEnd - nav.domainLookupStart,
tcp: nav.connectEnd - nav.connectStart,
ttfb: nav.responseStart - nav.requestStart,
domLoad: nav.domContentLoadedEventEnd - nav.fetchStart,
fullLoad: nav.loadEventEnd - nav.fetchStart,
transferSize: nav.transferSize,
}})
}
})
// Navigation
const originalPushState = history.pushState
history.pushState = (...args) => {
originalPushState.apply(history, args)
this.record({ type: "navigation", metrics: { timestamp: performance.now() } })
}
// Flush on interval
this.flushTimer = setInterval(() => this.flush(), this.config.flushInterval)
// Flush on page hide
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") this.flush()
})
}
record(partial: Omit<RumEvent, "timestamp" | "url" | "device" | "connection">) {
const event: RumEvent = {
...partial,
timestamp: new Date().toISOString(),
url: window.location.pathname,
device: window.innerWidth < 640 ? "mobile" : window.innerWidth < 1024 ? "tablet" : "desktop",
connection: (navigator as any).connection?.effectiveType || "unknown",
}
this.events.push(event)
this.config.onEvent(event)
}
private async flush() {
if (this.events.length === 0) return
const batch = [...this.events]
this.events = []
this.config.onFlush(batch)
try { await fetch(this.config.endpoint, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(batch), keepalive: true }) } catch {}
}
destroy() { if (this.flushTimer) clearInterval(this.flushTimer) }
}
let _rum: RumCollector | null = null
export function initRum(config?: RumConfig): RumCollector {
if (!_rum) _rum = new RumCollector(config)
return _rum
}
export function useRum(config?: RumConfig) {
React.useEffect(() => { const rum = initRum(config); return () => rum.destroy() }, [])
}
npx shadcn@latest add https://mzizi.dev/api/v1/ui/mzizi-rumFetch this component's metadata and source code from the registry API.
/api/v1/ui/mzizi-rum