A note for developers

The toolchain is a tax.
We’re no longer paying it.

Every layer of the modern stack — the bundler, the package manager, the container runtime, the orchestrator, the CI pipeline, the migration tool, the cache invalidation hook — was added for a real reason. Each was rational on the day it shipped. None of them know about each other. Together they form a tower we maintain on weekends so that on weekdays we can render a button.

Frames Studio is not another floor on the tower. It is the bet that the tower was always optional. Software does not need a build step to be real. A deploy does not need a pipeline to be safe. A schema does not need a migration to be versioned. An application does not need a Linux box to be alive. These are conveniences we sold ourselves, then forgot we were the ones selling.

What follows is not a feature tour. It is a list of the things that disappear — and underneath that, the architecture that makes the disappearance defensible. Read the first half if you want to know what changes. Read the second half if you want to know why it holds up.

Skip to the architecture →

Part I — What disappears

Ten things you will stop doing.

Read these as questions. Each is a load-bearing piece of the modern stack we have decided is no longer load-bearing.

  1. What if you didn’t have to write a Dockerfile?

    Frames carry their own runtime contract. There is no image to build, no registry to push to, no orchestrator to convince. The frame is the deployable unit, and the runtime knows how to honor it.

  2. What if you didn’t have to wait for a build?

    There is no build. The frame is the running thing. The artifact you author is the artifact the runtime executes. Compile time and run time are the same time.

  3. What if you didn’t have to write down migrations?

    Schema is part of the frame. It is versioned with the frame, rolled back with the frame, and reasoned about with the frame. There is no separate migration tool because there is no separate migration.

  4. What if “deploying” was just saving the file?

    A save is a frame transaction. The next read sees the new frame. There is no pipeline, no CI run, no cache invalidation phone tree. Production is whatever the latest committed frame says it is.

  5. What if your AI agent stopped emitting code files?

    An LLM that emits a TypeScript file has just made you responsible for compiling, deploying, and maintaining its output. A frame is executable intent. Agents emit frames. The runtime takes it from there.

  6. What if rollbacks took one click and included the schema?

    Frames are immutable, addressable, and time-traveled by default. Restoring last Tuesday means picking last Tuesday’s frame. The schema rolls with it. The data rolls with it. The fingers do not need to be crossed.

  7. What if multi-tenancy wasn’t a security policy you had to remember?

    Tenancy is a property of the primitive, not a row-level rule you wrote in SQL. Cross-tenant access is impossible by construction, not impossible-on-Tuesday-because-someone-remembered-the-WHERE-clause.

  8. What if you never had to choose between “fast prototype” and “real architecture”?

    Frames are the production primitive. The thing you build in the first hour is the thing you ship in the last hour. There is no rewrite step, no “now we have to make this real,” no second system to throw the first one into.

  9. What if your dev environment opened in 200 milliseconds?

    No VM boot. No container spin-up. No “loading project…” spinner that ate your morning. Open a tab, you are inside a working desktop. Close the tab, you have lost nothing.

  10. What if leaving the platform meant one command, not a rewrite?

    The escape hatch is in the spec. frames eject emits standard code you can host anywhere. The single biggest reason developers refuse to try a new platform — lock-in fear — is the one we removed first.

Part II — Why it holds up

The architecture in four pieces.

For the senior engineer who has stopped trusting marketing pages. These are the load-bearing decisions and what they cost us. Where we made an architectural bet, we say so.

1. Why frames instead of files.

A text file is a poor primitive for software. It has no identity beyond its path. It cannot be addressed by what it does, only by where it sits. It does not know its own version. It does not know whether it is in production. It does not know whether anyone is currently reading from it, and if so, with what privileges. We have spent forty years writing tools that try to make text files behave like a primitive — git for identity, npm for addressability, Docker for environment, Kubernetes for placement. Every layer is a patch on the same wound.

A frame is the primitive the file was pretending to be. Each frame is an addressable, versioned, executable unit. It carries its own type signature, its own schema, its own permissions, its own runtime contract. It is reachable by intent (“the user-auth frame”) rather than by path. It knows what version of itself is in production. It knows who is reading it. It composes with other frames the way functions compose with other functions: by reference, with types.

A FILE + ITS TOWER user.ts git — identity npm — addressability Docker — environment k8s — placement CI — correctness five tools to behave like one primitive A FRAME user-auth + identity + addressability + environment + placement + schema + permissions + version one primitive. all of the above. by construction.

