OpenFlags
Fast, self-hosted, edge-ready feature flags for modern teams.
The lightweight alternative to LaunchDarkly — built for React, Bun, and Node.js.
✨ Why OpenFlags?
Most feature flag platforms are expensive, enterprise-heavy, and add unnecessary network latency to your app.
OpenFlags is different:
- Local Evaluation: Flags are evaluated instantly (
0mslatency) inside your client SDK. - Edge-Ready: Cache-Control built-in. Easily hide the SQLite server behind Cloudflare or Vercel.
- Self-Hosted: Full ownership of your audit trails and users inside your own infrastructure.
- Progressive Delivery: Run percentage rollouts, kill switches, and targeted beta tests effortlessly.
Tech Stack: Bun · React · Tailwind v4 · SQLite
⚡ Deploy with Docker
Option A — All-in-one image (recommended)
A single container serves the API + Dashboard on one port. No nginx needed.
docker run -d \
--name openflags \
-p 4000:4000 \
-v openflags_data:/app/data \
-e CORS_ORIGIN=https://flags.yourcompany.com \
huextrat/openflags:latest
Open http://localhost:4000.
Option B — Multi-container (docker compose)
Run the API and Dashboard as two separate services behind an nginx reverse proxy:
git clone https://github.com/huextrat/openflags.git
cd openflags
docker compose up -d
Open http://localhost:8080.
The first user to sign up automatically becomes the Platform Admin.
Environment variables
| Variable | Default | Description |
|---|---|---|
PORT |
4000 |
Server port |
CORS_ORIGIN |
http://localhost:4000 |
Allowed origin for cookies (set your domain in prod) |
DATA_DIR |
/app/data |
SQLite database directory — mount a volume here |
See docs/deployment for production tips and reverse proxy setup.
🚀 Local Development (Manual)
If you want to contribute, develop, or run natively without Docker:
1. Install Bun 2. Install dependencies & Start
bun install
bun run dev
This starts the Dashboard on localhost:5173 and the API/Server on localhost:4000.
📖 SDK Usage
JavaScript / TypeScript
import { createClient } from "@openflagsdev/js"
const flags = await createClient({
apiUrl: "http://localhost:4000",
project: "my-app",
userId: "user_123",
refreshIntervalMs: 60_000, // Polls Edge/CDN every 60s
})
if (flags.isEnabled("new_checkout")) {
showNewCheckout()
}
React / Next.js
Wrap your application with the provider, and use the hook anywhere.
import { OpenFlagsProvider, useFlag } from "@openflagsdev/react"
// 1. Setup Provider
root.render(
<OpenFlagsProvider
apiUrl="https://flags.mycompany.com"
project="frontend-app"
userId={user?.id}
refreshIntervalMs={30_000}
>
<App />
</OpenFlagsProvider>
)
// 2. Consume flag
function App() {
const showAI = useFlag("ai_assistant")
return showAI ? <AIAssistant /> : <StandardChat />
}
🏗️ Monorepo Architecture
OpenFlags is structured beautifully as a Turborepo.
| Package | Path | Description |
|---|---|---|
| Server | apps/server |
Bun.serve + SQLite API |
| Dashboard | apps/dashboard |
React SPA for Flag Management |
| Docs Vitrine | apps/docs |
Next.js Landing + Fumadocs |
| React | packages/sdk-react |
@openflagsdev/react Provider & Hooks |
| JS | packages/sdk-js |
Core string-hashing evaluation |
🤝 Contributing & Licensing
Contributions to the codebase, SDKs, or Dashboard UI are highly welcome!
Please read our Contributing Guide to get started.
See AGENTS.md for AI Agent / Workspace context.
Licensed under MIT.