HBForge/Examples
01 · Applications

Web API — full CRUD

A minimal REST API: list, get, create, update, delete. State is in-memory; swap for forge/data to back it with Postgres/SQLite.

forge/serverNodeBunDenoCF Workers
Code
web-api.js
const { WebApp } = require(class="tk-str">'@hyperbridge/forge/server');
const app   = new WebApp();
const posts = new Map();
let id = 1;

app.get(class="tk-str">'/posts',      (c) => c.json([...posts.values()]));
app.get(class="tk-str">'/posts/:id',  (c) => {
  const p = posts.get(+c.req.param(class="tk-str">'id'));
  return p ? c.json(p) : c.notFound();
});
app.post(class="tk-str">'/posts', async (c) => {
  const body = await c.req.json();
  const post = { id: id++, ...body };
  posts.set(post.id, post);
  return c.json(post, 201);
});
app.put(class="tk-str">'/posts/:id', async (c) => {
  const i = +c.req.param(class="tk-str">'id');
  posts.set(i, { id: i, ...(await c.req.json()) });
  return c.json(posts.get(i));
});
app.delete(class="tk-str">'/posts/:id', (c) => {
  posts.delete(+c.req.param(class="tk-str">'id'));
  return c.body(null, 204);
});

app.listen(3000);
How it works

WebApp is HBForge's Fetch-API-native HTTP layer. Each handler receives a Context (c) that exposes the parsed request and response builders.

c.req.param('id') reads the trie-router path parameter, c.req.json() parses and caches the body, and c.json(data, status) returns a standard Response. The body cache means you can safely call .json() and .text() on the same request.

Same code runs on Node (app.listen(3000)), Bun (export default app), Deno (Deno.serve(app.fetch)), and Cloudflare Workers.

Try it
Quickstart
npm i @hyperbridge/forge && node app.js
Related modules