Build apps with AI on your machines.

Elements makes you and your agents insanely better at building apps. Apps that work the first time and keep working, for one predictable monthly bill.

Screenshot: VS Code with the build state Ok, and the agent saying the build is greenScreenshot: VS Code with the build state Ok, and the agent saying the build is green
Elements checks your app while you work. Green means the build is okay.

Join our community.

Come build the next generation of software with us.

Why builders choose Elements.

Build apps with AI that are robust enough to run your business.

Agents write code at superhuman speed. But ask one to build an app and it starts with no building blocks. The popular frameworks are patchworks of packages never designed together, so the agent often writes raw code instead. The result may not work, and it's hard to extend or deploy. Elements gives your agent every building block an app needs, engineered to work together. An always-on project server keeps the app's build state in memory and checks it as you and your agent work.

What we hear from builders

Without Elements
With Elements
“I'm paying for the agent to fix its own bugs.”
Elements checks your agent's work at the speed of file saves. Your agent gets the build state in microseconds and fixes mistakes immediately.
“New features sometimes break old ones that used to work.”
When a change touches an old feature, that feature's tests rerun. Your agent can fix the issue before you or your users run into a broken app.
“The agent deleted my production database.”
Your agent writes a migration instead of changing your live database. If a migration fails, it rolls back.
“I can't get my code out of my vibe coding platform.”
Your app is a folder on your computer that you control. It's written in standard languages any agent understands, so switching costs are low.
“My app went viral, and so did my hosting bill.”
Elements has no usage fees and no AI credits to buy. You bring your own agent, you pay a fixed monthly price per machine, and deploy to low-cost servers you control.

I've been building Elements for more than a decade. The plan was better tooling for people, to make building web apps dramatically simpler. It turns out that same tooling is the linchpin that lets agents build apps that actually work and stay maintainable.

Our business is simple. You own the output. We get paid by creating the best tooling in the world so that you can focus on building.

Chris Mather

Read our history →

No lock-in.

We get paid for the tooling. You own the output, and the Elements runtime packages are MIT licensed.

MIT licensed runtime packages.

You pay for the tooling, not for the runtime packages. The project server, build, test runner and deploy are the tooling. @elements/app is MIT licensed, and it includes the runtime your Elements HTML runs on, which is where you write most of your app. @elements/style is MIT licensed too. A built app runs on plain Node.js.

Standard languages your agent already knows.

Elements was built with painstaking care to stay on standards. Elements HTML is standard HTML with a lightweight extension: TypeScript expressions and a few attributes. Logic is TypeScript, queries and migrations are SQL on Postgres, and styles are CSS. Agents have read more of these languages than any framework's own, so they write them well.

Any agent, any model.

Elements works with any agent and model. Use the agent you have today and switch when a better one comes out.

Pay for the tooling, not for your success.

When a free framework is paid for by hosting, the bill grows as your app does. Elements is one subscription for the tooling, not based on traffic, requests or revenue, and you deploy to servers you control.

Community, without gatekeepers.

We value the people building on Elements. We do not value gatekeepers. In the age of AI, what matters is standard languages and concepts, not framework abstractions only insiders can read. What you learn building on Elements is HTML, TypeScript, SQL and CSS, and it goes wherever you go.

A closer look at Elements.

A project server, app framework and build tooling, engineered from the ground up to work together.

You and your agent build on Elements.

You bring the agent. It works with any agent and model. Elements brings the project server, build tooling, app framework and deployment. It works in the background, doing the right thing as you and your agent write the code. The result is correct code the first time, and still correct a hundred agent sessions later. Keep building on your own machine, then deploy to commodity hardware in seconds.

Here are some of the technologies that make that possible.

An Elements app, running on your machine.

An agent can build a complex app extremely quickly, because everything it needs is already here. Features like realtime pubsub, database migrations, sessions and background jobs all ship with Elements.

An AI agent building an Elements app

The build state is ready before you or your agent asks.

The build has already run by the time you or your agent asks: type check, program analysis, migrations and tests. Your agent reads the diagnostics and corrects the code before reporting the work finished.

