ceo / founder of elements

California, USA
Joined April 2010
I rebuilt the entire web app stack from a new reactive html language down to the project server and file watcher. It started 14 years ago as a new reactive html language. And I just kept going. Building web apps back then was insanely too difficult. I wasn’t planning for the AI wave but it turns out the same architecture built to make human developers lives much easier is exactly what was needed to make agents significantly more effective! Over the coming weeks I’ll talk through this journey and all the various architectural parts. Perhaps you all will find it interesting.
203
I basically walk around my house with my phone and an rc connection with @claudeai and make rapid changes to the site and yell deploy! And I see the changes in 1-2s. The deploys are so fast it doesn’t feel risky to go straight to production because a fix can go out in seconds.
elements deploy is the same build run on the remote machine after uploading only the changed source graph via a p2p protocol. It adds coordination; each machine builds, waits for test db migration, runs tests, waits for the app db migration, finally atomic release. The build does package install, type checking for both targets, and multi target emit to the scratch build folder. Tests are run off of that folder instead of the final release folder. The app continues to serve the existing app until we’re ready to flip the switch. Then the app is hot reloaded in memory, and connected browsers are hot reloaded for any users. The entire deploy typically takes .5 - 3s depending on the machine. Even across a cluster of multiple machines! I deploy via @claudeai remote control by talking to my phone and the agent does it.
45
elements deploy is the same build run on the remote machine after uploading only the changed source graph via a p2p protocol. It adds coordination; each machine builds, waits for test db migration, runs tests, waits for the app db migration, finally atomic release. The build does package install, type checking for both targets, and multi target emit to the scratch build folder. Tests are run off of that folder instead of the final release folder. The app continues to serve the existing app until we’re ready to flip the switch. Then the app is hot reloaded in memory, and connected browsers are hot reloaded for any users. The entire deploy typically takes .5 - 3s depending on the machine. Even across a cluster of multiple machines! I deploy via @claudeai remote control by talking to my phone and the agent does it.
1
105
An elements project server stays running. Multiple clients can connect, and the build state is always ready. Tests are run incrementally - only affected tests are rerun. Tests are run concurrently in separate node.js processes. Very fast. Test results available immediately upon request. Because the test state is persisted, even if you have thousands of tests, when an agent queries the test state it gets a result immediately, usually microseconds. This means tests no longer slow down development. It’s just safety. I think in many cases it helps prevent regressions. Admittedly, I wasn’t a major write tests kind of guy. Only when they really helped to get something done faster. But with agents doing things, and almost zero marginal cost to write them and run them, I’d rather have the tests!
68
A build in elements is everything required to release the app. That includes hot syncing database migrations. After you create a migration and save it, the migration is applied automatically on the next build. And if you edit the file, the db is updates automatically. In production migrations cannot be edited, for safety. This makes it very easy to work with Postgres in Elements. And it makes it very unlikely an agent will do something destructive with your database (has never happened in extensive testing). The agent just writes new migration files, in plain sql, and they are applied atomically. Migrations are first applied to a test db. Then any affected tests are run, and only after those phases succeed are the migrations applied to the app database. Multiple levels of safety. You can use a build tag on a migration to mark it as for the dev environment only, for seed data. Very useful. Data is a core part of any app. So that experience is really important to me. I think agents should simply write sql, not deal in abstractions. Working with the database should be safe by construction.
3
2
110
It was kind of fun early on agents would be like: wait it appears I don’t have to do anything else. Hmm. Had to teach it not to worry so much and we’ll tell it immediately if any problems.
9
The db migrations integrated into the build make elements a good fit for any db backed app, not just web applications, although that was the original intended purpose.
35
The elements package installer is another client to the server. So when you install the missing mime package, the build goes green almost instantly.
Initially I built each part of the elements system as separate commands. The core build, the extremely fast package installer, the db migrator. But this throws away a lot of knowledge on each invocation, and has no coordination across the tools. You end up doing a lot of IO to read, resolve a source graph, compile and emit, and then you have a completely different process for installing packages! That doesn’t make much sense, when installing packages affects the build. So I decided why not keep the server always running. And it can coordinate all build activities through a central loop: core build is read, parse, resolve, type check, static analyze, emit. Install packages, run db migrations on test. Then on app. Run tests concurrently, atomically release the next build. And if you’re going to do that, why not have the same server respond to editors too via the lsp protocol. And why not have the same server respond to 1 or a thousand agents! And that’s how the elements project server came to be. I didn’t know about agents yet when I built it, and it took just a bit of massaging to get it ready for that use case. But the same server now serves your disk build, your editor, and as many agents as you want, working simultaneously on the code base, getting all consistent build state, concurrently, in about 50 microseconds from time of request. The memory and cpu usage alone from sharing the same source graph is enormous. But the instant build query state for agents is what has fundamentally changed developing apps. Each agent gets the multi target type checking errors, package install errors, test results, db migration results, instantly upon request because by the time they ask the work is already done.
1
82
I think this is one of the most effective architectural shifts for building apps with agents. I've been calling it an integrated app environment.
46
Multiple clients connect to the same elements server, and the build state is instantly visible to all of them. Your editor, multiple agents, your app server, all connect concurrently. When an agent asks for the build state it gets an answer in microseconds.
Initially I built each part of the elements system as separate commands. The core build, the extremely fast package installer, the db migrator. But this throws away a lot of knowledge on each invocation, and has no coordination across the tools. You end up doing a lot of IO to read, resolve a source graph, compile and emit, and then you have a completely different process for installing packages! That doesn’t make much sense, when installing packages affects the build. So I decided why not keep the server always running. And it can coordinate all build activities through a central loop: core build is read, parse, resolve, type check, static analyze, emit. Install packages, run db migrations on test. Then on app. Run tests concurrently, atomically release the next build. And if you’re going to do that, why not have the same server respond to editors too via the lsp protocol. And why not have the same server respond to 1 or a thousand agents! And that’s how the elements project server came to be. I didn’t know about agents yet when I built it, and it took just a bit of massaging to get it ready for that use case. But the same server now serves your disk build, your editor, and as many agents as you want, working simultaneously on the code base, getting all consistent build state, concurrently, in about 50 microseconds from time of request. The memory and cpu usage alone from sharing the same source graph is enormous. But the instant build query state for agents is what has fundamentally changed developing apps. Each agent gets the multi target type checking errors, package install errors, test results, db migration results, instantly upon request because by the time they ask the work is already done.
1
1
84
All clients (editor, multiple agents, app server) connect to the same elements server and memory stays relatively consistent as you add more clients. Each lsp gets its own layer for virtual file changes. And each build client simply asks for the latest disk build results. No separate tsserver, one off build commands for each agent, etc.
1
62
My 5 yr old son: “dad can you get me some extremely cold water”
74
The source graph in elements is quite complex even if a simple concept. It models two things at once: the file tree and the dependency graphs across each build target (server and browser). When the project server boots up it scans all the files, including node modules, but only parses files reachable from the project via imports. So it’s a sort of lazy crawl. I brought in the TypeScript golang code and threw out all of the source graph and project stuff and connected it to elements instead. One of the reasons it’s so fast is that the elements import graph resolver works off of the in memory file tree instead of going to disk. Keeping the graph up to date after initial startup is completely incremental. And typescript uses the same graph as the rest of our build. By plugging into our source graph we eliminate a lot of extra work the typescript system is doing to produce a program. And we add the ability to type check across both the server and browser, only checking the symbols actually reachable from a given target! And even with all that, a single file save with a warm os will be 1-5ms to do the incremental build. And then by the time the agent asks for it the result comes back in microseconds.
102
Initially I built each part of the elements system as separate commands. The core build, the extremely fast package installer, the db migrator. But this throws away a lot of knowledge on each invocation, and has no coordination across the tools. You end up doing a lot of IO to read, resolve a source graph, compile and emit, and then you have a completely different process for installing packages! That doesn’t make much sense, when installing packages affects the build. So I decided why not keep the server always running. And it can coordinate all build activities through a central loop: core build is read, parse, resolve, type check, static analyze, emit. Install packages, run db migrations on test. Then on app. Run tests concurrently, atomically release the next build. And if you’re going to do that, why not have the same server respond to editors too via the lsp protocol. And why not have the same server respond to 1 or a thousand agents! And that’s how the elements project server came to be. I didn’t know about agents yet when I built it, and it took just a bit of massaging to get it ready for that use case. But the same server now serves your disk build, your editor, and as many agents as you want, working simultaneously on the code base, getting all consistent build state, concurrently, in about 50 microseconds from time of request. The memory and cpu usage alone from sharing the same source graph is enormous. But the instant build query state for agents is what has fundamentally changed developing apps. Each agent gets the multi target type checking errors, package install errors, test results, db migration results, instantly upon request because by the time they ask the work is already done.
1
219
It takes a special kind of teacher to deconstruct every layer of abstraction possible from an advanced concept to its primitives. The magic in Mentava comes from being super diligent about not missing connections in the concepts. And we back it up with a lot of reading and other activities (e.g. my son will read to his younger sister instead of me doing it). I hope they do a math app soon. First thing I noticed when using another app was that it was jumping abstractions and losing my son quickly. It doesn't take much to get discouraged. There needs to be aha! moments at each step, then my son gets audibly excited. It was surprising to me when my wife told me we were now paying $500/mo for an app tbh. But compared to a private school of $12-15k / yr it looks pretty good! Btw I'm not a paid shill! I just know how hard it is to get these kinds of details right so I like to send the team positive feedback. I'd send a video of my son doing the dance, but going to keep him off the internet!
Much of the popular understanding of intrinsic motivation is flawed, for the same reason that schools taught reading badly for so many years. **Experts forget what it's like to be beginners.** By the time you’re an accomplished reader, your brain has learned to recognize words as single units. But that’s not how new readers learn. New readers need to learn that the letters in words encode sounds, that those sounds can be blended into words, and those words can be matched to spoken language. Expert reading looks nothing like beginning reading. Expert *anything* doesn’t look like beginning *anything*. The same is true of motivation. Adults are familiar with the intrinsic satisfaction of working hard and getting better at something. But that’s a more abstract feedback loop than it seems. You practice a skill today. You get better at it tomorrow. And that tiny improvement might not even be that noticeable. Everyone knows the feeling of "I put in all this work but it doesn't feel like I'm getting better" That connection between “effort” and “progress” is not innate. It must be learned, and it can be taught. This is why I think the popular criticism of rewards and gamification is so misguided. People worry that extrinsic rewards will replace intrinsic motivation. And done poorly, they can. But done right, rewards and celebrations actually build intrinsic motivation by making the connection between effort and progress legible Motivation develops when we internalize that our effort creates progress. We *learn* to enjoy hard work by making progress visible and celebrating it
2
133
Maybe enough time to get the tmux/vim/claude code setup video done.
18
Oh no! it's Friday and almost end of the day. Time to send all the tweets!
46
I’ve never had an agent write my app in assembly. So, it appears we’re just quibbling about which software or abstractions will be best used for which jobs.
70
Building apps on your laptop with Elements and Claude Code is insanely great. I'm still partial to the terminal, but watching Claude drive the hot reloading browser app in real time is magical. Elements is what makes the build loop extremely tight.
2
1
164
Try running one of these demos in Claude Code or Codex yourself. As of today, you can pick from 50 demos to look at. Run the demo prompt and get the app running instantly. Check out the code locally or on GitHub to see what the agent built! elements.dev/demos
1
95