{"slug": "stone-js-your-app-exists-in-every-runtime-until-you-run-it", "title": "Stone.js: your app exists in every runtime, until you run it", "summary": "Stone.js is a new open-source framework that lets developers write application logic once and deploy it across multiple runtimes—Node HTTP, AWS Lambda, Azure Functions, GCP Cloud Functions, edge runtimes, browser, CLI, and WebSockets—without rewriting code. The framework uses a micro-kernel with adapters that normalize platform-specific events into a universal event model, and supports both decorator and functional APIs. It also includes an MCP server for AI agent integration, allowing agents to introspect and interact with the app as tools.", "body_md": "Count the versions of your last real-world app. There is the Express or Nest version for the server. The handler you extracted and mangled for Lambda. The API routes you re-declared when the frontend moved to Next. And now someone is asking for an MCP server so agents can use it.\n\nSame domain logic. Four incarnations. Every framework you picked made you pay this tax, because every framework has a home runtime and your code belongs to it.\n\nStone.js starts from the opposite premise: **an application is not an object, it is an act**. `Application = Domain x Context`\n\n. You write the domain once; the context (server, function, browser, agent) applies itself to your domain at runtime, not the other way around.\n\nA domain is just classes or functions. No base class, no framework import in your business logic:\n\n``` js\nimport { Service } from '@stone-js/core'\nimport { IncomingHttpEvent } from '@stone-js/http-core'\nimport { Get, Post, EventHandler } from '@stone-js/router'\n\n@Service({ alias: 'tasks' })\nexport class TaskService {\n  private readonly items: Task[] = []\n\n  list (): Task[] { return this.items }\n  add (title: string): Task { /* ... */ }\n}\n\n@EventHandler('/tasks')\nexport class TaskController {\n  private readonly tasks: TaskService\n  constructor ({ tasks }: { tasks: TaskService }) { this.tasks = tasks }\n\n  @Get('/')\n  list (event: IncomingHttpEvent): Task[] {\n    return this.tasks.list()\n  }\n}\n```\n\nWhere does it run? That is not the domain's problem. It is declared once, at the edge of the app:\n\n```\n@NodeHttp()       // a Node HTTP server\n@AwsLambdaHttp() // an API Gateway handler\n@Routing()\n@StoneApp({ name: 'tasks' })\nexport class Application {}\n```\n\nEach decorator is an **adapter**: it captures the platform's raw event (an `IncomingMessage`\n\n, a Lambda payload), normalizes it into one `IncomingEvent`\n\n, and turns your response back into whatever the platform expects. Your controller never learns which one ran. `stone run`\n\ncollapses the superposition into the target you deploy.\n\nAdapters today: Node HTTP, AWS Lambda, Azure Functions, GCP Cloud Functions, Tencent SCF, Alibaba FC, edge/fetch runtimes, browser, CLI, WebSockets. One domain, any of them.\n\nEvery single feature exists in two first-class forms, decorators or plain functions. Not a fallback, a parity contract:\n\n``` js\nimport { defineEventHandler, defineRoutes } from '@stone-js/router'\n\nconst TaskController = ({ tasks }) => ({\n  list: (event) => tasks.list()\n})\n\nexport const routes = defineRoutes([\n  [defineEventHandler(TaskController, 'list'), { path: '/tasks', method: 'GET' }]\n])\n```\n\nThe decorators are TC39 2023-11 stage 3 (`Symbol.metadata`\n\n), not `experimentalDecorators`\n\n, and there is no reflect-metadata anywhere. ESM only.\n\nYour app can expose itself to AI agents. In development, `stone mcp`\n\nstarts an MCP server that lets your coding agent introspect the app it is working on (routes, services, blueprint, framework knowledge). And the same adapter mechanism that serves HTTP can serve your domain to agents as tools. The fourth rewrite is the one you skip.\n\nNumbers you can verify, not adjectives:\n\n`@stone-js/*`\n\n(MIT), a micro-kernel that depends on exactly 3 of themThe API is settled enough that I document both paradigms for everything, and unstable enough that your feedback can still bend it. That is exactly the window where trying a framework is the most fun.\n\nI am looking for a dozen pilots: developers, architects, QA. Build something small, break it, tell me everything that hurts. You get direct access to me and founding-tester credit.\n\nYour app exists in every runtime. Until you run it.\n\nHappy Entanglement. 😎", "url": "https://wpnews.pro/news/stone-js-your-app-exists-in-every-runtime-until-you-run-it", "canonical_source": "https://dev.to/mr_stone/stonejs-your-app-exists-in-every-runtime-until-you-run-it-2n8o", "published_at": "2026-07-22 22:59:17+00:00", "updated_at": "2026-07-22 23:29:44.009956+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "ai-agents"], "entities": ["Stone.js", "AWS Lambda", "Azure Functions", "GCP Cloud Functions", "Tencent SCF", "Alibaba FC"], "alternates": {"html": "https://wpnews.pro/news/stone-js-your-app-exists-in-every-runtime-until-you-run-it", "markdown": "https://wpnews.pro/news/stone-js-your-app-exists-in-every-runtime-until-you-run-it.md", "text": "https://wpnews.pro/news/stone-js-your-app-exists-in-every-runtime-until-you-run-it.txt", "jsonld": "https://wpnews.pro/news/stone-js-your-app-exists-in-every-runtime-until-you-run-it.jsonld"}}