⚠️ ACTIVE DEVELOPMENT This project is under active development. If you encounter any issues, please open an issue on GitHub. Feature requests and suggestions are also highly encouraged! I love to hear what you need!⭐ Please star this repo! We ship updates frequently, and starring helps you stay notified of new features and improvements.
Zero-config mobile dev tools that just work.
A single floating menu gives your entire team instant access to powerful debugging tools—in dev, staging, AND production. No configuration, no complexity. Just install packages and they automatically appear.
npm install @react-buoy/core @react-buoy/env @react-buoy/network
# or: pnpm add / yarn add / bun addimport { FloatingDevTools } from "@react-buoy/core";
function App() {
return (
<>
{/* Your app content */}
<FloatingDevTools environment="local" userRole="admin" />
</>
);
}All installed tools automatically appear in your floating menu. No config needed.
💡 Pro Tip: Install all tools at once:
npm i @react-buoy/{core,env,network,storage,react-query,route-events,debug-borders,highlight-updates}
✨ Zero Configuration – Install packages, they auto-appear. No manual setup.
🏷️ Always-Visible Context – See your environment (dev/staging/prod) and role at a glance.
🔄 Persistent State – Tools remember their position and state through reloads.
📍 Minimizable Interface – Minimize open tools to small floating indicators. Quick-restore with a tap or swipe down to dismiss.
👥 Team-Friendly – Same tools everywhere. Onboard new devs in minutes.
🎨 Beautiful UI – Draggable menu with modal and bottom-sheet views.
🔌 Fully Extensible – Drop in any React component as a custom tool.
Install any combination to customize your dev menu:
| Tool | Package | What It Does | Key Features |
|---|---|---|---|
| 🌍 ENV | @react-buoy/env |
Environment variable inspector | Validation, search, type checking, warnings |
| 📡 Network | @react-buoy/network |
API request monitor | Timeline view, filtering, performance metrics |
| 💾 Storage | @react-buoy/storage |
AsyncStorage/MMKV browser | View/edit/delete, bulk ops, validation |
| ⚡ React Query | @react-buoy/react-query |
TanStack Query devtools | Cache inspector, offline toggle, refetch |
| 🧭 Routes | @react-buoy/route-events |
Route & navigation tracker | Sitemap, stack view, event timeline |
| 🎨 Borders | @react-buoy/debug-borders |
Visual layout debugger | 3 modes, tap-to-inspect labels, smart filtering |
| 🔄 Highlights | @react-buoy/highlight-updates |
Render highlight tracker | Visual re-render detection, render counts, history |
| 🔀 Env Switch | @react-buoy/core |
Environment switcher | Switch between dev/qa/staging/prod environments |
Installation Pattern: All packages follow the same simple pattern:
npm install @react-buoy/{tool-name}
# Peer dependencies auto-detected (e.g., @tanstack/react-query, @react-native-async-storage/async-storage)That's it! Once installed, each tool automatically appears in FloatingDevTools.
📸 View screenshots for each tool
Show preview
Screenshot coming soon
👶 Just Starting?
- Follow the 2-Minute Setup above
- All tools work with zero config
🔧 Need Validation?
- See Configuration below for env var and storage validation
🎨 Building Custom Tools?
- Check out Custom Tools section
📖 Want Deep Dive?
- View detailed package docs (collapsed sections)
<FloatingDevTools environment="local" userRole="admin" />That's all you need! But if you want validation...
If you don't want to show any first-time user hints (clipboard tips, modal hints, onboarding tooltips), you can disable them all with a single prop:
<FloatingDevTools disableHints environment="local" userRole="admin" />import { FloatingDevTools } from "@react-buoy/core";
import type { EnvVarConfig } from "@react-buoy/core";
const requiredEnvVars: EnvVarConfig[] = [
"API_URL", // Just check if exists
{ key: "DEBUG_MODE", expectedType: "boolean" },
{ key: "ENVIRONMENT", expectedValue: "development" },
];
<FloatingDevTools
requiredEnvVars={requiredEnvVars}
environment="local"
userRole="admin"
/>;import type { StorageKeyConfig } from "@react-buoy/core";
const requiredStorageKeys: StorageKeyConfig[] = [
{
key: "@app/session",
expectedType: "string",
description: "User session token",
storageType: "async", // "async" | "mmkv" | "secure"
},
];
<FloatingDevTools
requiredStorageKeys={requiredStorageKeys}
environment="local"
/>;import React from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { FloatingDevTools } from "@react-buoy/core";
import type { EnvVarConfig, StorageKeyConfig } from "@react-buoy/core";
export default function App() {
const queryClient = new QueryClient();
const requiredEnvVars: EnvVarConfig[] = [
"EXPO_PUBLIC_API_URL",
{ key: "EXPO_PUBLIC_DEBUG_MODE", expectedType: "boolean" },
];
const requiredStorageKeys: StorageKeyConfig[] = [
{
key: "@app/session",
expectedType: "string",
storageType: "async",
},
];
return (
<QueryClientProvider client={queryClient}>
{/* Your app content */}
<FloatingDevTools
requiredEnvVars={requiredEnvVars}
requiredStorageKeys={requiredStorageKeys}
environment="local"
userRole="admin"
/>
</QueryClientProvider>
);
}💡 Note: All types (
EnvVarConfig,StorageKeyConfig, etc.) are exported from@react-buoy/core
React Buoy uses automatic package discovery. When you render <FloatingDevTools />, it:
- Checks which
@react-buoy/*packages are installed - Loads only the installed packages (lazy + safe)
- Renders them automatically in the floating menu
No registration, no imports, no config arrays. Just install and go.
Behind the scenes: The core package attempts to require() each plugin. If installed, it loads. If not, it silently skips. This means:
- ✅ Zero config for the 90% use case
- ✅ No crashes from missing packages
- ✅ Automatic updates when you install new tools
Want full control? You can still manually configure tools with the apps prop (see Advanced Configuration).
Any React component can be a dev tool! Perfect for:
- 🚀 Feature flag toggles
- 👤 User impersonation panels
- ✅ QA checklists
- 📊 Analytics dashboards
- 🗄️ Database browsers
- 📱 Push notification testers
import { FloatingDevTools } from "@react-buoy/core";
import type { InstalledApp } from "@react-buoy/core";
// Your custom tool - just a React component
function FeatureFlagsModal({ onClose }) {
return (
<View style={{ padding: 20 }}>
<Text>Feature Flags</Text>
{/* Your UI here */}
<Button title="Close" onPress={onClose} />
</View>
);
}
// Define the tool
const customTools: InstalledApp[] = [
{
id: "feature-flags",
name: "FLAGS",
description: "Toggle feature flags",
slot: "both", // "row" | "dial" | "both"
icon: ({ size }) => <YourIcon size={size} />,
component: FeatureFlagsModal,
props: {},
},
];
// Add to FloatingDevTools
<FloatingDevTools
apps={customTools} // Your custom tools
environment="local"
/>;✨ Auto-discovery still works! Custom tools merge with auto-discovered tools. Same ID = your custom tool overrides.
🌍 Environment Inspector (@react-buoy/env)
Visual health check for your app configuration. Validates environment variables, checks types, and warns about missing/incorrect values.
npm install @react-buoy/env- ✅ Visual validation of required environment variables
- 🔍 Search and filter across all env vars
- 🎯 Type checking (string, number, boolean, object)
⚠️ Clear warnings for missing or incorrect values- 📋 Copy values to clipboard
import { createEnvVarConfig, envVar } from "@react-buoy/env";
import type { EnvVarConfig } from "@react-buoy/core";
const requiredEnvVars: EnvVarConfig[] = createEnvVarConfig([
envVar("API_URL").exists(),
envVar("DEBUG_MODE").withType("boolean").build(),
envVar("ENVIRONMENT").withValue("development").build(),
]);📡 Network Inspector (@react-buoy/network)
Real-time network request monitoring with timeline view, detailed inspection, and performance stats.
npm install @react-buoy/network- 📊 Timeline view of all network requests
- 🔍 Detailed request/response inspection with JSON viewer
- ⚡ Performance metrics and timing breakdown
- 🎛️ Filter by status, method, URL patterns
- 📋 Copy request details (curl, JSON, etc.)
- 🔴 Highlight failed requests
💾 Storage Explorer (@react-buoy/storage)
Real-time storage browser for AsyncStorage, MMKV, and SecureStore with live updates and bulk operations.
npm install @react-buoy/storage
npm install @react-native-async-storage/async-storage # peer dependency
npm install react-native-mmkv # optional - for MMKV support- 🗂️ Browse all AsyncStorage, MMKV, and SecureStore data
- ✏️ Edit storage values in real-time
- 🗑️ Bulk delete operations
- 🔍 Search and filter storage keys
⚠️ Validation for required storage keys- 📋 Copy keys/values
- AsyncStorage: React Native standard (auto-detected)
- MMKV: Encrypted, faster alternative (requires registration)
- SecureStore: iOS Keychain / Android Keystore (coming soon)
MMKV instances need to be manually registered:
import { createMMKV } from "react-native-mmkv";
import { registerMMKVInstance } from "@react-buoy/storage";
// Create your MMKV instances
export const storage = createMMKV({ id: "mmkv.default" });
export const authStorage = createMMKV({
id: "auth.storage",
encryptionKey: "your-encryption-key",
});
// Register them with the storage dev tool
try {
registerMMKVInstance("mmkv.default", storage);
registerMMKVInstance("auth.storage", authStorage, { encrypted: true });
} catch {
// Storage package not installed - that's fine
}Why? react-native-mmkv v4 uses read-only exports which prevents automatic detection. Manual registration is a one-time setup per instance.
Note: Registration is safe in production - it only takes effect when <FloatingDevTools /> is rendered.
⚡ React Query DevTools (@react-buoy/react-query)
TanStack Query devtools adapted for mobile with query explorer, cache manipulation, and offline toggle.
npm install @react-buoy/react-query
npm install @tanstack/react-query # peer dependency (v5+)Wrap your app with QueryClientProvider:
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { FloatingDevTools } from "@react-buoy/core";
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* Your app */}
<FloatingDevTools environment="local" />
</QueryClientProvider>
);
}- 🔍 Query explorer with real-time data
- 🗂️ Cache inspection and manipulation
- 📊 Query performance metrics
- 🔄 Manual query refetching and invalidation
- 📶 WiFi Toggle - Simulate offline mode
- 🎨 Query state visualization (loading, error, success)
🧭 Route Events (@react-buoy/route-events)
Comprehensive route tracking and visualization for Expo Router applications. Monitor route changes, explore your app's sitemap, and visualize the navigation stack.
npm install @react-buoy/route-events
npm install expo-router @react-navigation/native # peer dependencies- 🗺️ Route Sitemap - Browse all routes with search
- 📊 Event Timeline - Chronological route changes
- 🏗️ Navigation Stack - Real-time stack visualization
- 🔍 Event Inspection - Detailed params, segments, timing
- 🎯 Filtering - Filter by pathname patterns
- ⏱️ Performance Metrics - Navigation timing
- ✨ Zero Config - Auto-tracks when modal opens
import { useRouteObserver } from "@react-buoy/route-events";
export default function RootLayout() {
useRouteObserver((event) => {
analytics.trackPageView({
path: event.pathname,
params: event.params,
timeSpent: event.timeSincePrevious,
});
});
return <Stack />;
}🎨 Debug Borders (@react-buoy/debug-borders)
Visual debugging tool with three modes: borders only, borders with labels, or off. Labels mode shows only components with testID or accessibilityLabel, and you can tap any label to inspect the component.
npm install @react-buoy/debug-borders- 🔄 Three Modes - Tap to cycle: Off → Borders → Labels
- 🏷️ Smart Labels - Only shows components with testID or accessibilityLabel
- 👆 Tap-to-Inspect - Tap any label to see component details (styles, props, position)
- 🎨 Color-Coded - Green = testID, Pink = accessibilityLabel
- 📚 Label Stacking - Overlapping labels stack upward like a menu
- 🙈 Smart Filtering - Hides inactive screens, SVGs, and devtools components
- ⚡ Zero performance impact when disabled
Zero Config: Install and it appears as "BORDERS" in the floating menu. Tap to cycle modes.
Standalone:
import { DebugBordersStandaloneOverlay } from "@react-buoy/debug-borders";
<DebugBordersStandaloneOverlay />🔄 Highlight Updates (@react-buoy/highlight-updates)
Visual component re-render tracker that highlights components when they render. Helps identify unnecessary re-renders and performance bottlenecks.
npm install @react-buoy/highlight-updates- 🔄 Visual Render Detection - See components flash when they re-render
- 🔢 Render Counts - See exact render counts on each component to identify problematic re-renders
- 📊 Render History - Track which components render and how often
- 🎛️ Filter Controls - Filter by component type or render frequency
- 🎭 Toggle Mode - Quick tap to enable/disable highlights
- 📋 Modal View - Detailed render list with timing information
- ⚡ Zero performance impact when disabled
Zero Config (Recommended): Just install and it auto-appears as an "UPDATES" button in the floating menu.
🔀 Environment Switcher (@react-buoy/core)
Switch between environments (dev, qa, staging, prod) directly from the floating menu. Built into core—no extra package needed.
const [environment, setEnvironment] = useState<Environment>("dev");
<FloatingDevTools
environment={environment}
availableEnvironments={["dev", "qa", "staging", "prod"]}
onEnvironmentSwitch={(env) => {
// Your logic: update API URLs, clear caches, etc.
setEnvironment(env);
}}
/>- 🎯 Inline Badge - Shows current environment in the floating row
- 📂 Animated Dropdown - Tap to expand and select environment
- ✅ Visual Feedback - Checkmark shows current selection
- 🎨 Color-Coded - Each environment has a distinct color
📚 Expand for advanced topics
Want to override auto-discovery with full control? Use factory functions:
import { FloatingDevTools } from "@react-buoy/core";
import { createEnvTool } from "@react-buoy/env";
import { createNetworkTool } from "@react-buoy/network";
const customTools = [
createEnvTool({
name: "ENVIRONMENT", // Custom name
iconColor: "#9333EA", // Custom color
requiredEnvVars: [...],
}),
createNetworkTool({
name: "API MONITOR",
iconColor: "#EC4899",
}),
];
<FloatingDevTools
apps={customTools} // Overrides auto-discovery for these IDs
environment="production"
/>import type { InstalledApp } from "@react-buoy/core";
import { EnvVarsModal } from "@react-buoy/env";
import { NetworkModal } from "@react-buoy/network";
import { EnvLaptopIcon, WifiCircuitIcon } from "@react-buoy/shared-ui";
const manualTools: InstalledApp[] = [
{
id: "env",
name: "ENV",
description: "Environment debugger",
slot: "both",
icon: ({ size }) => <EnvLaptopIcon size={size} colorPreset="green" noBackground />,
component: EnvVarsModal,
props: { requiredEnvVars: [...] },
},
{
id: "network",
name: "NET",
description: "Network logger",
slot: "both",
icon: ({ size }) => <WifiCircuitIcon size={size} colorPreset="cyan" noBackground />,
component: NetworkModal,
props: {},
},
];
<FloatingDevTools apps={manualTools} environment="local" />Control where tools appear:
type AppSlot = "row" | "dial" | "both";- "row": Always-visible header (environment/role badges)
- "dial": Floating expandable menu
- "both": Available in both locations (default)
type LaunchMode = "self-modal" | "host-modal" | "inline" | "toggle-only";- "self-modal": Tool manages its own modal (default for most)
- "host-modal": Core manages the modal lifecycle
- "inline": Renders inline (no modal)
- "toggle-only": Just triggers an action (e.g., debug-borders)
JSON Viewer & Diff Tools
All tools that display data (Network, Storage, React Query) use optimized JSON viewers:
Like Redux DevTools - explore nested objects with expand/collapse
Like VS Code - compare payloads visually
Quickly find what you need in large payloads:
- String values
- Numbers
- Booleans
- Null/undefined
- Objects
- Arrays
- Functions
Example: Debugging a 5MB API response → filter only booleans to check feature flags, or search undefined keys to spot missing data.
State Persistence & Minimize Feature
React Buoy remembers:
- Which tools are open
- Tool positions (if dragged)
- Minimized vs expanded state
- Modal sizes and positions
- User preferences
React Buoy uses a smart storage system that automatically picks the best available option:
| Backend | Persists Through Logout? | Requires | When Used |
|---|---|---|---|
| 📁 File System | ✅ Yes | expo-file-system |
Dev builds, RN CLI |
| 💾 AsyncStorage | ❌ No (cleared on logout) | @react-native-async-storage/async-storage |
Expo Go fallback |
| 🧠 Memory | ❌ No (lost on restart) | Nothing | Last resort |
Why does this matter?
If your app clears AsyncStorage during logout (common pattern), your devtools settings would normally be wiped too. With expo-file-system installed, settings persist independently—surviving logout flows, AsyncStorage.clear() calls, and more.
To enable persistent storage:
# Expo projects
npx expo install expo-file-system
# RN CLI projects
npm install expo expo-file-systemYou can check which storage backend is active in Settings → Storage Type in the devtools menu.
This means your debugging session survives:
- ✅ Hot reloads
- ✅ App restarts
- ✅ Crash recovery
- ✅ Logout flows (with file system storage)
Keep tools running in the background without cluttering your screen:
- Minimize - Tap the minimize button (−) in any tool's header
- Minimized State - Tool shrinks to a small floating indicator with its icon
- Restore - Tap the minimized indicator to restore the full tool
- Dismiss - Swipe down on the minimized indicator to close the tool completely
Why minimize?
- 👁️ Reduces visual clutter while debugging
- ⚡ Keeps tools running (e.g., network monitor keeps capturing)
- 🔄 Quick restore without reloading tool state
- 🎯 Perfect for monitoring tools you want to keep "in the background"
Example Use Case: Minimize the Network monitor while testing your UI, then restore it when you need to check API calls—all captured data is still there.
Production Usage
React Buoy is production-safe with proper access controls:
import { FloatingDevTools } from "@react-buoy/core";
import { useUser } from "./auth";
function App() {
const user = useUser();
const showDevTools = user.role === "admin" || __DEV__;
return (
<>
{/* Your app */}
{showDevTools && (
<FloatingDevTools
environment={process.env.ENVIRONMENT}
userRole={user.role}
/>
)}
</>
);
}Recommendation: Gate with your existing authentication/authorization system.
- ✅ Zero config (Reactotron requires manual command registration)
- ✅ In-app UI (Reactotron requires external app)
- ✅ Production-safe with auth (Reactotron is dev-only)
- ✅ Plugin architecture (install packages = auto-appear)
- ✅ Zero setup (Flipper requires native config + desktop app)
- ✅ Works on physical devices out-of-the-box
- ✅ Lightweight (Flipper is heavy)
- ✅ Team-friendly (no desktop app to install)
- ✅ Modern (supports Hermes, new architecture)
- ✅ In-app (no external tools)
- ✅ Extensible (custom tools as React components)
- ✅ Production-ready
Scenario: Debugging a payment flow issue in staging
- Environment badge shows you're in staging (not prod!)
- Role badge confirms you're logged in as "QA"
- Tap Network to watch API calls in real-time
- Open Storage to see what's persisted locally
- Check React Query to inspect cached payment data
- Use Routes to see the navigation flow
- Launch your custom Payment Debug tool
All from one floating menu that follows you through every screen.
MIT © React Buoy Team
Resources:
- Example App - Full working example with all packages
- Package Source - Individual package source code
- Changelog - Version history
Contributing:
- Report bugs: GitHub Issues
- Feature requests welcome!
Big thanks to galaxies.dev — their content helped me get up to speed with React Native early on, and I strongly recommend it as a resource for anyone making the jump from web to mobile.






