# Elements vs Vite Vite is an open-source build tool for frontend web code, created by Evan You and developed by the Vite team with [VoidZero](https://voidzero.dev/posts/announcing-voidzero-inc), the company he founded in 2024, which [joined Cloudflare](https://voidzero.dev/posts/voidzero-cloudflare) in June 2026. It has [two parts](https://vite.dev/guide/): a development server that updates the page in the browser as you edit, and a build command that bundles your code into static files for production. Vite works with most UI frameworks, including React, Vue and Svelte, and it is the build layer under many of them. It is free under the MIT license. Elements is an integrated app environment for building web apps, built for people and their agents, and it includes build tooling too. Its project server runs while you work and holds the build graph and build state in memory, so on every save the build state is updated almost instantly: it builds in milliseconds and answers agents and humans in microseconds. Alongside it, the same system ships a package installer, a test runner, checks for code and templates, a bundled Postgres database with migrations, a deploy command for any Ubuntu server you reach over SSH, and a default app framework built for that tooling. Elements charges for that tooling, per machine, and meters nothing. Vite is the dev server and the bundler, and the rest of the build is parts you add. Type checking is `tsc --noEmit --watch` in a second terminal, tests are Vitest, installs are your package manager, and migrations, the app server and deploy each come from another tool with its own config. Every seam is a place the build breaks: path aliases in `tsconfig.json` that Vite ignores until you set `resolve.tsconfigPaths` ([shared options](https://vite.dev/config/shared-options)), two plugins that transform the same file and give a different result in a different order, a type error in a terminal you were not watching while the browser reloads as if nothing were wrong. Elements comes ready. Installing, type checking, compiling, tests and migrations are phases of one build, so from the first minute you and your agent see every error from one command, and nothing releases until all of it passes. The apps it builds stay close to the metal: HTML, CSS, TypeScript, SQL and function calls, with a framework vocabulary of `app.route()`, `session.login()`, `sql()`, `@rpc` and tests. | | Elements | Vite | |---|---|---| | What it is | An integrated app environment: build tooling that runs as a project server, plus a default app framework built for it | A frontend build tool and dev server | | What it builds | The app: server code, browser code, templates, styles, migrations and tests | Frontend code; its server rendering support is [a low-level API for framework authors](https://vite.dev/guide/ssr) | | Build errors | [One build](/learn/man/build): type errors, failing tests, migration errors and server code reachable from the browser | Type checking not performed; the docs recommend running `tsc` in a separate process, and tests run in Vitest | | Hot reload | [The browser and the server process](/learn/man/build), patched in place on save | The browser; server code updates through a low-level API that frameworks wire up | | Production output | [One file per module](/learn/man/build), content-hashed and cached long term; a change replaces only the files it touched | Bundled chunks, built with Rolldown | | Package install | [Part of the build](/learn/man/packages) | npm, pnpm, Yarn or another package manager | | Tests | [Part of the build](/learn/man/tests), each test in a Postgres transaction that rolls back | Not part of Vite; Vitest is a separate tool | | Server framework | [Built in](/learn/man/router): routes, `@rpc` server functions, sessions | Not part of Vite; choose one and connect it | | Database and migrations | [Postgres, bundled](/learn/man/database), with [migrations](/learn/man/migrations) applied by the build | Not part of Vite | | Configuration | One `config.jsoc` file | `vite.config`, `tsconfig.json` and `package.json` | | Deploy | [`elements deploy`](/learn/man/deploy) to any Ubuntu server over SSH; each deploy runs the tests and applies migrations | Upload the `dist` folder to a static host; server code deploys separately | ## Every Build Error Comes From One Build Vite leaves type checking, tests and migrations to other tools. For TypeScript it transpiles, stripping the types so the code can run, and does not check them. Its docs say it ["only performs transpilation on `.ts` files and does NOT perform type checking"](https://vite.dev/guide/features#transpile-only), and they give the reason: type checking needs knowledge of every module in the graph, and adding it to Vite's transform pipeline "will inevitably compromise Vite's speed benefits." The [recommended setup](https://vite.dev/guide/features#typescript) is to run `tsc --noEmit --watch` in a separate process, or to add a plugin that reports type errors in the browser. Elements already holds the module graph, so every build error comes from one build: type errors, failing tests, migration errors and program analysis, such as server code reachable from the browser, found in milliseconds and answered in microseconds. [Type checking](/learn/man/typescript), [tests](/learn/man/tests) and [migrations](/learn/man/migrations) run against the same graph in memory, and a save redoes only the work that depends on what changed. Templates are part of that build. A template declares its inputs as typed TypeScript parameters, and the expressions inside `{}` are checked against them, with the same error messages as a `.ts` file: ```ehtml // app/shared/templates/comment.ehtml (Elements)

