Webernetes: Kubernetes in the browser, minus the cluster
Kubernetes in the browser.
At a glance
- What is it?
- Webernetes is a TypeScript port of a Kubernetes subset that boots a simulated cluster inside the browser, with no backend components. It is built for interactive Kubernetes content, not for running real workloads.
- Who is it for?
- Adopt Webernetes if you are building interactive Kubernetes teaching material and can live with HTTP and DNS only, a fixed node count at construction time, and no volume mounts, resources, or affinity rules. Do not adopt it if you need to run real container images or exercise the full Kubernetes API surface.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 37 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Webernetes solves: Kubernetes content that outlives its cluster
Interactive Kubernetes tutorials normally need a real cluster behind them. That means infrastructure to spin clusters up, someone to keep that infrastructure working, and a content artifact that decays as the cluster version drifts. The ngrok team wanted to make visual and interactive content about Kubernetes without maintaining that infrastructure, so they ported a subset of Kubernetes into the browser instead. The README frames the goal as longevity: content that lives for a long time because the maintenance burden is much smaller.
The audience is narrow and specific. This is for people building interactive Kubernetes teaching material, demos, or visualizations that run in a browser tab. It is not for anyone who wants a Kubernetes cluster to run workloads in, and the README is explicit that running real images from Docker Hub is not a goal. If you want a local cluster for real containers, this is the wrong tool and the README says so indirectly by scoping itself to simulation.
How the simulator works: images, a three-node cluster, and an HTTP-only network
The architecture has three moving parts. You define images in TypeScript by extending BaseImage, you register those images with a Cluster instance, and you apply manifests to that cluster exactly as you would with kubectl. The Cluster class spins up three nodes named node-1, node-2, and node-3 by default. The README notes that the node count can be changed with a constructor parameter, and that arbitrarily adding and removing nodes at runtime is a future goal rather than a current feature.
The interesting design decision is the network. Webernetes does not emulate the network stack far enough for UDP, and the README says TCP is only sort of supported in the same sense. What containers can actually do is speak HTTP and DNS to each other. The README states that this is intentional and that the author does not anticipate wanting to change it. As a consequence, IP families are not modeled either. Round-robin load balancing across the pods behind a Service is implemented, and Services get EndpointSlices, though the README notes the usual sharding into groups of 100 pods is not implemented, purely for simplicity.
On the control plane side, the README claims parity with upstream controllers for ReplicaSets and Deployments, including RollingUpdate and Recreate strategies, plus a namespace controller separate from the garbage collector. Events fire with messages and can be inspected, though the README admits there is no event aggregation and that not all fields may be present or correct. That is an honest caveat worth taking at face value.
Installing Webernetes and running a first pod with a NodePort service
The package is published on npm as @ngrok/webernetes. The README's install step is a single npm command:
npm install @ngrok/webernetesAfter that you define an image. The class below declares an image name and version that form the label you reference in a container spec, provides a default command, and returns a promise from exec that resolves only when the process is killed. That last detail matters: the README explains that returning an exit code of 0 immediately would unregister the HTTP listener, because the container would have exited.
import { BaseImage, type ProcessContext } from "@ngrok/webernetes";
class MyImage extends BaseImage {
static readonly imageName = "my-image";
static readonly imageVersion = "1.0";
readonly defaultCommand = ["server"];
override async exec(ctx: ProcessContext, argv: readonly string[]): Promise<number> {
if (argv[0] !== "server") {
return await super.exec(ctx, argv);
}
ctx.listenHttp(8080, async (request) => ({
statusCode: 200,
body: "hello, world\n",
}));
return await ctx.waitUntilKilled();
}
}Registering the image and booting the cluster takes two calls. The README notes that init spins up a three-node cluster by default and that this cannot currently be changed through this path, even though the constructor accepts a node count.
import { Cluster } from "@ngrok/webernetes";
const cluster = new Cluster();
cluster.registerImage(MyImage);
await cluster.init();Applying a Pod and a NodePort Service is where the shape of the API becomes clear. The Service selects the pod by label and forwards port 80 to target port 8080 on node port 31000. The README's example then fetches through the node hostname and reads the body back as the string the image returned.
await cluster.apply([
{
apiVersion: "v1",
kind: "Service",
metadata: { name: "my-service" },
spec: {
type: "NodePort",
ports: [{ port: 80, targetPort: 8080, nodePort: 31000, protocol: "TCP" }],
selector: { app: "my-pod" },
},
},
]);
const resp = await cluster.fetch("http://node-1:31000");
const text = await resp.text(); // hello, worldThere is a set of runnable examples in the repository under examples/, with package scripts named example:single-pod, example:node-port, example:two-pods, example:deployment, and example:cross-namespace. Those scripts are the fastest way to see the intended usage without writing an image from scratch.
What Webernetes does not implement, and when that matters
The README's own list of gaps is the most useful part of the documentation. Pods do not support init containers or ephemeral containers, gRPC probing, volume mounts, affinity rules, or resources. Services support ClusterIP and NodePort only; LoadBalancer and ExternalName are not implemented. UDP is out, and TCP is only as real as the HTTP and DNS layer above it. EndpointSlice sharding into groups of 100 is absent. Event aggregation is absent.
The failure mode that will bite most people first is the image model. You cannot pull an image from a registry. Every container you run must be a TypeScript class extending BaseImage that you have registered with the cluster. If your teaching material depends on a real nginx or redis image, Webernetes cannot help you, and the README states this as a design boundary rather than a missing feature.
The second trap is the network. Because only HTTP and DNS are modeled, any exercise about raw TCP, UDP, or IP family behaviour will either fail or silently teach the wrong thing. The README says the author does not anticipate changing this, so treat it as permanent rather than a roadmap item. The third is the fixed node count at init time. The README describes changing the node count through a constructor parameter and separately says the default three-node cluster cannot currently be changed, which is a contradiction a reader has to resolve by reading the source. That kind of ambiguity is worth flagging before you build a lesson around node topology.
Webernetes against kind, minikube, and the Kubernetes playgrounds
The obvious alternative for teaching Kubernetes is a real local cluster from kind or minikube, or a hosted playground. The difference in approach is fundamental rather than incremental. kind and minikube run actual container images through a real container runtime and a real API server, so everything you demonstrate is genuine, including the parts Webernetes leaves out: volumes, resources, affinity, gRPC probes, LoadBalancer services. The cost is that they require a machine, a runtime, and maintenance, and they cannot be embedded in a web page.
Webernetes trades that fidelity for zero backend. There is no server component, no container runtime, and no cluster to keep alive, which is exactly what makes it embeddable in browser-based interactive content. If your goal is a tutorial that a reader can click through without installing anything, the local-cluster alternatives cannot compete on that axis. If your goal is to teach how Kubernetes actually schedules and runs containers, Webernetes will mislead by omission, because the parts it does not implement are precisely the parts that make the scheduler interesting.
Maintenance, releases, and the Apache-2.0 licence
The repository is not archived, and the last push was on 2026-08-13, the same day as the 0.6.1 release. The release history shows 0.6.0 earlier that day and 0.5.5 on 2026-08-07, so the version cadence has been tight. The presence of a .changeset/ directory and a changeset:publish script indicates the project uses Changesets for versioning and publishing, which is a normal signal that releases are deliberate rather than ad hoc.
Webernetes is licensed under Apache-2.0, and the repository carries both a LICENSE and a NOTICE file, with NOTICE included in the published package files. Apache-2.0 permits commercial use and modification and includes a patent grant, but it also requires that you preserve the NOTICE file and state significant changes. For a simulator you embed in teaching content, that is unlikely to be a practical obstacle; for a product built on top of it, the notice obligations are the part to read. This is not legal advice, and the licence text is the authority.
The upgrade cost is the part that deserves attention. The README describes the project as very experimental, with the API subject to change and resource support subject to change. There is no documented migration path between minor versions in the README, so pinning a version and reading the changelog before upgrading is the only reliable approach.
Editorial conclusion
Adopt Webernetes if you are building interactive Kubernetes teaching material and can live with HTTP and DNS only, a fixed node count at construction time, and no volume mounts, resources, or affinity rules. Do not adopt it if you need to run real container images or exercise the full Kubernetes API surface. Before you commit, verify that the resources you plan to teach are in the implemented list, that your NodePort and ClusterIP service assumptions hold, and that the version you install is the one whose behaviour you have read about. The README states plainly that the API is subject to change and that resource support may change too, so pin the version you build against.
Frequently asked questions
What is Webernetes and why is it used?
Webernetes is a port of a subset of Kubernetes that runs in the browser with no backend server components. It exists so that visual and interactive Kubernetes content can be built without maintaining infrastructure for spinning up real clusters.
What is the difference between Docker and Webernetes?
Docker runs real container images from a registry. Webernetes does not run real images from Docker Hub, and the README states that doing so is not a goal; instead you define images as TypeScript classes extending BaseImage and register them with a Cluster.
Can I learn Kubernetes in 2 days with Webernetes?
Webernetes covers a subset of Kubernetes, including Pods, Services, ReplicaSets, Deployments, namespaces, and events, but it omits volume mounts, resources, affinity rules, init containers, and LoadBalancer services. The README does not make any claim about how long learning takes.
What is the difference between Webernetes and OpenShift?
OpenShift is a Kubernetes distribution for running real workloads. Webernetes is a browser-based simulator that supports ClusterIP and NodePort services, speaks HTTP and DNS only, and cannot run real container images.
Community notes