@arlioz/flagship
v3.0.0
Published
Official JavaScript/TypeScript SDK for FlagShip — feature flags for startups
Maintainers
Readme
Why FlagShip?
- Zero dependencies — works in Node.js, browsers, edge runtimes, and serverless
- Tiny footprint — under 2 KB minified + gzipped
- TypeScript-first — full type safety out of the box
- Real-time sync — built-in polling keeps flags up to date
- Targeting & rollouts — percentage-based rollouts with user attribute conditions
- Open source — self-host or use our managed platform
Quick Start
1. Install
npm install @arlioz/flagship# or with your preferred package manager
yarn add @arlioz/flagship
pnpm add @arlioz/flagship2. Initialize
import { FlagShip } from "@arlioz/flagship"
const client = new FlagShip({
apiKey: "flg_production_your_key_here",
})3. Use flags
const showNewUI = await client.get("new_ui")
if (showNewUI) {
renderNewDashboard()
} else {
renderLegacyDashboard()
}That's it. You're shipping with feature flags. 🚀
Usage
Basic flag evaluation
// Boolean flag (most common)
const isEnabled = await client.get("dark_mode")
// With a fallback value
const limit = await client.get("upload_limit", 10)
// String flag
const theme = await client.get("theme", "light")Fetch all flags at once
const flags = await client.fetchFlags()
console.log(flags)
// → { dark_mode: true, upload_limit: 50, theme: "dark" }Get all cached flags (synchronous)
// After an initial fetch, read from cache without awaiting
const allFlags = client.getAll()User targeting
const client = new FlagShip({
apiKey: "flg_production_abc123",
userId: "user-42",
attributes: {
plan: "pro",
country: "FR",
role: "admin",
},
})
// Flags are evaluated server-side with targeting rules
const canAccessBeta = await client.get("beta_features")Update user context
// When a user logs in or their context changes
client.identify("user-789", {
plan: "enterprise",
country: "DE",
})
// Cache is cleared — next .get() will re-fetch with new context
const flags = await client.get("premium_feature")Auto-polling
const client = new FlagShip({
apiKey: "flg_production_abc123",
pollingInterval: 15000, // poll every 15 seconds
})
// Flags stay up to date automatically.
// When you toggle a flag in the dashboard,
// it takes effect within one polling cycle.Clean up
// Stop polling when the app shuts down
client.close()API Reference
new FlagShip(options)
Creates a new FlagShip client instance.
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| apiKey | string | Yes | — | Environment API key from your dashboard (e.g. flg_production_...) |
| baseUrl | string | No | http://localhost:4000/api | Base URL of your FlagShip API |
| userId | string | No | — | User ID for percentage-based rollouts |
| attributes | Record<string, any> | No | {} | User attributes for targeting conditions |
| pollingInterval | number | No | 30000 | Polling interval in ms. Set 0 to disable |
client.get<T>(key, defaultValue?): Promise<T>
Get a single flag value by key. Returns the defaultValue if the flag doesn't exist.
const isEnabled = await client.get("feature_x") // boolean
const limit = await client.get("rate_limit", 100) // number
const variant = await client.get("cta_text", "Sign Up") // stringclient.fetchFlags(): Promise<Record<string, any>>
Fetch all flags from the server and update the local cache. Returns the full flag map.
client.getAll(): Record<string, any>
Returns all cached flag values synchronously. Useful after an initial fetchFlags() call.
client.identify(userId, attributes?): void
Update the user context for subsequent evaluations. Clears the cache so the next read triggers a fresh fetch.
client.close(): void
Stop the polling timer and clean up resources. Call this when your app shuts down.
Framework Examples
Next.js (App Router)
// lib/flags.ts
import { FlagShip } from "@arlioz/flagship"
export const flagClient = new FlagShip({
apiKey: process.env.FLAGSHIP_API_KEY!,
baseUrl: "https://flagship-pwxs.onrender.com/api",
pollingInterval: 0, // disable polling in server context
})// app/page.tsx
import { flagClient } from "@/lib/flags"
export default async function HomePage() {
const showBanner = await flagClient.get("promo_banner")
return (
<main>
{showBanner && <PromoBanner />}
<HeroSection />
</main>
)
}Express / Node.js
import express from "express"
import { FlagShip } from "@arlioz/flagship"
const app = express()
const flags = new FlagShip({
apiKey: "flg_production_abc123",
baseUrl: "https://flagship-pwxs.onrender.com/api",
})
app.get("/api/config", async (req, res) => {
const userId = req.headers["x-user-id"] as string
if (userId) {
flags.identify(userId)
}
const showNewCheckout = await flags.get("new_checkout")
const uploadLimit = await flags.get("upload_limit", 10)
res.json({ showNewCheckout, uploadLimit })
})React (Client-side)
import { useEffect, useState } from "react"
import { FlagShip } from "@arlioz/flagship"
const client = new FlagShip({
apiKey: "flg_production_abc123",
baseUrl: "https://flagship-pwxs.onrender.com/api",
})
function App() {
const [flags, setFlags] = useState<Record<string, any>>({})
useEffect(() => {
client.fetchFlags().then(setFlags)
return () => client.close()
}, [])
return (
<div>
{flags.chat_widget && <ChatWidget />}
{flags.dark_mode ? <DarkTheme /> : <LightTheme />}
</div>
)
}How It Works
┌─────────────┐ GET /flags/evaluate ┌──────────────┐
│ Your App │ ──────────────────────────▶ │ FlagShip │
│ │ ?environment_key=... │ API Server │
│ @arlioz/ │ ◀────────────────────────── │ │
│ flagship │ { dark_mode: true, ... } │ PostgreSQL │
└─────────────┘ └──────────────┘
│ ▲
│ polls every 30s │
└─────────────────────────────────────────────┘- Your app initializes the SDK with an environment API key
- The SDK calls the evaluate endpoint with the key + user context
- The server evaluates targeting rules and returns resolved flag values
- The SDK caches results and polls for updates automatically
MIT — Arlioz
