Rozenite
Experimental — not yet verified against a real running app. Rozenite’s plugin API is young and still moving. This package was built and tested against Rozenite
1.13.0(specifically the Rozenite monorepo commit3d7ab5307da9256e183d3a8dfd4e9bca00ce2960, 2026-06-24, matching the1.13.0release published to npm forrozenite,@rozenite/vite-plugin,@rozenite/plugin-bridge, and@rozenite/metro). Its unit tests (bun run --cwd packages/hakka-rozenite test) cover the pure RN-side bridge logic, the panel store adapter, and the panel component with Rozenite’s client mocked — none of them exercise a real Rozenite messaging channel, a real Metro/Re.Pack plugin auto-discovery pass, or a real React Native DevTools session. Treat this package’s shape as likely to change alongside Rozenite’s, not a stable contract, and run the manual verification steps below yourself before relying on it.
hakka-rozenite renders Hakka’s network inspector as a panel inside React Native DevTools,
via Rozenite. It renders the same
hakka-browser/elements custom elements the rest of the Hakka web
ecosystem uses — <hakka-request-list>, <hakka-request-detail>, <hakka-filter-bar> —
through their typed hakka-browser/react wrappers, fed live from
hakka-react-native’s capture stream.
Reach for this only if you already use React Native DevTools and have Rozenite configured in
your app’s Metro/Re.Pack config. If you don’t, hakka-react-native’s own in-app inspector
(covered in React Native Package) or the
desktop bridge are the non-experimental ways to see RN network traffic.
Install
Section titled “Install”bun add hakka-rozenitehakka-react-native is a peer dependency, and it’s pinned to the exact version
0.1.0 (not a range) — a stricter pin than most peer dependencies in this ecosystem, worth
noting if you’re used to range-based peers elsewhere.
Requires Rozenite already configured in your app’s Metro/Re.Pack config — see Rozenite’s own quick start; this package doesn’t configure that for you, the same way every other Rozenite plugin doesn’t.
Call the hook once, alongside useHakka():
import { useHakkaRozeniteDevTools } from 'hakka-rozenite'
function App() { useHakka() useHakkaRozeniteDevTools() // ...}useHakkaRozeniteDevTools is exported from this package’s react-native entry
(hakka-rozenite/hakka-rozenite/react-native — both resolve to the same build). It’s
lazy-required and a no-op on web, under SSR, and in production bundles, so it’s safe to call
unconditionally rather than gating it behind a dev-only check yourself.
Architecture
Section titled “Architecture”hakka-rozenite/├── rozenite.config.ts # one panel: src/ui/App.tsx├── react-native.ts # lazy RN entry point (no-op in prod/web/SSR)└── src/ ├── shared/protocol.ts # plugin id + event map ├── react-native/bridge.ts # createHakkaRozeniteBridge — RN-side wiring └── ui/ ├── App.tsx # the panel: FilterBar + RequestList + RequestDetail └── panelStore.ts # store adapter fed by client messagesRN side. useHakkaRozeniteDevTools() gets a Rozenite client
(useRozeniteDevToolsClient from @rozenite/plugin-bridge), then
createHakkaRozeniteBridge flushes Hakka.getLogs() as individual request frames,
subscribes to Hakka.onRequest for live ones, and answers the panel’s
get-snapshot/clear messages. It imports Hakka straight from hakka-core, the same thing
hakka-react-native’s own HakkaBridge.ts does for its desktop-bridge integration.
Panel side. App.tsx gets its own Rozenite client, builds a panelStore
(getSnapshot()/subscribe()/clear()/ingest()) that mirrors incoming request/cleared
frames, and passes that store into both <FilterBar store> and <RequestList store> from
hakka-browser/react — those two wire together automatically via hakka-browser/elements’s
shared FilterViewModel/SelectionViewModel singletons. Selecting a row passes the resolved
NetworkRequest object directly into <RequestDetail request>, bypassing
hakka-browser/elements’s request-id-against-shared-store resolution entirely, since this
plugin’s store is never that shared singleton.
Data path: Rozenite messaging, not the desktop bridge hub
Section titled “Data path: Rozenite messaging, not the desktop bridge hub”Captured requests reach the panel over Rozenite’s own useRozeniteDevToolsClient messaging —
not by connecting the panel directly to the Hakka desktop bridge hub
(ws://localhost:8989, Bridge overview’s protocol). Every captured
request is sent as its own client.send('request', ...) call — one frame per request, no
batching, mirroring hakka-react-native’s own desktop-bridge behavior. There’s no separate
pre-connect queue: Hakka.getLogs() is already hakka-react-native’s persistent capture
store, so the bridge reads it directly (flushBacklog()) the moment the client connects.
This has not been load-tested against a real high-volume capture session. If a real app
shows the Rozenite channel struggling under volume, the documented (but unimplemented)
fallback is connecting the panel to the desktop bridge hub instead, reusing
hakka-react-native’s existing HakkaBridge/desktop wire protocol.
What’s read-only today
Section titled “What’s read-only today”This plugin is v0.1.0 and read-only: unlike Rozenite’s own official
@rozenite/network-activity-plugin, it does not yet let you edit a response before it reaches
the app. hakka-core’s mockEngine/ThrottleEngine — already used by
hakka-react-native’s own Mocks/Throttle panels — are the natural next step for this panel, but
they aren’t wired in here yet.
Testing — what’s covered, what needs a real app
Section titled “Testing — what’s covered, what needs a real app”Covered (bun run --cwd packages/hakka-rozenite test, happy-dom + vitest):
react-native/bridge.test.ts— backlog-flush/live-forward/get-snapshot/clearwiring, against a fake Rozenite client and a fakeHakkafacade.ui/panelStore.test.ts— the store adapter’s upsert-by-id mirroring, subscriber fan-out,clear()/ingest()/destroy().ui/App.test.tsx— mounts the real panel withuseRozeniteDevToolsClientmocked; verifies the connecting state, that all three custom elements mount and register, row selection reaching the detail pane, and listener cleanup on unmount.
Not covered — needs a real app with React Native DevTools open:
useHakkaRozeniteDevTools()calling the realuseRozeniteDevToolsClient— its channel depends onglobal.__FUSEBOX_REACT_DEVTOOLS_DISPATCHER__(device) or a livepostMessage-connected parent (panel), neither reproducible in a unit test.- Whether the RN ↔ panel round trip holds up under a real capture session’s volume.
- Whether
rozenite build’s Metro/Re.Pack auto-discovery actually picks this plugin up and mounts its panel in a real React Native DevTools sidebar.
Manual verification steps (do this before treating the integration as done):
- In a Rozenite-enabled RN app (or the Rozenite monorepo’s own playground app), link this
package (and
hakka-browser— for its/reactand/elementssubpaths —hakka-core/hakka-react-nativealongside it). - Call
useHakkaRozeniteDevTools()once, alongsideuseHakka(). - Run with
ROZENITE_DEV_MODE=hakka-rozenite npx react-native start(orexpo start), per Rozenite’s own dev-mode docs, to load this plugin’s panel live instead of a builtdist/. - Open React Native DevTools and confirm a “Hakka” panel appears in the sidebar.
- Trigger some network requests; confirm they appear live in the panel’s request list, and that the detail pane and filter bar behave as expected.
- Click “Clear” in the panel; confirm
Hakka.getLogCount()in the app goes to zero too, not just the panel’s own view.
Known limitations
Section titled “Known limitations”- “Load sample traffic” in the empty-state
<RequestList>only updates the panel’s own local mirror. This plugin has no synthetic demo-data source, soingest()on the store adapter never forwards anything back to the device. - No batching. Every request is its own message frame — see “Data path” above.
- Read-only — no mock/throttle/breakpoint controls in the panel yet (see above).
See also
Section titled “See also”- Components — the custom elements this panel renders.
- React — the typed wrappers this panel uses to render them.
- React Native Package —
hakka-react-native, the capture source this panel is fed from. - Bridge overview — the desktop bridge hub this panel deliberately does not use (see “Data path” above).