This is a React app that contains the UI code for Requestly. The same codebase runs in three different contexts:
- Web browser at https://app.requestly.io
- Desktop app (loaded inside Electron from
../../requestly-desktop-app) - Browser extension popup/options pages
The app adapts its behavior based on the environment using window.RQ.MODE and window.RQ.DESKTOP.
The app detects its runtime environment and adapts:
- Web mode: Full web app experience
- Desktop mode: Enhanced with proxy control, file system access via IPC to desktop main/background processes
- Extension mode: Limited UI, communicates with extension background script
Communication bridges:
- Desktop:
window.RQ.DESKTOP(IPC functions exposed via preload script) - Extension:
chrome.runtime.sendMessage/ custom events
The features/ directory is the main organizational unit. Each feature is a self-contained module:
apiClient/- REST API client (Postman-like)rules/- Rule creation and managementmocks/- Mock serversessionBook/- Session recordingsettings/- Settings and billingworkspaces/- Team and workspace managementnetworkInspector/- Network debugging- and more...
Each feature contains its own:
- Components
- State management (Redux slices or Zustand stores)
- Routes
- Business logic
- Types
When adding new functionality, prefer creating/extending features rather than adding to top-level directories.
Used for cross-feature state that needs to be accessed across the app:
store/slices/- App-wide state (user, teams, workspace settings)store/features/- Feature state that needs to be shared or persisted:rules/- Rule records (shared across rule editor, list, etc.)billing/- Subscription statesession-recording/- Session datavariables/- Environment variables
Why Redux here: Needs persistence (redux-persist), cross-feature access, time-travel debugging
Used for feature-specific state that doesn't need global access:
features/apiClient/- Heavily uses Zustand stores for request builder state, collection tree, execution state
API Client Store Architecture (13+ stores):
- Nested store composition: Stores contain other Zustand stores (e.g., each collection/environment has its own variables store)
- Multi-context pattern: Each workspace gets isolated stores via
ApiClientFeatureContextProviderStore- enables multiple workspaces to coexist - Store-per-scope: Variables are managed at three levels (runtime → environment → collection) with dedicated stores at each scope
- Performance optimization: Reference maps (
childParentMap,index) for fast tree navigation without full-array scans
Repository Layer Abstraction (features/apiClient/helpers/modules/sync/):
- Abstracts data persistence behind
ApiClientRepositoryInterface - Three implementations swapped at runtime based on workspace type:
ApiClientCloudRepository- Firebase (team workspaces)ApiClientLocalRepository- File system via desktop IPC (local workspaces)ApiClientLocalStoreRepository- IndexedDB (browser fallback)
- Why: UI code stays identical regardless of storage backend; workspace type determines which repository is injected
- Variable persistence uses separate IndexedDB layer (
store/shared/variablePersistence.ts) with composite keys for scoping
Used for component-tree scoped state:
- Feature-specific contexts in
features/*/contexts/ - Layout contexts in
layouts/*/context/
Location: src/config/PageScriptMessageHandler.js
Purpose: Handles cross-context communication when the app runs in different sandboxed environments:
- Extension content scripts ↔ Web app
- Desktop app renderer ↔ Background process
- Iframe ↔ Parent window
Key constraint: Similar to IPC in desktop app, can only send serializable data. No functions, circular references, or complex objects.
Uses custom events and message passing to bridge isolated JavaScript contexts.
layouts/ directory contains different layout wrappers:
DashboardLayout/- Main authenticated app (header, sidebar, footer)MinimalLayout/- Secondary pages (invites, payments) - minimal chromeFullScreenLayout/- Embedded/iframe contexts - no navigation
Layouts are applied via React Router in routes/index.tsx and control:
- Navigation visibility
- Authentication requirements
- Context-specific UI chrome
Routes are nested under layouts - changing layout affects entire route subtree.
backend/ directory is the only place that should:
- Import Firebase SDK
- Make Firestore/RTDB queries
- Call Cloud Functions
- Handle Firebase Storage
Pattern: Features should import from backend/ modules, not directly use Firebase.
features/rules/screens/
↓ imports from
backend/rules/
↓ uses
Firebase SDK
Why: Abstraction allows switching storage backends (e.g., local storage in desktop workspaces) without changing feature code.
lib/design-system/- Legacy design components (being phased out)lib/design-system-v2/- Modern Ant Design-based components (preferred)
When building UI: Prefer design-system-v2 or Ant Design components directly.
components/mode-specific/ contains platform-specific implementations:
- Browser-only features
- Desktop-only features (proxy controls, file system)
- Extension-only features
Use conditional rendering based on window.RQ.MODE to load correct variant.
Communication layer with browser extension. Handles:
- Extension detection
- Rule sync to extension
- Extension status monitoring
Analytics abstraction layer (Mixpanel, GA). All analytics events should go through this module for consistency.
Converts rules between different formats (Requestly format ↔ other tools like Charles, Fiddler).
Critical abstraction layer for storage. Switches between:
localStorage(web)- IndexedDB (large data)
- Desktop local files (local workspace mode)
Location: ../../requestly-cloud/
- Authentication - Firebase Auth (Google, Email, SSO)
- Database - Firestore (structured data), Realtime DB (live sync)
- Cloud Functions - Serverless backend
- Storage - File uploads
Location: ../../requestly-desktop-app/
When running in desktop app:
- Communicates via IPC through
window.RQ.DESKTOP.SERVICES.IPC - to understand more, read the claude.md at
../../requestly-desktop-app/
src/index.jsx- Bootstrap: Redux store initialization, error boundary (Sentry), hotkeys providersrc/App.tsx- Root component with React Router setupsrc/routes/index.tsx- Route definitions with layout nestingsrc/store/index.ts- Redux store config with autoBatch enhancer for performancesrc/firebase.js- Firebase initialization (DO NOT import elsewhere, usebackend/modules)src/config/PageScriptMessageHandler.js- Cross-context communication setup
- New features: Add to
features/directory as self-contained modules - State management: Use Redux for shared state, Zustand for feature-local state
- Backend calls: Always go through
backend/modules, never direct Firebase imports - Storage: Use
services/clientStorageService/, not direct localStorage - Platform-specific code: Use
mode-specific/components andwindow.RQ.MODEdetection - UI components: Prefer
lib/design-system-v2/or Ant Design directly