react-access-engine is a unified React-first access and feature management platform.
It combines RBAC, ABAC, feature flags, experiments, policy evaluation, and subscription-gated access into a single, tree-shakeable, type-safe library with declarative components and hooks.
React applications cobble together:
- Homegrown RBAC checks (
if (user.role === 'admin')) - Separate feature flag services (LaunchDarkly, Unleash)
- Ad-hoc subscription/plan gating
- Manual A/B test wiring
- No unified audit trail
react-access-engine replaces all of this with one coherent, type-safe system.
| Dimension | Typical RBAC lib | Feature flag tool | react-access-engine |
|---|---|---|---|
| Access model | Roles → permissions | Boolean flags | RBAC + ABAC + policies |
| Feature flags | None | Yes | Built-in with rollouts |
| Experiments | None | Sometimes | First-class A/B testing |
| Typing | Loose strings | Loose strings | Inferred literal types |
| Remote config | None | Proprietary | Open loader protocol |
| Audit | None | Proprietary | Event hooks + debug meta |
| Architecture | Single context blob | SDK-specific | Tree-shakeable engines |
| SSR | Often broken | Varies | Server-safe by design |
┌─────────────────────────────────────────────────────┐
│ AccessProvider │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Role │ │Permission│ │ Policy Engine │ │
│ │ Engine │ │ Engine │ │ (ABAC + rules) │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Feature │ │ Rollout │ │ Experiment Engine │ │
│ │ Engine │ │ Engine │ │ (A/B testing) │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Remote │ │ Plugin │ │ Debug Metadata │ │
│ │ Config │ │ Engine │ │ Engine │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────┘
Each engine is a pure function module. They are tree-shakeable — if you don't use feature flags, the feature engine is not bundled.
Config → Engines → Context → Hooks/Components → UI
↑
Remote Config Loader (optional)
↑
Plugin Events (optional)
All public APIs use a single generic TConfig that flows through the system:
const config = defineAccess({
roles: ['admin', 'editor', 'viewer'] as const,
permissions: { ... },
features: { ... },
}) // TConfig is inferred — role names, feature names, permission names autocompleteThis gives:
useRole()returns'admin' | 'editor' | 'viewer'useFeature('dark-mode')autocompletes feature names<Can perform="articles:edit">autocompletes permission strings
- Split contexts — roles, permissions, features, policies in separate React contexts so a feature flag change doesn't rerender permission-checking components
- Memoized engines — engine evaluation results are memoized with shallow comparison
- Stable references — hook return values use
useMemo/useRefto avoid unnecessary rerenders downstream - Tree-shaking — each engine is a separate module; unused engines are eliminated
- Lazy evaluation — policies and experiments are evaluated on demand, not eagerly
- All hooks return deterministic values from config on first render (no
useEffectneeded) - No
window/document/localStorageaccess in core evaluation - Remote config supports server-side fetching (pass resolved config to provider)
- Rollout engine uses stable user ID hashing, not
Math.random() <Feature>rendersfallbackon server when rollout is percentage-based and no user context- Full React Server Component compatibility — provider is a Client Component boundary
- AccessProvider, Can, Feature components
- useAccess, usePermission, useRole, useFeature hooks
- Role engine, permission engine, feature flag engine
- Full TypeScript inference
- ESM + CJS builds
- SSR safe
- All MVP features
- ABAC conditions
- Policy engine
- Experiments / A/B
- Percentage rollouts
- Feature dependencies
- Subscription/plan gating
- Environment rules
- Plugin system + event hooks
- Remote config protocol
- Debug metadata + useAccessDebug
- AccessGate, PermissionGuard, Experiment, FeatureToggle components
- No DevTools UI (complexity)
- No Chrome extension
- No CLI tools
- No middleware (keep it React-only)
- No React Native specific code
- No persistence layer