An agent reading two build errors and proposing the fixes

An always-on project server, for you and your agent.

One server per project. The first command starts it and everything after connects to the same one: elements build, elements test, elements install, and your editor over LSP. It holds the build state in memory, so checking costs microseconds instead of seconds, and you and your agent can check after every change rather than at the end.

The project server answers in microseconds.

Save a file and the rebuild and the full type check are already done, because the build state never left memory. Your editor shows the result as you type, and your agent asks the same question with -json and reads the answer without parsing a screen.

elements build
State: Ok
Elapsed: 0.000006s
j/k: down/up G/g: bottom/top y: copy q: quit
elements build -json
{
"path": "/Users/cmather/elements/projects/myapp",
"ok": true,
"errorCount": 0,
"warningCount": 0,
"message": "The build is ok.",
"buildGen": 15,
"buildRanAt": "2026-09-21T12:08:15.74752-07:00",
"started": "2026-09-21T12:09:41.121451-07:00",
"finished": "2026-09-21T12:09:41.121457-07:00",
"elapsedSeconds": 0.000006
}

Your agent reads the manual with elements man, and it is online too. Read the manual

A build is everything required to release the app.

Read the config, install packages, crawl, type check, run program analysis, emit, migrate the test database, run the tests, collect diagnostics, migrate the app database, release atomically, hot reload connected browsers.

A build only does the work a change requires. It does more than the popular bundlers and dev servers, and it is faster than all of them. Nothing in it trades speed for convenience. After a save, a build takes a few milliseconds, and the browser usually shows the change within one frame of a 60Hz screen. By the time your agent asks how the build went, it is already done, so the answer takes a few microseconds. That is the result of ten years of engineering on one integrated system.

One of the fastest package installers ever built.

Packages install as part of the build, automatically. It is npm compatible. Install one at version local and it resolves from your package search path, gets watched like the rest of the project, and ships on deploy. No monorepo, no file links.

elements install
State: Ok
Elapsed: 0.000857s
PACKAGES:
@elements/app @0.7.0
@elements/style @0.7.0
@types/node @22.20.3
tslib @2.8.1
5 root, 29 total packages
j/k: down/up G/g: bottom/top y: copy q: quit

Your database stays in sync automatically.

A migration is a .sql file. No ORM, no migration DSL, nothing to learn on top of sql you already know, which is also why an agent writes and edits them correctly, and why you can always run one directly against a database if you need to. Write one and it is applied on save, to the test database before the tests run and to the app database after. Nothing to remember, nothing to run.

elements db migrate
State: Ok
Elapsed: 0.035618s
MIGRATIONS:
node_modules/@elements/app/migrations/2026-07-11-000000-app-baseline.migration.sql [ok]
The application framework baseline migrations.
app/migrations/20260915155829-add-chat.migration.sql [ok]
add chat
j/k: down/up G/g: bottom/top y: copy q: quit

Tests are fast enough to be useful.

The test server runs several processes at once, so tests execute in parallel against the freshly migrated test database. Those processes take part in hot module reload, and a test is rerun when its dependencies change, so a typical test takes a few milliseconds. Fast enough that they stop being the thing you write to be compliant and start being how you find out what you broke.

elements test
State: Ok
Elapsed: 0.000014s
TESTS:
app/pages/home/test.ts [pass]
└─ home [pass]
├─ a fresh install has a channel to open on [pass]
├─ an anonymous visitor cannot create a channel [pass]
├─ a guest creates a channel too [pass]
├─ a signed in user creates a channel under a slug [pass]
├─ a channel name that slugifies to nothing is refused [pass]
└─ two channels cannot share a name [pass]
j/k: down/up G/g: bottom/top y: copy q: quit

Program analysis stops unsafe code.

A database call reachable from the browser does not compile, so it never ships. The report carries the fix and the path that got there.

