A powerful, type-safe targeting and feature flag system for dynamically serving different content based on query conditions.
@targetd is a TypeScript-first monorepo providing a complete solution for
building context-aware applications with dynamic content delivery. Perfect for
feature flags, A/B testing, content personalization, and configuration
management.
Key Features:
- π― Type-safe targeting - Full TypeScript inference and runtime validation with Zod
- β‘ High performance - In-memory data store optimized for speed
- π Modular architecture - Use only what you need with focused packages
- π HTTP-ready - Built-in server and client for distributed systems
- π File-based rules - Load rules from JSON/YAML files with hot-reloading
- π¨ Extensible - Custom targeting descriptors and predicates
Core targeting and data querying API. Define payloads, targeting rules, and query logic.
import { Data, DataSchema, targetIncludes } from '@targetd/api'
import { z } from 'zod'
const schema = DataSchema.create()
.usePayload({ greeting: z.string() })
.useTargeting({ country: targetIncludes(z.string()) })
const data = await Data.create(schema).addRules('greeting', [
{ targeting: { country: ['US'] }, payload: 'Hello!' },
{ targeting: { country: ['ES'] }, payload: 'Β‘Hola!' },
{ payload: 'Hi!' },
])
await data.getPayload('greeting', { country: 'US' }) // 'Hello!'HTTP server for exposing @targetd/api data over REST endpoints.
import { createServer } from '@targetd/server'
createServer(data).listen(3000)
// GET /greeting?country=US β "Hello!"Type-safe HTTP client for querying @targetd/server instances.
import { Client } from '@targetd/client'
const client = await Client.create('http://localhost:3000', schema)
const greeting = await client.getPayload('greeting', { country: 'US' })Load targeting rules from JSON/YAML files with hot-reloading support.
import { load, watch } from '@targetd/fs'
const data = await load(baseData, './rules')
watch(baseData, './rules', (error, updatedData) => {
// Rules automatically reload on file changes
})Built-in targeting descriptor for date range queries.
import dateRangeTargeting from '@targetd/date-range'
const schema = DataSchema.create()
.usePayload({ campaign: z.string() })
.useTargeting({ date: dateRangeTargeting })
const data = await Data.create(schema).addRules('campaign', [
{
targeting: { date: { start: '2024-12-01', end: '2024-12-31' } },
payload: 'Holiday Campaign',
},
])Transform flat key notation to nested objects.
import { explode } from '@targetd/explode'
explode({ 'user.name': 'John' })
// { user: { name: 'John' } }Generate JSON Schema from Zod schemas for documentation and validation.
# Core API
npm install zod && npx jsr add @targetd/api
# With server and client
npx jsr add @targetd/api @targetd/server @targetd/client
# With file loading
npx jsr add @targetd/api @targetd/fs1. Define your data:
import { Data, DataSchema, targetIncludes } from '@targetd/api'
import { z } from 'zod'
const schema = DataSchema.create()
.usePayload({
banner: z.string(),
feature: z.object({
enabled: z.boolean(),
maxUsers: z.number(),
}),
})
.useTargeting({
platform: targetIncludes(z.string()),
isPremium: targetIncludes(z.boolean()),
})
export const data = await Data.create(schema)
.addRules('banner', [
{ targeting: { platform: ['mobile'] }, payload: 'π± Mobile Banner' },
{ targeting: { platform: ['desktop'] }, payload: 'π₯ Desktop Banner' },
{ payload: 'Default Banner' },
])
.addRules('feature', [
{
targeting: { isPremium: [true] },
payload: { enabled: true, maxUsers: 1000 },
},
{ payload: { enabled: true, maxUsers: 10 } },
])2. Start a server:
import { createServer } from '@targetd/server'
import { data } from './data.ts'
createServer(data).listen(3000)3. Query from a client:
import { Client } from '@targetd/client'
import { data } from './data.ts'
const client = new Client('http://localhost:3000', data)
// Type-safe queries
const banner = await client.getPayload('banner', { platform: 'mobile' })
const allPayloads = await client.getPayloadForEachName({ isPremium: true })const data = await Data.create(
DataSchema.create()
.usePayload({ newFeature: z.boolean() })
.useTargeting({ userTier: targetEquals(z.string()) }),
).addRules('newFeature', [
{ targeting: { userTier: 'beta' }, payload: true },
{ payload: false },
])const data = await Data.create(
DataSchema.create()
.usePayload({ variant: z.string() })
.useTargeting({ userId: targetIncludes(z.string()) }),
).addRules('variant', [
{ targeting: { userId: experimentGroup }, payload: 'variant-a' },
{ payload: 'variant-b' },
])const data = await Data.create(
DataSchema.create()
.usePayload({ content: z.string() })
.useTargeting({
region: targetIncludes(z.string()),
language: targetIncludes(z.string()),
}),
).addRules('content', [
{
targeting: { region: ['US'], language: ['en'] },
payload: 'US English content',
},
{
targeting: { region: ['US'], language: ['es'] },
payload: 'US Spanish content',
},
{ payload: 'Default content' },
])const data = await Data.create(
DataSchema.create()
.usePayload({
config: z.object({
apiUrl: z.string(),
timeout: z.number(),
}),
})
.useTargeting({ environment: targetEquals(z.string()) }),
).addRules('config', [
{
targeting: { environment: 'production' },
payload: { apiUrl: 'https://api.prod.com', timeout: 5000 },
},
{
targeting: { environment: 'staging' },
payload: { apiUrl: 'https://api.staging.com', timeout: 10000 },
},
{ payload: { apiUrl: 'http://localhost:3000', timeout: 30000 } },
])Use DataSchema to declare payload schemas and targeting descriptors, then pass
the resulting schema directly to Data.create(). Splitting the schema and data
phases keeps TypeScript compilation cheap even with hundreds of payloads and
targeting descriptors.
Define what data you want to serve using Zod schemas.
Specify conditions that determine which payload to serve using predicates like
targetIncludes and targetEquals, or create custom ones.
Map targeting conditions to payloads. Rules are evaluated in orderβfirst match wins.
Reusable values with their own targeting rules that can be referenced in
payloads using {{variableName}} syntax.
Pass unresolved targeting conditions between services for evaluation in distributed systems.
βββββββββββββββββββ
β @targetd/api β Core targeting engine
ββββββββββ¬βββββββββ
β
ββββββ΄βββββ
β β
βββββΌβββββ βββΌβββββββββββ
β server β β file loadersβ
βββββ¬βββββ ββββββββββββββ
β
βββββΌβββββ
β client β
ββββββββββ
- API Documentation
- Server Documentation
- Client Documentation
- File System Loader Documentation
- Date Range Targeting Documentation
- Explode Utility Documentation
- JSON Schema Documentation
This is a monorepo managed with Deno workspaces.
# Install dependencies
deno install
# Run tests
deno task test
# Run tests for specific package
cd packages/api && deno task testSee individual package LICENSE files for details.