{comment.txet}

``` Each of those is a build error. It appears in the terminal, in `elements build -json` and in the editor, from one build, and a build with an error anywhere does not release. ## Several Programs Become One Build A web app is more than the code the browser runs. It has a server that answers requests, a database, migrations that change its schema, and tests, and it has to be deployed. Vite's own docs place that work outside Vite. Its server-side rendering support is ["a low-level API meant for library and framework authors"](https://vite.dev/guide/ssr), and the guide recommends running Vite in middleware mode inside a server you control, such as Express. For a traditional backend, the [backend integration guide](https://vite.dev/guide/backend-integration) has the backend serve the HTML and Vite serve the assets. In Vite, a typical project therefore runs several programs at once in development, each with its own view of the code: ```bash # terminal (Vite) vite # dev server and hot updates for the browser code tsc --noEmit --watch # type checking, per Vite's docs vitest # tests # plus the app server, the database, and a migration tool ``` In Elements, one command starts the project, and one more reads its build state: ```bash # terminal (Elements) elements start # builds and runs the app; the build covers all of it elements build -json # the current build state, for you or your agent ``` A build in Elements covers installing packages, type checking, compiling, [migrations](/learn/man/migrations), [tests](/learn/man/tests) and release, and the project server redoes only what a change touched. `elements build -json` answers in microseconds, because the build state is already in memory. The build covers the running server too. Your app runs as one long-lived process that is [hot reloaded in place](/learn/man/build) when you save server code, and never restarted. The browser is patched in place the same way. Tests are part of it. The tests whose dependencies changed rerun on a pool of concurrent workers, each inside a Postgres transaction that rolls back when it ends, and their results arrive with every other build error. There is no `vite.config`, no `tsconfig.json`, no plugin to choose, and no second terminal for type checking. ## Agents Need Standards, Not a Menu of Plugins Vite's ecosystem offers a plugin for most jobs and a list of UI frameworks to put on top, and Vite leaves every one of those choices to you. A plugin is a shortcut for an agent only when it does something the agent cannot write quickly from standards, and that surface is small. Past it, each plugin is another API to learn and another entry in `vite.config` to get right. What agents need is standards they already know (HTML, CSS, SQL, TypeScript, SSH, Ubuntu) and tooling that reports each mistake right away. Some framework is still needed. Somewhere between machine code and a package that subtracts two numbers is the plumbing an agent should not rewrite: routing, typed server calls, sessions and a database driver, which every app needs; Elements ships them as `app.route()`, `@rpc`, `session.login()` and `sql()`. Past that plumbing, returns diminish: each further plugin or framework abstraction costs an agent more to learn and get right than it saves. What an agent gets from its tools there is correction, word of each mistake the moment it makes it. So past the plumbing Elements stays with the standards, pages in [Elements HTML](/learn/man/html), standard HTML with reactive expressions in `{}`, styles in CSS, server code as TypeScript function calls and queries in SQL, and puts its engineering into correction. One coherent system checks every page, function, query, test and migration, finding every build error, from type checking, tests, migrations and program analysis, in milliseconds, and `elements build -json` reads the build state the project server already holds and answers in microseconds, the same build your editor and terminal see. Server code needs no `async` or `await`, so an agent has no `await` to forget. ## Vite+ Is One Command; Elements Is One Build [Vite+ 1.0](https://voidzero.dev/posts/announcing-vite-plus-1-0), released by VoidZero in September 2026, brings Vite, Vitest, the Oxlint linter, the Oxfmt formatter and the Rolldown bundler together behind the `vp` command. `vp check` formats, lints and type checks in one pass, `vp test` runs Vitest, and `vp run` runs tasks with caching. The tools are easier to reach, and they are still separate tools. `vp check`, `vp test` and `vp build` are commands you run, and each reports on its own run. `vp install` hands installs to the project's package manager. The server framework, the database, migrations and deploy remain outside the toolchain. In Elements those jobs are one build, run by the project server, and every tool sees the same state. Saves, installs and test runs are handled in order, so your editor, your terminal and your agents never step on each other's work. An agent that saves a file and immediately asks for the build gets the result of that save, not the state before it. The installer, the checker, the test runner and the migration runner share one source graph, so an install feeds straight into the next build. The parts Vite+ still leaves you to connect come ready in Elements: a default [server framework](/learn/man/router), a bundled [Postgres](/learn/man/database) database with [migrations](/learn/man/migrations), and a [deploy](/learn/man/deploy) command. ## Deploys Include the Tests and the Migrations A Vite production build writes static files to `dist`, and Vite's [deployment guide](https://vite.dev/guide/static-deploy) covers uploading that folder to a static host. The server, the database and its migrations deploy by other means. `elements deploy` ships the app to any Ubuntu server you reach over SSH. It provisions the machine, brings up Postgres, starts the [load balancer](/learn/man/deploy/load-balancer) with TLS, builds, runs the tests on every machine, and applies pending migrations once, on the first machine. The Postgres it brings up suits a prototype or a single-server app; for several machines, or managed backups and scaling, Elements recommends a hosted Postgres such as DigitalOcean Managed PostgreSQL or Amazon RDS, connected by setting `DB_HOST` ([setup](/learn/man/deploy/setup)). [An error in any phase aborts the deploy](/learn/man/deploy/what-happens), and the previous release keeps serving until the new one is swapped in atomically. The project server on your machine talks to the one on the deploy machine, so only changed files transfer. A first deploy to a new machine takes a few seconds, and later deploys often complete in under a second. ## A Deploy Leaves Most of the Browser Cache Intact When you ship a change, returning visitors download whatever files it touched. Vite's production build bundles modules into chunks with Rolldown, so a change to one module gives its chunk a new name, and the browser fetches that chunk again. Elements emits each browser module as its own file with a content hash in its name, linked by a small loader in each page, and tells the browser to [cache those URLs long term](/learn/man/build). A change replaces only the files of the modules it touched. Returning visitors and the CDN keep everything else. Unused exports are removed file by file. Static assets such as images and fonts get [hashed URLs](/learn/man/assets) the same way when markup or CSS refers to them by a relative path. ## Who Pays for Vite VoidZero, the company behind Vite's development, was [venture-backed](https://voidzero.dev/posts/announcing-series-a) and has been part of Cloudflare since June 2026. The announcement says the team has "started working on Void, a Vite-native deployment platform built on top of Cloudflare" ([VoidZero joins Cloudflare](https://voidzero.dev/posts/voidzero-cloudflare)). Vite is becoming an on-ramp to Cloudflare's hosting business ([Elements vs Cloudflare](/vs/cloudflare)). Elements sells its tooling directly, per machine, with nothing metered ([pricing](/pricing)). It charges for the tooling, not the framework: the app framework and runtime packages such as `@elements/app` are MIT licensed, and everything you build is yours ([licenses](/learn/man/licenses)). ## One Framework, Built for the Tooling Vite leaves the UI framework to you, and Elements includes one. Elements is not React compatible: it ships its own template language, and that is what lets one compiler type check a template and compile it for both server rendering and hydration. In the browser, the runtime [updates only the parts of the page](/learn/man/html/reactivity) whose data changed. The framework and the tooling were designed together. An [`@rpc`](/learn/man/rpc) function is a server function the browser calls like a local one: the compiler rewrites the call into a network request and keeps the function body out of the browser bundle. Calling a server-only API such as `sql()` from code the browser can reach is a compile error at the call site. [Sessions](/learn/man/session), [LiveTable](/learn/man/livetable) (database rows kept in sync with every browser), [jobs](/learn/man/jobs) and [email](/learn/man/email) are part of the same framework and the same build. ## Questions ### Is Elements an alternative to Vite? Yes. Vite builds the frontend and leaves type checking, tests, the server, the database and deploy to other tools. Elements comes ready with all of them: a project server that installs packages, type checks, runs tests and applies migrations, a command that deploys to your servers, and a default app framework built for that tooling. ### Does Vite report type errors and failing tests? No. Vite's docs say it only transpiles .ts files and does not type check them, and they recommend running tsc --noEmit --watch in a separate process. Tests run in Vitest, another tool. In Elements, every build error comes from one build: type errors, failing tests, migration errors and server code reachable from the browser. ### Can I use Vite with Elements? No, and you do not need it. Elements compiles, hot reloads and serves browser code itself. Styles and assets are part of the same build, and each is served as a content-hashed file the browser caches long term. ### Does Elements use React, Vue or Svelte? No. Elements pages are written in Elements HTML: standard HTML with typed reactive expressions, rendered on the server and hydrated in the browser. Elements is not React compatible. ### How is Elements different from Vite+? Vite+ puts Vite, Vitest, a linter, a formatter and type checking behind the vp command, and each vp command reports on its own run. In Elements, installs, type checking, tests and migrations are phases of one build, run by a project server that keeps one shared state. A default server framework, a bundled Postgres database and a deploy command come ready in the same system. ### Where can I deploy an Elements app? Any Ubuntu server you can reach over SSH, from any provider. Elements provisions it, runs Postgres and a load balancer with TLS on it, and runs the tests before the release goes live. Later deploys often complete in under a second.