Get Started

Introduction

Learn the one idea behind okengine — then the eight elements and ten exports.

OKE is a Bun-first TypeScript backend. You do not learn a pile of unrelated tools (router + queue + cron + websockets). You learn one sentence, and everything else follows from it.

The one law

Every backend behavior is a Flow: on(Trigger) → Effects

There are no separate species called endpoints, handlers, consumers, jobs, subscribers, or workflows. There is one species — the Flow — and triggers are typed values:

flows
on(http.post("/bookings"), createBooking);      // "an API endpoint"
on(every("10m"), expireStale);                  // "a cron job"
on(orderPlaced, sendReceipt);                   // "a queue consumer"
on(db.table(users).changed("email"), reverify); // "a CDC trigger"

Same shape every time: a trigger, a flow body, and effects inferred from what that body touches through fx.

Why this lowers the learning curve

One law → one mental model → one documentation path → one trace shape → one thing for an AI agent to learn.

Learning OKE is learning one sentence.

What you get

You write TypeScript. At build time OKE extracts a Manifest — a machine-readable description of your system. From that Manifest the rest is derived, not configured by hand:

  • Typed client (no separate codegen step to maintain)
  • OpenAPI / docs surfaces
  • Architecture diagram that is the effect graph
  • Console panels, traces, and explorers
  • MCP surface for agents (:6535)
  • Least-privilege capability matrix and cache invalidation keys

Ten exports

The entire public vocabulary fits in one import:

okengine
import { on, flow, signal, store, clock, gate, vault, channel, ai, plugin } from "okengine";
ExportRole
onBind a trigger to a flow
flowDefine behavior + contracts
signalData in motion (queue / pub-sub / live)
storeData at rest (sql · kv · files · index)
clockTime (cron, delay, sleep, TTL)
gatePermission to act (auth, ABAC, limits)
vaultSecrets and config
channelReach humans (email, SMS, …)
aiReach models / agents
pluginExtend the runtime without a ninth element

Everything else in the docs is derived from these ten names.

The eight elements

Everything a backend has ever needed reduces to eight typed elements. An element earns its place only if it has irreducible physics. New infrastructure becomes a new driver for an existing element — never a ninth element.

What each element replaces
ElementReplaces the zoo of
Flowendpoint · handler · consumer · job · workflow · webhook
Signalqueue · pub/sub · stream · websocket · SSE · event bus
Storedatabase · cache · KV · file storage · search index
Clockcron · delay · timeout · durable sleep · TTL
Gateauth · session · ABAC · rate limit · quota · feature flag
Vaultsecrets · config · environment
Channelemail · SMS · WhatsApp · push
AImodel calls · prompts · embeddings · agents · RAG

The fx rule

All world access goes through fx. A Flow that imports node:fs (or any other side-channel I/O) is a defect.

That single rule is why cache invalidation, live queries, least privilege, deterministic tests, and Manifest Diff can be inferred instead of annotated by hand. You will see fx in every example from here on.

Where to go next

Read in this order if you are new:

  1. Comparison — when OKE fits (and when it doesn't)
  2. Installation — scaffold an app in minutes
  3. Basic Usage — first flows, client, and tests
  4. Notes — full teaching path

AI resources

AGENTS.md and MCP (:6535) expose the Manifest, schemas, effects, traces, and the Console's safe runtime actions. See AI Resources for the agent contract and machine-readable docs (/llms.txt, /llms-full.txt).

On this page