@hotfyllc/debug-console-rn
v1.1.3
Published
Floating in-app debug console for React Native — captures console logs, network requests (fetch/XHR), and app-defined custom actions. Toggleable via a draggable button.
Readme
@hotfyllc/debug-console-rn
Floating in-app debug console for React Native. Captures console.*
output, intercepts fetch/XHR for network inspection, and exposes
custom action buttons.
Status:
1.0.0— stable.
What you get
- Floating draggable button — toggleable, position persisted in
AsyncStorage. Shows badge with unread error count. - Logs tab — captures all
console.log/info/warn/errorcalls automatically. Search, filter by level, copy to clipboard. - Network tab — intercepts
fetchandXMLHttpRequest. Shows status, method, duration, URL. Tap a request for full headers/body in/out. - Actions tab — host app passes a list of
DebugAction[](label + onPress) for quick triggers (clear cache, force refresh, dump state, etc.).
Zero impact on production: just don't render <DebugConsole /> and the interceptors never install.
Install
npm install @hotfyllc/debug-console-rnPeer dependencies
| Package | Required version |
|---|---|
| react | * |
| react-native | >=0.70.0 |
| @react-native-async-storage/async-storage | >=1.17.0 |
| expo-clipboard | >=6.0.0 |
| lucide-react-native | >=0.300.0 |
| react-native-safe-area-context | >=4.0.0 |
If you're on Expo, all of these (except lucide-react-native) are already
installed in most templates. For bare RN, install them manually.
Usage
Mount once
Render <DebugConsole /> at the root of your app (or anywhere it's
always mounted while the app runs). Best place: just before the screen
tree closes in your root layout.
import { DebugConsole, type DebugAction } from '@hotfyllc/debug-console-rn'
import AsyncStorage from '@react-native-async-storage/async-storage'
const debugActions: DebugAction[] = [
{
label: 'Clear Storage',
onPress: async () => {
await AsyncStorage.clear()
console.warn('AsyncStorage cleared')
},
color: '#EF4444',
},
{
label: 'Force CDN refresh',
onPress: () => fetch('/api/cache-bust', { method: 'POST' }),
},
]
export default function RootLayout() {
return (
<>
{/* your app */}
{__DEV__ && <DebugConsole actions={debugActions} />}
</>
)
}Conditionally enable in production
For builds shipped to testers/QA, you can gate the console behind a flag read from env, install referrer, or any other source:
const debugEnabled =
process.env.EXPO_PUBLIC_DEBUG_CONSOLE === 'true' ||
installedViaDebugReferrer
return (
<>
{/* your app */}
{debugEnabled && <DebugConsole actions={debugActions} />}
</>
)API
<DebugConsole>
interface DebugConsoleProps {
actions?: DebugAction[]
}When mounted:
- Installs
console.*interceptor (logs become entries in the Logs tab; originalconsole.*still works) - Installs
fetchandXHRinterceptors (network requests appear in Network tab; originals still work) - Renders the floating button + tap-to-open panel
DebugAction
interface DebugAction {
label: string
onPress: () => void | Promise<void>
color?: string // hex, default = neutral gray
}NetworkRequest (exported type)
If your app needs to inspect captured requests programmatically, import
the NetworkRequest type. The internal store isn't exposed publicly —
the panel reads it via useSyncExternalStore.
Behavior notes
- Logs are kept in memory only (capped at 1000 entries). Cleared on app reload.
- Network requests cap at 200. Older are dropped.
- No remote logging — the console only displays locally. If you want to ship logs to a backend, use a separate analytics SDK and let this console just be the local lens.
- Performance: interceptors add a thin wrapper around
console,fetch,XHR. Negligible overhead, but if you mount<DebugConsole>in production builds, audit before shipping.
License
UNLICENSED — proprietary. Copyright (c) 2026 Hotfy LLC. All rights reserved. See LICENSE for terms.
