HelloWorld on Our First Platform: Cloudflare
The first milestone in a portability story is never glamorous. It’s the moment you can take one tiny program, run it in your own tooling, and also package it for a real platform without rewriting it.
For Distlang, that moment is a Worker-style “Hello World” running end-to-end, with Cloudflare as our first target. Cloudflare Workers is a natural starting point because it has a clear runtime model and a well-defined deployment toolchain.
If you want to follow along with the exact code in this post, the example lives here:
https://github.com/distlanglabs/distlang/tree/main/examples/helloworld
The smallest Worker that matters
Here is the whole example:
examples/helloworld/index.js
https://github.com/distlanglabs/distlang/blob/main/examples/helloworld/index.js
export default {
async fetch(request, env, ctx) {
console.log("Hello worker fetch will return a Response object");
return new Response("Hello Worker!");
},
};
This matches the Worker module shape Cloudflare expects: your module exports a default object with an async fetch() handler. When a request arrives, the platform calls fetch(request, env, ctx) and expects a Response back.
Running locally: what Goja is and why we use it
Before deploying anything, we want a tight feedback loop. Distlang can run this Worker locally by starting a small HTTP server and routing incoming requests into default.fetch.
The local runtime in Phase 0 is powered by Goja. Goja is a JavaScript engine implemented in Go, which means Distlang can execute JavaScript Workers directly inside the Distlang CLI without depending on Node.js. At this stage, the goal is simple: one binary that can compile your Worker-shaped module and execute it immediately, so we can iterate on semantics and portability quickly.
From the repo’s examples/helloworld/ directory:
make run
Then, in another terminal:
curl -i http://127.0.0.1:5656
Here is the response from my local run:
HTTP/1.1 200 OK
Date: Fri, 06 Mar 2026 21:12:17 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Hello Worker!
From one source file to a Cloudflare Worker
Once the Worker runs locally, the next step is to turn the same source file into something Cloudflare can run. Distlang’s build step generates platform artifacts under dist/, including a Cloudflare Worker entrypoint and the Wrangler configuration needed to run it with Cloudflare’s tooling.
make build
That will produce outputs in examples/helloworld/dist/cloudflare/ (including worker.js and wrangler.toml). These files are generated so they can be driven directly by Wrangler, keeping the deploy story aligned with how Cloudflare expects Workers projects to behave.
To run the generated Worker under Wrangler locally:
make dev
This starts Wrangler’s local server. Here is what I see from a local run (trimmed to the interesting lines):
wrangler dev
wrangler 4.71.0
----------------
Starting local server...
[wrangler:info] Ready on http://localhost:8787
And hitting that local dev server returns the same body:
curl -i http://127.0.0.1:8787/
HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain;charset=UTF-8
Hello Worker!
And to deploy it, you first scaffold the local Cloudflare credential file:
make cloudflare-init
On my machine this prints:
../../bin/distlang target init --target=cloudflare --path=.
Skipped existing file targets/cloudflare/cloudflare.env.example
Skipped existing file targets/cloudflare/cloudflare.env
Initialized cloudflare target in targets/cloudflare
Fill in examples/helloworld/targets/cloudflare/cloudflare.env (created from the template), then deploy:
make deploy
Here is the output from a successful deploy run (trimmed slightly):
wrangler deploy
wrangler 4.71.0
----------------
ERROR Failed to fetch auth token: 400 Bad Request
Attempting to login via OAuth...
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?...
Successfully logged in.
Uploaded index
Deployed index triggers
https://index.georgethomas.workers.dev
Current Version ID: 9583b635-9726-451f-88a8-a44465eef380
And if you curl the deployed Worker, you should see the same response body:
curl -i https://index.georgethomas.workers.dev
HTTP/2 200
content-type: text/plain;charset=UTF-8
content-length: 13
Hello Worker!
Why this matters for platform independence
Cloudflare is the first target, but it’s not the destination. The larger intent of Distlang is to make “where code runs” a build choice rather than an application rewrite. This HelloWorld is small by design: it gives us a concrete place to nail down the Worker execution model, learn where platforms differ, and harden our compiler and runtime so the same source program can be carried to more environments over time.