{"id":47197203,"url":"https://github.com/elixir-volt/quickbeam","last_synced_at":"2026-05-03T14:01:56.732Z","repository":{"id":343644589,"uuid":"1177851303","full_name":"elixir-volt/quickbeam","owner":"elixir-volt","description":"JavaScript runtime for the BEAM — Web APIs backed by OTP, native DOM, and a built-in TypeScript toolchain.","archived":false,"fork":false,"pushed_at":"2026-04-30T09:05:23.000Z","size":93246,"stargazers_count":380,"open_issues_count":6,"forks_count":11,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-04-30T11:08:15.266Z","etag":null,"topics":["beam","dom","genserver","javascript-runtime","otp","typescript","webapi","zig"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elixir-volt.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-10T12:44:15.000Z","updated_at":"2026-04-29T17:38:51.000Z","dependencies_parsed_at":"2026-04-10T14:05:21.987Z","dependency_job_id":null,"html_url":"https://github.com/elixir-volt/quickbeam","commit_stats":null,"previous_names":["dannote/quickbeam","elixir-volt/quickbeam"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/elixir-volt/quickbeam","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-volt%2Fquickbeam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-volt%2Fquickbeam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-volt%2Fquickbeam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-volt%2Fquickbeam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elixir-volt","download_url":"https://codeload.github.com/elixir-volt/quickbeam/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-volt%2Fquickbeam/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32571456,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beam","dom","genserver","javascript-runtime","otp","typescript","webapi","zig"],"created_at":"2026-03-13T12:00:38.955Z","updated_at":"2026-05-03T14:01:56.707Z","avatar_url":"https://github.com/elixir-volt.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# QuickBEAM\n\nJavaScript runtime for the BEAM — Web APIs backed by OTP, native DOM,\nand a built-in TypeScript toolchain.\n\nJS runtimes are GenServers. They live in supervision trees, send and\nreceive messages, and call into Erlang/OTP libraries — all without\nleaving the BEAM.\n\n## Installation\n\n```elixir\ndef deps do\n  [{:quickbeam, \"~\u003e 0.7.1\"}]\nend\n```\n\nRequires Zig 0.15+ (installed automatically by Zigler, or use system Zig).\n\n## Quick start\n\n```elixir\n{:ok, rt} = QuickBEAM.start()\n{:ok, 3} = QuickBEAM.eval(rt, \"1 + 2\")\n{:ok, \"HELLO\"} = QuickBEAM.eval(rt, \"'hello'.toUpperCase()\")\n\n# State persists across calls\nQuickBEAM.eval(rt, \"function greet(name) { return 'hi ' + name }\")\n{:ok, \"hi world\"} = QuickBEAM.call(rt, \"greet\", [\"world\"])\n\nQuickBEAM.stop(rt)\n```\n\n## BEAM integration\n\nJS can call Elixir functions and access OTP libraries:\n\n```elixir\n{:ok, rt} = QuickBEAM.start(handlers: %{\n  \"db.query\" =\u003e fn [sql] -\u003e MyRepo.query!(sql).rows end,\n  \"cache.get\" =\u003e fn [key] -\u003e Cachex.get!(:app, key) end,\n})\n\n{:ok, rows} = QuickBEAM.eval(rt, \"\"\"\n  const rows = await Beam.call(\"db.query\", \"SELECT * FROM users LIMIT 5\");\n  rows.map(r =\u003e r.name);\n\"\"\")\n```\n\nJS can also send messages to any BEAM process:\n\n```javascript\n// Get the runtime's own PID\nconst self = Beam.self();\n\n// Send to any PID\nBeam.send(somePid, {type: \"update\", data: result});\n\n// Receive BEAM messages\nBeam.onMessage((msg) =\u003e {\n  console.log(\"got:\", msg);\n});\n\n// Monitor BEAM processes\nconst ref = Beam.monitor(pid, (reason) =\u003e {\n  console.log(\"process died:\", reason);\n});\nBeam.demonitor(ref);\n```\n\n### `Beam` API reference\n\n| Category | API | Description |\n|---|---|---|\n| **Bridge** | `Beam.call(name, ...args)` | Call an Elixir handler (async) |\n| | `Beam.callSync(name, ...args)` | Call an Elixir handler (sync) |\n| | `Beam.send(pid, message)` | Send a message to a BEAM process |\n| | `Beam.onMessage(callback)` | Receive BEAM messages |\n| **Process** | `Beam.self()` | PID of the owning GenServer |\n| | `Beam.spawn(script)` | Spawn a new JS runtime as a BEAM process |\n| | `Beam.register(name)` | Register the runtime under a name |\n| | `Beam.whereis(name)` | Look up a registered runtime |\n| | `Beam.monitor(pid, callback)` | Monitor a process for exit |\n| | `Beam.demonitor(ref)` | Cancel a monitor |\n| | `Beam.link(pid)` / `Beam.unlink(pid)` | Bidirectional crash propagation |\n| **Distribution** | `Beam.nodes()` | List connected BEAM nodes |\n| | `Beam.rpc(node, runtime, fn, ...args)` | Remote call to another node |\n| **Utilities** | `Beam.sleep(ms)` / `Beam.sleepSync(ms)` | Async/sync sleep |\n| | `Beam.hash(data, range?)` | Non-cryptographic hash (`:erlang.phash2`) |\n| | `Beam.escapeHTML(str)` | Escape `\u0026 \u003c \u003e \" '` |\n| | `Beam.which(bin)` | Find executable on PATH |\n| | `Beam.peek(promise)` / `Beam.peek.status(promise)` | Read promise result without await |\n| | `Beam.randomUUIDv7()` | Monotonic sortable UUID |\n| | `Beam.deepEquals(a, b)` | Deep structural equality |\n| | `Beam.nanoseconds()` | Monotonic high-res timer |\n| | `Beam.uniqueInteger()` | Monotonically increasing unique integer |\n| | `Beam.makeRef()` | Create a unique BEAM reference |\n| | `Beam.inspect(value)` | Pretty-print any value (including PIDs/refs) |\n| **Semver** | `Beam.semver.satisfies(version, range)` | Check version against Elixir requirement |\n| | `Beam.semver.order(a, b)` | Compare two semver strings |\n| **Password** | `Beam.password.hash(password, opts?)` | PBKDF2-SHA256 hash |\n| | `Beam.password.verify(password, hash)` | Constant-time verification |\n| **Introspection** | `Beam.version` | QuickBEAM version string |\n| | `Beam.systemInfo()` | Schedulers, memory, atoms, OTP release |\n| | `Beam.processInfo()` | Memory, reductions, message queue |\n\n## Supervision\n\nRuntimes and context pools are OTP children with crash recovery:\n\n```elixir\nchildren = [\n  {QuickBEAM,\n   name: :renderer,\n   id: :renderer,\n   script: \"priv/js/app.js\",\n   handlers: %{\n     \"db.query\" =\u003e fn [sql, params] -\u003e Repo.query!(sql, params).rows end,\n   }},\n  {QuickBEAM, name: :worker, id: :worker},\n\n  # Context pool for high-concurrency use cases\n  {QuickBEAM.ContextPool, name: MyApp.JSPool, size: 4},\n]\n\nSupervisor.start_link(children, strategy: :one_for_one)\n\n{:ok, html} = QuickBEAM.call(:renderer, \"render\", [%{page: \"home\"}])\n```\n\nThe `:script` option loads a JS file at startup. If the runtime crashes,\nthe supervisor restarts it with a fresh context and re-evaluates the script.\n\nIndividual `Context` processes are typically started dynamically (e.g.\nfrom a LiveView `mount`) and linked to the connection process.\n\n## Context Pool\n\nFor high-concurrency scenarios (thousands of connections), use\n`ContextPool` instead of individual runtimes. Many lightweight JS\ncontexts share a small number of runtime threads:\n\n```elixir\n# Start a pool with N runtime threads (defaults to scheduler count)\n{:ok, pool} = QuickBEAM.ContextPool.start_link(name: MyApp.JSPool, size: 4)\n\n# Each context is a GenServer with its own JS global scope\n{:ok, ctx} = QuickBEAM.Context.start_link(pool: MyApp.JSPool)\n{:ok, 3} = QuickBEAM.Context.eval(ctx, \"1 + 2\")\n{:ok, \"HELLO\"} = QuickBEAM.Context.eval(ctx, \"'hello'.toUpperCase()\")\nQuickBEAM.Context.stop(ctx)\n```\n\nContexts support the full API — `eval`, `call`, `Beam.call`/`callSync`,\nDOM, messaging, browser/node APIs, handlers, and supervision:\n\n```elixir\n# In a Phoenix LiveView\ndef mount(_params, _session, socket) do\n  {:ok, ctx} = QuickBEAM.Context.start_link(\n    pool: MyApp.JSPool,\n    handlers: %{\"db.query\" =\u003e \u0026MyApp.query/1}\n  )\n  {:ok, assign(socket, js: ctx)}\nend\n\n```\n\nThe context is linked to the LiveView process — it terminates and\ncleans up automatically when the connection closes. No explicit\n`terminate` callback needed.\n\n### Granular API groups\n\nContexts can load individual API groups instead of the full browser bundle:\n\n```elixir\nQuickBEAM.Context.start_link(pool: pool, apis: [:beam, :fetch])  # 231 KB\nQuickBEAM.Context.start_link(pool: pool, apis: [:beam, :url])    # 108 KB\nQuickBEAM.Context.start_link(pool: pool, apis: false)            #  58 KB\nQuickBEAM.Context.start_link(pool: pool)                         # 429 KB (all browser APIs)\n```\n\nAvailable groups: `:fetch`, `:websocket`, `:worker`, `:channel`,\n`:eventsource`, `:url`, `:crypto`, `:compression`, `:buffer`, `:dom`,\n`:console`, `:storage`, `:locks`. Dependencies auto-resolve.\n\n### Per-context resource limits\n\n```elixir\n{:ok, ctx} = QuickBEAM.Context.start_link(\n  pool: pool,\n  memory_limit: 512_000,      # per-context allocation limit (bytes)\n  max_reductions: 100_000      # opcode budget per eval/call\n)\n\n# Track per-context memory\n{:ok, %{context_malloc_size: 92_000}} = QuickBEAM.Context.memory_usage(ctx)\n```\n\nExceeding `memory_limit` triggers OOM. Exceeding `max_reductions`\ninterrupts the current eval but keeps the context usable for\nsubsequent calls.\n\n## API surfaces\n\nQuickBEAM can load browser APIs, Node.js APIs, or both:\n\n```elixir\n# Browser APIs only (default)\nQuickBEAM.start(apis: [:browser])\n\n# Node.js compatibility\nQuickBEAM.start(apis: [:node])\n\n# Both\nQuickBEAM.start(apis: [:browser, :node])\n\n# Bare QuickJS engine — no polyfills\nQuickBEAM.start(apis: false)\n```\n\n## Node.js compatibility\n\nLike Bun, QuickBEAM implements core Node.js APIs. BEAM-specific\nextensions live in the `Beam` namespace.\n\n```elixir\n{:ok, rt} = QuickBEAM.start(apis: [:node])\n\nQuickBEAM.eval(rt, \"\"\"\n  const data = fs.readFileSync('/etc/hosts', 'utf8');\n  const lines = data.split('\\\\n').length;\n  lines\n\"\"\")\n# =\u003e {:ok, 12}\n```\n\n| Module | Coverage |\n|---|---|\n| `process` | `env`, `cwd()`, `platform`, `arch`, `pid`, `argv`, `version`, `nextTick`, `hrtime`, `stdout`, `stderr` |\n| `path` | `join`, `resolve`, `basename`, `dirname`, `extname`, `parse`, `format`, `relative`, `normalize`, `isAbsolute`, `sep`, `delimiter` |\n| `fs` | `readFileSync`, `writeFileSync`, `appendFileSync`, `existsSync`, `mkdirSync`, `readdirSync`, `statSync`, `lstatSync`, `unlinkSync`, `renameSync`, `rmSync`, `copyFileSync`, `realpathSync`, `readFile`, `writeFile` |\n| `os` | `platform()`, `arch()`, `type()`, `hostname()`, `homedir()`, `tmpdir()`, `cpus()`, `totalmem()`, `freemem()`, `uptime()`, `EOL`, `endianness()` |\n\n`process.env` is a live Proxy — reads and writes go to `System.get_env` / `System.put_env`.\n\n## Resource limits\n\n```elixir\n{:ok, rt} = QuickBEAM.start(\n  memory_limit: 10 * 1024 * 1024,  # 10 MB heap\n  max_stack_size: 512 * 1024        # 512 KB call stack\n)\n```\n\n## Introspection\n\n```elixir\n# List user-defined globals (excludes builtins)\n{:ok, [\"myVar\", \"myFunc\"]} = QuickBEAM.globals(rt, user_only: true)\n\n# Get any global's value\n{:ok, 42} = QuickBEAM.get_global(rt, \"myVar\")\n\n# Runtime diagnostics\nQuickBEAM.info(rt)\n# %{handlers: [\"db.query\"], memory: %{...}, global_count: 87}\n```\n\n### Bytecode disassembly\n\nDisassemble QuickJS bytecode into structured Elixir terms — like\n`:beam_disasm` for the BEAM:\n\n```elixir\n{:ok, bc} = QuickBEAM.disasm(rt, \"function fib(n) { if (n \u003c= 1) return n; return fib(n-1) + fib(n-2) }\")\nfib = hd(bc.cpool)\n\nfib.name       # \"fib\"\nfib.args       # [\"n\"]\nfib.stack_size # 4\nfib.opcodes\n# [\n#   {0, :get_arg0, 0},\n#   {1, :push_1, 1},\n#   {2, :lte},\n#   {3, :if_false8, 7},\n#   {5, :get_arg0, 0},\n#   {6, :return},\n#   {7, :get_var, \"fib\"},\n#   {12, :get_arg0, 0},\n#   {13, :push_1, 1},\n#   {14, :sub},\n#   {15, :call1, 1},\n#   ...\n# ]\n```\n\n`disasm/1` works on precompiled bytecode binaries without a runtime:\n\n```elixir\n{:ok, bytecode} = QuickBEAM.compile(rt, source)\n# later, even on a different node:\n{:ok, %QuickBEAM.Bytecode{}} = QuickBEAM.disasm(bytecode)\n```\n\n## DOM\n\nEvery runtime has a live DOM tree backed by [lexbor](https://github.com/lexbor/lexbor) (the C library\nbehind PHP 8.4's DOM extension and Elixir's `fast_html`). JS gets a full `document` global\nwith spec-compliant prototype chains (`instanceof HTMLElement` works), node identity\n(`el.parentNode === el.parentNode`), and uppercase `tagName` for HTML elements:\n\n```javascript\ndocument.body.innerHTML = '\u003cul\u003e\u003cli class=\"item\"\u003eOne\u003c/li\u003e\u003cli class=\"item\"\u003eTwo\u003c/li\u003e\u003c/ul\u003e';\nconst items = document.querySelectorAll(\"li.item\");\nitems[0].textContent; // \"One\"\nitems[0] instanceof HTMLElement; // true\n```\n\nElixir can read the DOM directly — no JS execution, no re-parsing:\n\n```elixir\n{:ok, rt} = QuickBEAM.start()\nQuickBEAM.eval(rt, ~s[document.body.innerHTML = '\u003ch1 class=\"title\"\u003eHello\u003c/h1\u003e'])\n\n# Returns Floki-compatible {tag, attrs, children} tuples\n{:ok, {\"h1\", [{\"class\", \"title\"}], [\"Hello\"]}} = QuickBEAM.dom_find(rt, \"h1\")\n\n# Batch queries\n{:ok, items} = QuickBEAM.dom_find_all(rt, \"li\")\n\n# Extract text and attributes\n{:ok, \"Hello\"} = QuickBEAM.dom_text(rt, \"h1\")\n{:ok, \"/about\"} = QuickBEAM.dom_attr(rt, \"a\", \"href\")\n\n# Serialize back to HTML\n{:ok, html} = QuickBEAM.dom_html(rt)\n```\n\n## Web APIs\n\nStandard browser APIs backed by BEAM primitives, not JS polyfills:\n\n| JS API | BEAM backend |\n|---|---|\n| `fetch`, `Request`, `Response`, `Headers` | `:httpc` |\n| `document`, `querySelector`, `createElement` | lexbor (native C DOM) |\n| `URL`, `URLSearchParams` | `:uri_string` |\n| `EventSource` (SSE) | `:httpc` streaming |\n| `WebSocket` | `Mint.WebSocket` |\n| `Worker` | BEAM process per worker |\n| `BroadcastChannel` | `:pg` (distributed) |\n| `navigator.locks` | GenServer + monitors |\n| `localStorage` | ETS |\n| `crypto.subtle` | `:crypto` |\n| `crypto.getRandomValues`, `randomUUID` | Zig `std.crypto.random` |\n| `ReadableStream`, `WritableStream`, `TransformStream` | Pure TS with `pipeThrough`/`pipeTo` |\n| `TextEncoder`, `TextDecoder` | Native Zig (UTF-8) |\n| `TextEncoderStream`, `TextDecoderStream` | Stream + Zig encoding |\n| `CompressionStream`, `DecompressionStream` | `:zlib` |\n| `Buffer` | `Base`, `:unicode` |\n| `EventTarget`, `Event`, `CustomEvent` | Pure TS |\n| `AbortController`, `AbortSignal` | Pure TS |\n| `Blob`, `File` | Pure TS |\n| `DOMException` | Pure TS |\n| `setTimeout`, `setInterval` | Timer heap in worker thread |\n| `console` (log, warn, error, debug, time, group, …) | Erlang Logger |\n| `atob`, `btoa` | Native Zig |\n| `performance.now` | Nanosecond precision |\n| `structuredClone` | QuickJS serialization |\n| `queueMicrotask` | `JS_EnqueueJob` |\n\n## Data conversion\n\nNo JSON in the data path. JS values map directly to BEAM terms:\n\n| JS | Elixir |\n|---|---|\n| `number` (integer) | `integer` |\n| `number` (float) | `float` |\n| `string` | `String.t()` |\n| `boolean` | `boolean` |\n| `null` | `nil` |\n| `undefined` | `nil` |\n| `Array` | `list` |\n| `Object` | `map` (string keys) |\n| `Uint8Array` | `binary` |\n| `Symbol(\"name\")` | `:name` (atom) |\n| `Infinity` / `NaN` | `:Infinity` / `:NaN` |\n| PID / Ref / Port | Opaque JS object (round-trips) |\n\n## TypeScript\n\nType definitions for the BEAM-specific JS API:\n\n```jsonc\n// tsconfig.json\n{\n  \"compilerOptions\": {\n    \"types\": [\"./path/to/quickbeam.d.ts\"]\n  }\n}\n```\n\nThe `.d.ts` file covers the `Beam` bridge API, opaque BEAM terms\n(`BeamPid`, `BeamRef`, `BeamPort`), and the `compression` helper.\nStandard Web APIs are typed by TypeScript's `lib.dom.d.ts`.\n\n## TypeScript toolchain\n\nQuickBEAM includes a built-in TypeScript toolchain via [OXC](https://oxc.rs)\nRust NIFs — no Node.js or Bun required:\n\n```elixir\n# Evaluate TypeScript directly\n{:ok, rt} = QuickBEAM.start()\nQuickBEAM.eval_ts(rt, \"const x: number = 40 + 2; x\")\n# =\u003e {:ok, 42}\n\n# Transform, minify, bundle — available as QuickBEAM.JS.*\n{:ok, js} = QuickBEAM.JS.transform(\"const x: number = 1\", \"file.ts\")\n{:ok, min} = QuickBEAM.JS.minify(\"const x = 1 + 2;\", \"file.js\")\n\n# Bundle multiple modules into a single IIFE\nfiles = [\n  {\"utils.ts\", \"export function add(a: number, b: number) { return a + b }\"},\n  {\"main.ts\", \"import { add } from './utils'\\nconsole.log(add(1, 2))\"}\n]\n{:ok, bundle} = QuickBEAM.JS.bundle(files)\n```\n\n## npm packages\n\nQuickBEAM ships with a built-in npm client — no Node.js required.\n\n```sh\nmix npm.install sanitize-html\n```\n\nThe `:script` option auto-resolves imports. Point it at a TypeScript file\nthat imports npm packages, and QuickBEAM bundles everything at startup:\n\n```elixir\n# priv/js/app.ts\nimport sanitize from 'sanitize-html'\n\nBeam.onMessage((html: string) =\u003e {\n  Beam.callSync(\"done\", sanitize(html))\n})\n```\n\n```elixir\n{QuickBEAM, name: :sanitizer, script: \"priv/js/app.ts\", handlers: %{...}}\n```\n\nNo build step, no webpack, no esbuild. TypeScript is stripped, imports\nare resolved from `node_modules/`, and everything is bundled into a\nsingle script via OXC — all at runtime startup.\n\nYou can also bundle from disk programmatically:\n\n```elixir\n{:ok, js} = QuickBEAM.JS.bundle_file(\"src/main.ts\")\n```\n\n## Performance\n\nvs QuickJSEx 0.3.1 (Rust/Rustler, JSON serialization):\n\n| Benchmark | Speedup |\n|---|---|\n| Function call — small map | **2.5x faster** |\n| Function call — large data | **4.1x faster** |\n| Concurrent JS execution | **1.35x faster** |\n| `Beam.callSync` (JS→BEAM) | 5 μs overhead (unique to QuickBEAM) |\n| Startup | ~600 μs (parity) |\n\nContext pool vs individual runtimes at scale:\n\n| | Runtime (1:1 thread) | Context (pooled) |\n|---|---|---|\n| JS heap per instance | ~530 KB | ~429 KB (full) / ~58 KB (bare) |\n| OS thread stack | ~2.5 MB each | shared (4 threads total) |\n| OS threads at 10K | 10,000 | 4 (configurable) |\n| Total RAM at 10K | ~30 GB | ~4.2 GB (full) / ~570 MB (bare) |\n\nSee [`bench/`](https://github.com/elixir-volt/quickbeam/tree/master/bench) for details.\n\n## When to use what\n\n| Use case | Module | Why |\n|---|---|---|\n| One-off eval, scripting | `QuickBEAM` (Runtime) | Simple, full isolation |\n| SSR request pool | `QuickBEAM.Pool` | Checkout/checkin with reset |\n| Per-connection state (LiveView) | `QuickBEAM.Context` | Lightweight, thousands concurrent |\n| Sandboxed user code | `QuickBEAM` or `Context` with `apis: false` | Memory limits, reduction limits, timeouts |\n\n## Development\n\n```sh\nmix ci\n```\n\nRuns the full project quality gate: formatting, Credo, Dialyzer, Zig lint,\nTypeScript lint, duplicate-code checks, and tests.\n\n## Examples\n\n- [`examples/chat_room/`](https://github.com/elixir-volt/quickbeam/tree/master/examples/chat_room) — real-time chat\n  with Phoenix Channels. Each room is a supervised QuickBEAM runtime; JS\n  broadcasts become PubSub pushes to WebSocket clients.\n- [`examples/ai_agent/`](https://github.com/elixir-volt/quickbeam/tree/master/examples/ai_agent) — conversational\n  AI agent with streaming, tool use, and pluggable LLM backends. JS\n  orchestrates the conversation loop; Elixir provides the I/O.\n- [`examples/counter_live/`](https://github.com/elixir-volt/quickbeam/tree/master/examples/counter_live) — LiveView\n  counter where each session gets a ~58 KB JS context from a shared pool.\n  The simplest QuickBEAM + Phoenix integration.\n- [`examples/ssr/`](https://github.com/elixir-volt/quickbeam/tree/master/examples/ssr) — Preact SSR with a pool of runtimes\n  and native DOM. Elixir reads the DOM directly — no `renderToString`.\n- [`examples/rule_engine/`](https://github.com/elixir-volt/quickbeam/tree/master/examples/rule_engine) — user-defined business\n  rules (pricing, validation, transforms) in sandboxed JS runtimes with\n  `apis: false`, memory limits, timeouts, and hot reload.\n- [`examples/live_dashboard/`](https://github.com/elixir-volt/quickbeam/tree/master/examples/live_dashboard) — Workers (BEAM\n  processes) compute metrics in parallel and broadcast results via\n  BroadcastChannel (`:pg`). Crash recovery via OTP supervisor.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-volt%2Fquickbeam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felixir-volt%2Fquickbeam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-volt%2Fquickbeam/lists"}