The floating control panel for your entire mobile app team.
A persistent, draggable menu that’s always available—showing your current environment and role, while giving instant access to the tools anyone in your org needs. From impersonating users in production for customer support, to debugging storage, network, or cache issues across environments, to testing feature flags or building entirely custom workflows—React Buoy makes it easy to create and share powerful tools with your whole team.
- Always visible – Shows environment & user role in a draggable row that survives reloads
- Consistent everywhere – Same tools in dev, staging, and production
- Bring your own tools – Drop in any React component as a tool
- Team-friendly – Each engineer can show/hide the tools they need
- Smart interactions – Double-tap to switch between bottom sheet and floating modal, triple-tap to close, swipe down to dismiss
React Buoy includes optimized JSON viewers and comparison tools:
- Tree view – Like Redux DevTools for exploring nested objects
- Side-by-side diff view – Like VS Code for comparing payloads
- Type filtering – Quickly find exactly what you need in large payloads:
- string
- number
- boolean
- undefined
- null
- object
- array
- function
Example: debugging a large response payload → filter only booleans to check feature flags, or search for undefined keys to spot missing data instantly.
Get the floating menu working in your app with just the core functionality.
npm
npm install @react-buoy/core
pnpm
pnpm add @react-buoy/core
yarn
yarn add @react-buoy/core
bun
bun add @react-buoy/core
import { FloatingDevTools } from "@react-buoy/core";
function App() {
return (
<>
{/* Your existing app content */}
<FloatingDevTools
apps={[]}
actions={{}}
environment="local"
userRole="admin"
/>
</>
);
}
That's it! You now have a floating menu showing "local" environment and "admin" user role. The menu is draggable and will persist its position.
Add any combination of these developer tools to your floating menu:
🌍 Environment Inspector (@react-buoy/env)
Visual health check for your app configuration. See all environment variables with validation, search, and filtering.
npm
npm install @react-buoy/env
pnpm
pnpm add @react-buoy/env
yarn
yarn add @react-buoy/env
bun
bun add @react-buoy/env
import { EnvVarsModal, createEnvVarConfig, envVar } from "@react-buoy/env";
import { EnvLaptopIcon } from "@react-buoy/shared-ui";
// Define your required environment variables
const requiredEnvVars = createEnvVarConfig([
// Basic existence check
envVar("API_URL").exists(),
// Type validation
envVar("DEBUG_MODE").withType("boolean").build(),
envVar("PORT").withType("number").build(),
envVar("FEATURE_FLAGS").withType("object").build(),
// Specific value validation
envVar("NODE_ENV").withValue("development").build(),
// Combined validations with descriptions
envVar("DATABASE_URL")
.exists()
.withDescription("PostgreSQL connection string")
.build(),
envVar("MAX_RETRIES")
.withType("number")
.withDescription("Maximum API retry attempts")
.build(),
]);
// Add to your apps array
const TOOLS = [
{
id: "env",
name: "ENV",
description: "Environment variables debugger",
slot: "both",
icon: ({ size }) => <EnvLaptopIcon size={size} color="#9f6" />,
component: EnvVarsModal,
props: {
requiredEnvVars,
},
},
];
Creates an environment variable validation rule.
Methods:
.exists()
- Validates the environment variable exists (not undefined/empty).withType(type)
- Validates the variable type ("string"
|"number"
|"boolean"
|"object"
).withValue(expectedValue)
- Validates the variable has a specific value.withDescription(description)
- Adds a description shown in the UI.build()
- Finalizes the validation rule (required for chained methods)
Examples:
// Just check if it exists
envVar("API_URL").exists();
// Type validation
envVar("PORT").withType("number").build();
// Exact value check
envVar("NODE_ENV").withValue("production").build();
// Combined validation
envVar("ENABLE_ANALYTICS")
.withType("boolean")
.withDescription("Controls analytics tracking")
.build();
Creates a configuration object from environment variable rules.
const config = createEnvVarConfig([
envVar("API_URL").exists(),
envVar("DEBUG").withType("boolean").build(),
]);
- ✅ Visual validation of required environment variables
- 🔍 Search and filter environment variables
- 🎯 Type checking (string, number, boolean, object)
⚠️ Clear warnings for missing or incorrect values
📡 Network Inspector (@react-buoy/network)
Real-time network request monitoring with timeline view, detailed inspection, and performance stats.
npm
npm install @react-buoy/network
pnpm
pnpm add @react-buoy/network
yarn
yarn add @react-buoy/network
bun
bun add @react-buoy/network
import { NetworkModal } from "@react-buoy/network";
import { Globe } from "@react-buoy/shared-ui";
// Add to your apps array
const TOOLS = [
{
id: "network",
name: "NETWORK",
description: "Network request logger",
slot: "both",
icon: ({ size }) => <Globe size={size} color="#38bdf8" />,
component: NetworkModal,
props: {},
},
];
- 📊 Timeline view of all network requests
- 🔍 Detailed request/response inspection
- ⚡ Performance metrics and timing
- 🎛️ Request filtering and search
- 📋 Copy request details for debugging
💾 Storage Explorer (@react-buoy/storage)
Real-time AsyncStorage browser with live updates, bulk operations, and storage validation.
npm
npm install @react-buoy/storage
npm install @react-native-async-storage/async-storage # peer dependency
pnpm
pnpm add @react-buoy/storage
pnpm add @react-native-async-storage/async-storage # peer dependency
yarn
yarn add @react-buoy/storage
yarn add @react-native-async-storage/async-storage # peer dependency
bun
bun add @react-buoy/storage
bun add @react-native-async-storage/async-storage # peer dependency
import { StorageModalWithTabs } from "@react-buoy/storage";
import { StorageStackIcon } from "@react-buoy/shared-ui";
// Define storage keys to monitor and validate
const requiredStorageKeys = [
// Basic key monitoring
{
key: "@app/session",
description: "Current user session token",
storageType: "async",
},
// Type validation
{
key: "@app/settings",
expectedType: "object",
description: "User preferences and settings",
storageType: "async",
},
// Exact value validation
{
key: "@app/theme",
expectedValue: "dark",
description: "Application theme preference",
storageType: "mmkv",
},
// SecureStore keys
{
key: "biometric_token",
expectedType: "string",
description: "Encrypted biometric authentication token",
storageType: "secure",
},
// Multiple storage types
{
key: "@analytics/user_id",
expectedType: "string",
description: "Anonymous user identifier for analytics",
storageType: "async",
},
];
// Add to your apps array
const TOOLS = [
{
id: "storage",
name: "STORAGE",
description: "AsyncStorage browser",
slot: "both",
icon: ({ size }) => <StorageStackIcon size={size} color="#38f8a7" />,
component: StorageModalWithTabs,
props: {
requiredStorageKeys, // optional
},
},
];
Each storage key configuration object supports the following properties:
Required:
key: string
- The storage key to monitor (e.g., "@app/session")storageType: "async" | "secure" | "mmkv"
- Which storage system to check
Optional Validation:
expectedType: "string" | "number" | "boolean" | "object"
- Validates the stored value typeexpectedValue: any
- Validates the stored value matches exactlydescription: string
- Human-readable description shown in the UI
Examples:
// Type validation
{
key: "@app/settings",
expectedType: "object",
description: "User app settings",
storageType: "async",
}
// Exact value validation
{
key: "@app/theme",
expectedValue: "dark",
description: "App theme (should be dark)",
storageType: "mmkv",
}
// SecureStore monitoring
{
key: "auth_token",
expectedType: "string",
description: "JWT authentication token",
storageType: "secure",
}
"async"
- React Native AsyncStorage"secure"
- Expo SecureStore (encrypted)"mmkv"
- MMKV high-performance storage
interface StorageModalProps {
requiredStorageKeys?: RequiredStorageKey[];
enableSharedModalDimensions?: boolean;
}
- 🗂️ Browse all AsyncStorage, SecureStore, and MMKV data
- ✏️ Edit storage values in real-time
- 🗑️ Bulk delete operations
- 🔍 Search and filter storage keys
⚠️ Validation for required storage keys
⚡ React Query DevTools (@react-buoy/react-query)
TanStack Query devtools adapted for mobile with query explorer, cache manipulation, and offline toggle.
npm
npm install @react-buoy/react-query
npm install @tanstack/react-query # peer dependency
pnpm
pnpm add @react-buoy/react-query
pnpm add @tanstack/react-query # peer dependency
yarn
yarn add @react-buoy/react-query
yarn add @tanstack/react-query # peer dependency
bun
bun add @react-buoy/react-query
bun add @tanstack/react-query # peer dependency
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<AppHostProvider>{/* Your app content */}</AppHostProvider>
</QueryClientProvider>
);
}
import { ReactQueryDevToolsModal, WifiToggle } from "@react-buoy/react-query";
import { ReactQueryIcon } from "@react-buoy/shared-ui";
// Add to your apps array
const TOOLS = [
{
id: "query",
name: "REACT QUERY",
description: "React Query inspector",
slot: "both",
icon: ({ size }) => <ReactQueryIcon size={size} colorPreset="red" />,
component: ReactQueryDevToolsModal,
props: {},
},
// Optional: Add WiFi toggle for offline testing
{
id: "wifi-toggle",
name: "WIFI TOGGLE",
description: "Toggle offline mode",
slot: "both",
icon: ({ size }) => <WifiToggle size={size} />,
component: () => <></>,
props: {},
},
];
- 🔍 Query explorer with real-time data
- 🗂️ Cache manipulation and inspection
- 📊 Query performance metrics
- 🔄 Manual query refetching
- 📶 Offline/online mode toggle
Here's a full working example with all packages (same as our example app):
Click to see complete setup with all tools
import React, { useMemo, useRef } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { FloatingDevTools, type InstalledApp } from "@react-buoy/core";
import { EnvVarsModal, createEnvVarConfig, envVar } from "@react-buoy/env";
import { NetworkModal } from "@react-buoy/network";
import { StorageModalWithTabs } from "@react-buoy/storage";
import { ReactQueryDevToolsModal, WifiToggle } from "@react-buoy/react-query";
import {
EnvLaptopIcon,
ReactQueryIcon,
StorageStackIcon,
Globe,
} from "@react-buoy/shared-ui";
export default function App() {
// Setup QueryClient
const queryClientRef = useRef<QueryClient | null>(null);
if (!queryClientRef.current) {
queryClientRef.current = new QueryClient({});
}
// Configure environment variables to validate
const requiredEnvVars = createEnvVarConfig([
envVar("EXPO_PUBLIC_API_URL").exists(),
envVar("EXPO_PUBLIC_DEBUG_MODE").withType("boolean").build(),
envVar("EXPO_PUBLIC_ENVIRONMENT").withValue("development").build(),
]);
// Configure storage keys to monitor
const requiredStorageKeys = useMemo(
() => [
{
key: "@app/session",
expectedType: "string",
description: "Current user session token",
storageType: "async",
},
{
key: "@app/settings:theme",
expectedValue: "dark",
description: "Preferred theme",
storageType: "async",
},
],
[]
);
// Configure all development tools
const installedApps: InstalledApp[] = useMemo(
() => [
{
id: "env",
name: "ENV",
description: "Environment variables debugger",
slot: "both",
icon: ({ size }) => <EnvLaptopIcon size={size} color="#9f6" />,
component: EnvVarsModal,
props: { requiredEnvVars },
},
{
id: "network",
name: "NETWORK",
description: "Network request logger",
slot: "both",
icon: ({ size }) => <Globe size={size} color="#38bdf8" />,
component: NetworkModal,
props: {},
},
{
id: "storage",
name: "STORAGE",
description: "AsyncStorage browser",
slot: "both",
icon: ({ size }) => <StorageStackIcon size={size} color="#38f8a7" />,
component: StorageModalWithTabs,
props: { requiredStorageKeys },
},
{
id: "query",
name: "REACT QUERY",
description: "React Query inspector",
slot: "both",
icon: ({ size }) => <ReactQueryIcon size={size} colorPreset="red" />,
component: ReactQueryDevToolsModal,
props: {},
},
{
id: "wifi-toggle",
name: "WIFI TOGGLE",
description: "Toggle offline mode",
slot: "both",
icon: ({ size }) => <WifiToggle size={size} />,
component: () => <></>,
props: {},
},
],
[requiredEnvVars, requiredStorageKeys]
);
return (
<QueryClientProvider client={queryClientRef.current!}>
{/* Your existing app content */}
<YourAppContent />
{/* The floating menu with all tools */}
<FloatingDevTools
apps={installedApps}
actions={{}}
environment="local"
userRole="admin"
/>
</QueryClientProvider>
);
}
Any React component can be a development tool. Perfect for:
- 👨💼 Admin dashboards
- 🎚️ Feature flag toggles
- 👤 User impersonation
- ✅ QA checklists
- 🌐 GraphQL explorers
- 🗄️ Database browsers
- 📱 Push notification testing
- 📊 Analytics dashboards
// Your custom tool - just a React component
function MyCustomTool({ onClose }) {
return (
<View style={{ padding: 20 }}>
<Text>My Custom Development Tool 🚀</Text>
{/* Your custom UI here */}
<Button title="Close" onPress={onClose} />
</View>
);
}
// Add it to the floating menu
const TOOLS = [
{
id: "custom",
name: "CUSTOM",
description: "My custom development tool",
slot: "both", // Show in row AND dial
icon: ({ size }) => <YourIcon size={size} />,
component: MyCustomTool,
props: {}, // Any props your component needs
},
];
Your current environment and role are always visible. No more "wait, am I in prod?" moments.
Hot reload? Crash recovery? The tools persist through it all. Positions are remembered.
Every engineer sees the same tools in every environment. Onboard new devs in minutes.
Beautiful, responsive, and intuitive. Your team will want to use these tools.
Ship it to production—just add your own access controls!
Imagine debugging a payment flow issue:
- Environment badge shows you're in staging (not prod! 😅)
- Role badge confirms you're logged in as "Admin"
- Tap Network to watch API calls in real-time
- Open Storage to see what's persisted locally
- Check React Query to inspect cached data
- Launch your custom Payment Debug tool
All from one floating menu that follows you through every screen.
MIT © React Buoy Team
Take a shortcut from web developer to mobile development fluency with guided learning
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.
