Skip to content

Express Web Server

A small Express 5 blog app — JSON API (/api/posts, /api/posts/:slug, /api/runtime), server-rendered article pages, and a static HTML/CSS/JS frontend — running on GJS through @gjsify/http. Express imports unmodified from npm; gjsify’s Node compat layer serves every http.Server / IncomingMessage / ServerResponse API call Express reaches for.

PillarWhat Express needs
@gjsify/httphttp.createServer(), Server.listen(), full IncomingMessage (close-only-via-destroy per Node semantics) + ServerResponse API
@gjsify/streamreq.pipe(res), body parsing
@gjsify/eventsEventEmitter with enumerable prototype methods (Express 5 requires this for some middleware)
@gjsify/urlURL parsing in Express’s route matcher
libsoup-3.0The TCP listener + HTTP/1.1 parser under @gjsify/http
gjsify showcase express-webserver

Starts a Gtk.Application-less GLib mainloop with Express bound to http://127.0.0.1:3000. Open the page or hit the API with curl:

curl http://127.0.0.1:3000/api/posts
# → {"count":…,"posts":[…]}
curl http://127.0.0.1:3000/api/runtime
# → {"runtime":"GJS","platform":"linux","version":"…","time":"…"}

The same Express app would behave identically under Node — there’s no GJS-specific branch in src/index.ts. That’s the load-bearing claim.

cd showcases/node/express-webserver
gjsify run build
gjsify run start:node

The package ships both start (GJS) and start:node scripts; same src/index.ts, two bundles (dist/index.gjs.js, dist/index.node.mjs).

showcases/node/express-webserver/

  • src/index.ts — the whole Express app: middleware, JSON API, server-rendered HTML pages, app.listen() (npm express import, no @gjsify/* in the request path)
  • src/data/posts.ts — in-memory blog post fixtures consumed by the API + HTML routes
  • src/public/ — static frontend (index.html, style.css, app.js) served via express.static()

Express is the most-deployed Node web framework on the planet. If gjsify’s http package can carry Express 5 unmodified — including middleware composition, error handling, route matching — then arbitrary npm web apps targeting Node tend to “just work” on GJS too. This showcase is the canary.

Integration coverage for the broader npm web ecosystem (Socket.IO, axios, WebTorrent, …) lives under tests/integration/ — they all dovetail with the same @gjsify/http + @gjsify/stream surface.

  • refs/socket.io/ — Socket.IO uses http.Server directly; the integration suite under tests/integration/socket.io/ is the multi-client validation
  • refs/undici/ — Node’s fetch / HTTP client reference, separate from @gjsify/http but the same socket plumbing
  • @gjsify/http — the package itself