Skip to content

The web framework for AI agents

WebJs is a full-stack framework built on web components, SSR, and progressive enhancement with zero build step. Lean enough for an agent to read end to end. Runs on Node 24+ or Bun.

npm create webjs@latest my-app

Real HTML first. JavaScript only when it earns it.

Pages and components render to real HTML on the server, so the page reads, links navigate, and forms submit before a single script loads. There is no hydration runtime to pay for, and dead JavaScript is statically elided, never shipped.

components/like-button.ts
class LikeButton extends WebComponent({ count: Number }) {
  render() {
    return html`<button @click=${() => this.count++}>
      ♥ ${this.count}
    </button>`;
  }
}
LikeButton.register('like-button');

// No build step. No bundler. No virtual DOM.
// The panel to the right is this file, server-rendered
// and upgraded in place. Click it.
live
Server-rendered first, then upgraded. Click it.
No hydration runtimeContent readsLinks navigateForms submitDisplay components ship 0 KB

The whole stack, in three files

A component, a server action, and a page. No build, no boilerplate, all web standards.

Interactive component

components/like-button.ts
import { WebComponent, html, signal } from '@webjsdev/core';

class LikeButton extends WebComponent {
  likes = signal(0);
  render() {
    return html`<button @click=${() => this.likes.set(this.likes.get() + 1)}>
      ♥ ${this.likes.get()}
    </button>`;
  }
}
LikeButton.register('like-button');

Server action (RPC)

actions/get-post.server.ts
'use server';
import { eq } from 'drizzle-orm';
import { db } from '#db/connection.server.ts';
import { posts } from '#db/schema.server.ts';

// Import this from a page or client component. WebJs rewrites
// the import into a typed RPC stub (the real call at SSR). No
// fetch by hand.
export async function getPost(id) {
  const [post] = await db.select().from(posts).where(eq(posts.id, id));
  return post;
}

SSR page

app/posts/[id]/page.ts
import { html, notFound } from '@webjsdev/core';
import { getPost } from '#actions/get-post.server.ts';
import '#components/like-button.ts';

export default async function Post({ params }) {
  const post = await getPost(params.id);
  if (!post) notFound();
  return html`<article>
    <h1>${post.title}</h1>
    <like-button></like-button>
  </article>`;
}

Modern full-stack, on web standards

Everything you need to ship, none of the build toolchain you don't.

Zero build step

Source files run as-is, so what you write is exactly what the browser serves. An AI agent debugs against the real served code, never a bundled or minified artifact.

bun dev
$ bun run dev
Ready on http://localhost:5001
page.ts reloaded in 3ms

Light DOM web components

Web components that render to light DOM, so Tailwind and global CSS just work, no shadow plumbing.

<like-button>
<button class="px-3 rounded bg-accent">
♥ Like
</button>
</like-button>

Server actions (RPC)

Mark a file 'use server' and import it. Date, Map, Set, BigInt, and Blob all round-trip across the wire with real http verbs (GET, POST, PUT, PATCH, DELETE).

Client
RPC
Server action

Streaming Suspense

Stream slow regions progressively. The shell paints instantly, fallbacks render, and async data fills in as it resolves.

streaming data chunk...

Progressive enhancement

Real HTML first. Links navigate, forms submit, and pages read before JavaScript loads. No hydration overhead.

No hydration lock Static elision

Built-in essentials

Auth, sessions, cache, rate limits, and websockets are built right in. Pluggable adapters, zero glue.

Auth & sessions
Rate limiting

Light enough for AI

A zero build step means the source you read is what runs. Because the framework ships without compilation layers, an AI agent can read and reason about the entire WebJs source end to end, straight from node_modules.

~29 KB
Client runtime, gzipped

A minimal Next.js client bundle is ~99 KB gzipped including React. WebJs is self-sufficient at ~29 KB, 3.4x lighter on the wire.

0 build
Instant agent loops

No compilation, no bundler. Agents edit, run tests, and verify in the browser in milliseconds.

100%
Web standards

Standard-aligned Web Component lifecycles, so models write components reliably.

~16k
LLM-context friendly

Under 6.5k lines of client runtime, ~16k for the whole stack, small enough to fit an LLM context window.

Familiar from day one. WebJs uses Next.js-style file-based routing and lit-style web components, conventions both people and agents already know.

Gzipped production sizes. A Next.js app ships a client bundle around ~99 KB gzipped (react, react-dom, and the Next runtime); @webjsdev/core is self-sufficient at ~29 KB gzipped with zero runtime dependencies and no build step.

Start where you are

Full-stack

Pages + API + components

SSR pages, web components, server actions, Drizzle, streaming, and a browsable feature gallery. Auth (login, sessions, a protected route) ships as a gallery card. The default.

app/page.ts
components/counter.ts
actions/posts.server.ts
npm create webjs@latest my-app
Backend (API)

Route handlers + Database

A backend-only app, no UI or SSR. File-based route handlers, modules, middleware, rate limiting, WebSockets, a database, and a backend-features gallery.

app/api/users/route.ts
app/api/chat/route.ts
middleware.ts
npm create webjs@latest my-api -- --template api

Prefer Bun? Add --runtime bun to either template, or run bun create webjs my-app to flavor the scaffold for Bun automatically.

Start building with AI

Run the command below in your terminal, launch your AI coding agent from the app folder, and tell it what you would like to build.

npm create webjs@latest my-app