StemJSON 讓用戶在已發佈的 App 中按需生成新功能
Ship the App. Let Users Add the Next Feature
StemJSON 是一種以 JSON 描述手機功能的宣告式語言,讓 AI 生成的模組經 App 內的 runtime 驗證後以原生元件呈現,無須發佈新版本。模組可描述畫面、狀態、邏輯、導覽、伺服器請求及本地資料,並在裝置上執行;初步比較中,驗證令首次開啟增加約 50 ms,其後約 12 ms。
Every app you release does only what you decided to build. When users need something else, they live without it, ask and wait for a new update, or look for another app. Your backlog or roadmap also has a limit. No team can build every feature every user wants, and the most personal requests never make the cut.
Perhaps it can be changed. Try to picture, for example, a simple budgeting app with a small prompt field. A user types or says: "Show me what I spent on coffee (beer) this year, month by month." The app has no such screen, but a few minutes later it does - a native chart or dashboard inside the app, with no new release and no ticket in your backlog.
Sounds interesting? Users could request new features in their apps on the fly, while you still stay in control and manage the boundaries of their imagination.
What makes it happen?
StemJSON is what makes this possible. It's a new declarative language based on JSON that describes a complete mobile feature: screens, state, logic, navigation, server requests and local data. In the mobile app, an AI turns the user's request into a StemJSON description, called a module, which is validated and rendered by a runtime (part of your app) using native components, so the feature is a normal SwiftUI or Jetpack Compose view, placed like any other. The StemJSON module used for rendering is quite small - a few dozen kilobytes, depending on feature complexity. The key thing here is that StemJSON is just JSON, which is widely used for encoding and decoding models for building UI and logic. In this case, it becomes a universal approach for AI generation.
Letting users generate features is only one way to use it. You can generate modules ahead of time with AI tools, test them like any other feature and send them from your backend. That goes further than classic server-driven UI, because a module carries its logic too. Prototyping tools can turn a prompt or a Figma export into something running on a device, and modules can sit next to hand-written code for the parts of an app that change often.
JSON instead of code
The idea of users updating their apps themselves is not new. But there are many obstacles to making it real. AI can reliably generate programming code, but many languages, like Swift or Kotlin, require compiling, which isn't possible on phones yet. Another way is generating web code that can run in a webview, but downloading code that adds or changes features runs into store rules. On iOS, guideline 2.5.2 is quite strict. In March 2026, Apple reportedly blocked updates to vibe coding apps like Replit and Vibecode, and pulled Anything from the store.
StemJSON takes another route. The AI generates JSON. iOS and Android can read it out of the box, and it only describes functionality the runtime already has, so it can't invent or add anything new. LLMs generate it very reliably too. JSON isn't the prettiest format, and some people ask why not YAML or something more modern. But here AI writes it and the runtime reads it, so nobody has to enjoy looking at it.
That doesn't make store rules go away, and the risk is real. The advantage is that you strictly control what can change. Besides, a module is a text file that can be analyzed and verified before it runs, and you decide what it may do. StemStudio AI, built on the same core, is already in the App Store. Keep generated features within your app's purpose, and you're on much safer ground.
Google also chose JSON for A2UI, and who am I not to trust Google :) The difference is where the logic lives. In its typical flow, a tap goes back to the AI agent, which replies with updated UI, while local functions handle things like formatting and input checks. A StemJSON module holds its own state and logic, so once generated it runs on the device by itself. A calculator keeps calculating with the network off.
Results so far
Generation has already produced complete features in a few minutes, sometimes with one more round to adjust behavior or polish the UI. With AI tools connected to the StemJSON MCP server, you can build quite complex functionality in a few iterations, test it and deliver it from a backend. Or use the already published StemStudio AI, the first mobile IDE for StemJSON.
Preliminary benchmarks are promising. Compared with the same screen built in SwiftUI, a StemJSON screen displayed just as fast once validated. Validation added about 50 ms on first open and about 12 ms after that. Memory was about 7 MB higher, most of it a one-time startup cost, and each later open cost 1.2 MB against 0.9 MB, with no sign of a leak.
Current limitations
Three things set today's limits: what the spec covers, what the runtime supports and how well AI generates. All three are improving.
The UI is limited to the components defined in the StemJSON spec. A module's external dependencies, such as services and data repositories, are more open. If the runtime doesn't have what a module needs, your app can add its own.
Getting reliable results from today's LLMs is the biggest challenge. No model has been trained on StemJSON yet. When I first used the models through the API, the result was really weak, while in ChatGPT or Claude I was getting quite decent StemJSON modules. The difference turned out to be everything those AI apps build around the model - the harness, which was built and is continuously improved for StemJSON generation.
The hardest part is ensuring that a generated feature really does what the user wanted. It can look perfect and still add up the wrong numbers. That's where people come in, or another AI model acting as a judge.
Security
Letting AI add features to a running app may not sound safe. Won't an AI-generated feature be harmful or malicious? Could it steal personal data?
StemJSON as a spec doesn't bring such issues. It all depends on the runtime, and the current ones are built with security in mind. StemJSON itself cannot describe anything that could communicate or interact with the host application. It's fully isolated by default.
Isolation starts with what a module can express. A module has no way to address memory, call a function or reach an object in the host app. The only values it can read are its own state, the system values the runtime provides, and the results of actions on dependencies it declared. So the host app's own data, its variables, objects and storage, reaches a module only if the host deliberately exposes them by sending custom events or registering services that use them.
The last one (registering your own services) is more critical, because a badly designed service can unintentionally provide unrestricted access to sensitive functionality or data. But that's the responsibility of the host app developers. Also, malicious LLM output appearing in that chain when the app is connected to an authorized AI provider is very unlikely unless the AI goes rogue (rise of the machines :) ). Besides, the runtime has some extra mechanisms, such as the security audit and host app policies. Every module is checked before anything is drawn. Decoding catches structurally wrong JSON, and validation reports other mistakes and stops the serious ones. The security audit lists what a module declares - its endpoints, services, storage, timers and subscriptions - without running it. The app policy, such as endpoint allow-lists or a module size cap, manages the module boundaries and won't allow an undesired module to run. And if it suddenly wanted to talk to an unknown server, your policy would simply refuse it.
What comes next
The next goal is to make generated features reliable enough to reach users without anyone checking each one. That takes improving the harness around the models. It analyzes every request before generation starts, then judges the finished module against what the user asked for. People then need to test only the high-stakes features.
Conclusion
Native apps have long been closed to new features once they ship. StemJSON offers a way through. Users could come up with things no roadmap would ever include. Soon, I think, an app will keep changing long after release, shaped by the people who use it. The best way to judge that is to try it.
This article was polished with the help of AI, as I’m not a native speaker.
來源:DEV Community · dev.to