The cost of this decision is real. A frame is heavier than a file. The runtime has to carry more invariants. The mental model has to be learned. We are not pretending these costs are zero. We are saying the trade buys back five layers of accidental complexity per project, and the math works out positive within the first afternoon.

2. Why the in-browser desktop is the runtime, not a sandbox.

We are not WebContainers. We did not recompile Node into WASM so the toolchain could fit inside a tab. We are not Codespaces. We did not move the toolchain to a cloud VM and pretend the move was the point. The browser is not where we display the development environment. The browser is where the runtime actually runs.

A frame executes inside the runtime. The runtime is hosted in a browser context. The same code that “serves the website” is the code that hosts your development session. There is no separate “production cluster” that your local edits eventually replicate to. The session is the cluster, fanned out by the runtime across however many tabs and tenants are currently active.

The practical consequence: cold starts are 200ms because there is no cold start. A new browser tab is a new attach to a running runtime, not a new VM. The familiar “works on my machine” class of bug is structurally unreachable, because there is no second machine. The runtime is one place. Every tab is a window into it.

3. Multi-tenancy by construction, not by convention.

Row-level security in Postgres is a brilliant idea executed as a footgun. It works exactly as long as every query goes through the connection that set the tenant context, every developer remembers to set it, and every code path is audited. The first time someone writes a raw query in a Jupyter notebook against the production database, the model is broken — and nothing tells you it broke.

In Frames Studio, the tenant is not a column. The tenant is part of the address. A frame is reached as tenant/frame/version, all the way down. There is no “the users table” that any code path could accidentally read across tenants. There is only tenant-a/users and tenant-b/users. They are separate addresses. You cannot reach one from the other because the addressing scheme does not let you.

POSTGRES RLS users tenant_id col + policy tenant A tenant B one missed WHERE = leak FRAMES a/users tenant-a scoped b/users tenant-b scoped tenant A tenant B cross-tenant address: unreachable

You cannot leak data you cannot address. The security posture stops being a discipline and starts being a topology. That is the bet.

4. The escape hatch — and why we want you to know it exists.

A platform without an escape hatch is a hostage situation. We have seen this play out enough times to know how it ends: the developer adopts the platform, the platform changes pricing or roadmap, the developer cannot leave without a rewrite, and the next platform never gets a fair hearing because the burn is still fresh.

frames eject is the answer. It is a CLI command that takes any Frames Studio project and emits a directory of standard code — TypeScript for the runtime logic, SQL for the schema, a Dockerfile for the deploy target. The result is not a hostile decompilation. It is a clean, idiomatic, hostable application. You can git clone it, host it on Vercel, deploy it to a VPS, hand it to a junior engineer to maintain.

We hope you never use it. That is the point. The escape hatch is the contract that says: if at any point we stop being worth your time, you can leave without losing your work. Knowing it exists is the trust unlock. Most developers will never run it. But every developer needs to know they could.

Part III — The human

Who built this, and why this time.

I started building a database-driven runtime in 2008. We called it Minuteman. It was wrong about a lot of things and right about one thing: the toolchain was already too big in 2008, and it has only gotten worse. We shut it down in 2013 for reasons that had nothing to do with the idea and everything to do with the timing.

The idea did not die. It became framesWork, which has been in production for years at a publicly traded enterprise serving tens of thousands of internal users. Real workloads. Real uptime. Real engineering teams that stopped writing Dockerfiles and never asked for them back. The proof point is not theoretical. It is operational.

Frames Studio is the third attempt. It is the one that ships as a public platform, available to developers outside the enterprise. I am building it solo, with Claude as my collaborator. There is no team to scale, no roadmap to fundraise, no headcount to justify. There is one engineer who has been wrong about this for eighteen years and is unwilling to be wrong about it for a nineteenth.

If the bet is correct, software development gets smaller, faster, and less hostile. If the bet is wrong, the worst case is one more interesting opinion in a space that has too few. I am comfortable with either outcome. I would prefer the first.

Two minutes is all I’m asking for.

The Loom below is the shortest version of this argument that does not lose the argument. If anything you just read sounded like it might be worth checking, watching the demo is the next step that costs the least and tells you the most.

Watch the 2-minute demo →