elements build
State: Error
Elapsed: 0.000010s
ERRORS:
You have 1 error:
1. app/pages/home/template.ehtml:6:10
Security error: cannot call server code from the browser without going through an rpc
function.
Try:
Put the server code inside a function with an @rpc build tag. For example:
/**
* @rpc
*/
export function fn() {}
Then call fn().
5: function onSignIn(email: string) {
6: return sql(`select id from users where email = ${email}`).first();
7: }
Call stack:
2. app/pages/home/template.ehtml:6:10 sql
1. app/pages/home/template.ehtml:32:49 onSignIn
j/k: down/up G/g: bottom/top y: copy q: quit

Deploy to your own servers, with one command.

Any Ubuntu box you can ssh into. Elements builds the release, ships it, runs the migrations and hot reloads the app. No server restart, no dropped connections. A load balancer and TLS certificates come with every deploy machine.

elements deploy
State: Ok
Elapsed: 0.720184s

Peer to peer, and incremental.

A deploy is your project server talking directly to the one on each machine. Yours sends the source graph it already holds, theirs diffs it against the graph it already holds, and only what changed crosses the wire. Both ends are already hot. No queue behind a million other people's builds, no container image to assemble and push, and nothing rebuilt from scratch on the far side.

Load balancing on every machine.

Every machine runs its own load balancer and they find each other automatically. To grow the cluster, add the IP address to config.jsoc and deploy. Whichever machine takes a request balances it across the cluster, with failover to the ones still answering.

Automatic SSL on every machine.

Set a domain, point DNS at the machine, open 80 and 443. Elements issues the certificate through Let's Encrypt on the first request and renews it before it expires. Adding a domain or rotating a certificate takes effect without dropping connections.

Integrated Postgres.

Elements installs and manages Postgres on every machine, so a single-machine app has a database with nothing to set up. For a cluster of several machines, point them at one shared Postgres, on a server you run or with a managed provider.

A completely integrated app framework that just works.

Everything a real application needs, with no external packages. Your app is standard HTML, TypeScript, SQL and CSS. The HTML is the HTML you and your agent already know, made reactive and dynamic, not JSX with a tree diffing algorithm between you and the page.

html
Standard HTML, made reactive and dynamic. TypeScript expressions in attributes and body, and templates with typed attributes. Renders on the server, updates in place in the browser, with no virtual DOM diffing.
rpc
Call a server function from the browser like any other function. The compiler turns the call into a request and keeps the body out of the browser bundle.
routes
Declared in TypeScript with a typed request and response. Return a page, or return data.
sessions
Signed cookie sessions with login and logout built in. Works in routes, rpc functions, and reactively in Elements HTML.
sql
Write sql in your code. It is parameterized at build time, against the Postgres the install already gave you.
migrations
Applied by the build: the test database before the tests run, the app database after.
live tables
Real time publish and subscribe for your data, with optimistic mutations. Declare the set of rows a page needs and every browser subscribed to it stays current: insert, update or delete anywhere and the change arrives everywhere, painting locally before the server has answered.
channels
Broadcast from the server to every browser listening, on every app server.
jobs and cron
Queue work off the request path, or schedule it. A job server starts with the project, on your machine and on every machine you deploy to.
email
Write mail in the same Elements HTML as your pages. The compiler inlines the stylesheets so it renders in a mail client.
tests
Run across child node processes with hot reload on, against a freshly migrated test database. A test reruns only when something it depends on changes.
app/pages/hello/template.ehtml
import { sql } from "@elements/app";
/** @rpc */
function save(name: string) {
sql(`insert into names (name) values (${name})`);
}
<html (name: string = "world")>
<h1>Hello, {name}!</h1>
<input value={name}>
<button onclick={() => save(name)}>Save</button>
</html>

The difference between an app that works the first time and an afternoon of telling your agent to try again.

It matters more the larger the app gets. Save any file in the project and it is checked against every page and every route, so you or your agent can change a schema in a codebase nobody remembers and find out immediately that it broke something three files away. Nothing regresses quietly, and an app you shipped six months ago is still one you can change with confidence.

The integrated app environment.

A project server, build tools, app framework and deployment, as one carefully engineered system. Built from the ground up to work together, on your own machines.

Install Elements