Skip to main content

How It Works

Five user journeys explain everything Ember does. Read in order or jump to whichever matches the question you're answering.


1. Creating a new project

The user clicks New Project, types what they want, has a quick conversation, clicks Build, and shortly after their app is live at its own URL.

The conversation phase. The user describes their app in plain English. Ember's spec collector - itself an LLM call, but a small and cheap one - asks clarifying questions until it has enough to build something. "What kind of vibe are you going for?", "Should there be a contact form?", "What's the bot supposed to do when someone messages it?" The user sees a spec card filling in as they chat: target type, template, key parameters. Nothing has been built yet; nothing has been deployed yet; nothing has cost anything. Just structured intent forming.

The confirmation gate. This is deliberate. The user has to click Build before Ember commits any resources. That's the moment that turns "an idea" into "a project". It also gives the user a chance to back out if the spec isn't what they meant.

Generation. Ember's adaptive generation engine inspects the request and routes it through one of three engineered paths. Production-grade templates provide a battle-tested starting baseline; the LLM then makes every design choice that matters - typography, voice, structure, personality, content, layout decisions - and adapts the bundle to the user's specific intent. The system learns from real usage data to improve routing over time, so iterations get sharper as the platform sees more traffic.

The security gate. Every generated bundle goes through the static security gate before any cloud resource is created. The gate inspects for secret leakage, dangerous code patterns, unapproved dependencies, and outbound network calls to unauthorised hosts. If the bundle fails, the user sees a friendly "that request got flagged for safety - try rephrasing". No resources are allocated. No half-broken project is left lying around.

Build and deploy. Ember provisions a fresh isolated container for this project's first version, builds the bundle into a container image, starts the container, and verifies it's healthy before returning. The entire pipeline runs as a background process - the user can close the tab the moment they click Build and come back later to find their app live. Status events stream over a Realtime channel so the dashboard catches up automatically when the user returns, replaying every stage the pipeline progressed through.


2. Iterating on a project

This is where Ember's UX really earns its place. After the first build, the user keeps chatting. Each message becomes a refinement - "make the hero text larger", "add a pricing section", "change the colour scheme to feel more professional". Each refinement appears in the preview window without leaving the chat.

Tiered iteration. Ember classifies each iteration into one of three tiers and routes accordingly. A small tweak - "change the headline colour to navy" - uses a tiny, near-instant LLM call. A multi-file edit - "add a testimonials section" - uses a single mid-tier LLM call that returns the file diffs in one go. A complex refactor - "restructure the whole site to have a separate dashboard" - runs an agentic loop where the LLM reads files, writes files, checks itself, and iterates until done.

This tiering is invisible to the user. They just see fast responses to easy asks and slightly longer responses to hard ones. But it's the difference between charging $20/mo and being viable at $5/mo: each tier costs about 10x less than the next-deeper one. Most iterations are tier-1.

The agentic loop in action. For complex requests routed to tier 3, the LLM is given file-system tools - read_file, write_file, list_files, check_syntax, lint, read_template_manifest - and operates as an autonomous coder. The dashboard shows what it is doing in real time: "reading the navigation component...", "writing the updated styles...", "checking syntax on layout.tsx...", "found a missing import, fixing...". The user sees the agent's thinking, not a spinner. When syntax errors come back, the agent reads them and writes a fix. When lint complains, the agent reformats. It only stops when the bundle is clean and the request is satisfied (with hard caps preventing runaway).

Background execution end-to-end. A complex iteration through the agentic loop can take a few minutes. The user does not need to wait for it. The whole pipeline - generate, scan, sync, hot-reload - runs as a background process; the user can close the tab and come back. Status streams over Realtime so the dashboard catches up automatically when the user returns. This is what makes the platform feel like delegating to a coworker rather than watching a progress bar.

Hot reload to a dedicated preview container. Once the change is generated and the security gate passes, Ember pushes the diff to the user's iteration preview container. The container's hot-reload server detects the change and refreshes. The preview iframe in the dashboard updates automatically.

The preview container is kept idle-suspended when nobody's iterating, so cost is near-zero for inactive users. The first iteration after idle takes slightly longer as the container wakes from suspend; subsequent iterations are full-speed.


3. Publishing to production

When the user's happy, they click Publish. The current preview state gets promoted into a fresh production container with its own immutable version ID. The previous version keeps running until the new one is verified healthy; only then does traffic swap.

Sequential swap. This pattern is why publishing is safe even if the new build is broken: the old version keeps serving traffic until the new one is verified, and only then is the cutover atomic. A failed publish never takes down a working project. The user just sees an error and can try again.

Versioned, immutable. Each published version gets its own unique identifier and its own container. Rolling back is a single click - find the previous version in the iteration history, click rollback, the previous container is reactivated. Nothing about the user's project state was ever destroyed; we just point traffic at a different container.


4. Routing a visitor to a live project

When someone visits the URL of a published Ember project - <projectId>.emberstudio.app - they're routed through Ember's edge network. The edge router asks Ember which container that project's current version lives in, then proxies the request straight through.

The routing is dynamic - Ember doesn't need to provision a DNS record per project. When the user publishes a new version, the subdomain instantly points at the new container; the old container keeps serving until traffic naturally drains over a short cache window. Custom domains (paid-tier) work the same way once the user adds a CNAME record pointing at Ember.


5. An agent receiving a Telegram message

The agent target is Ember's strategic differentiator. Once the user has set up an agent project, connected their LLM provider key, and pasted their BotFather token, the agent runtime is ready to receive Telegram messages and reply autonomously.

Why this is the strategic story. Look at the diagram: the LLM call in the middle is what makes the agent valuable. The cost of that call is paid by the user, not by Ember. Their messages bill to their own Anthropic or OpenAI account directly. The agent can loop on tools (fetch a webpage, look something up, query an API) and respond intelligently - and the variable cost of all that intelligence lands on the user's account, not the platform's.

This is what generic vibe-coding tools can't do without burning their margin. When the user's agent processes 100 Telegram messages a day for a year, that's 36,500 LLM calls. At platform-borne cost, that single user would consume more inference than the platform's monthly budget for the whole user. With BYO key, that same usage costs Ember the same as if the user sat idle - only the compute the agent runs on.

Per-chat conversation memory. Each Telegram chat gets its own conversation history, stored on the agent's container filesystem. Multiple users texting the same bot don't see each other's context. Conversations stay coherent across messages.

Tool execution. The agent has access to platform-defined tools - HTTP requests (to hosts the project owner has allowlisted), Telegram-specific tools like sending messages and uploading media, and skill modules for common patterns. New tools can be added as needed; the user enables them per-project by listing them in the agent's configuration.


What ties these flows together

A few patterns recur across every flow above:

The control plane sees everything. Every important action - generation, scan, deploy, message, tool invocation - passes through the control plane and gets logged. There's no path that bypasses it.

Per-project containers are the unit of isolation. Every generated workload lives in its own container with its own secrets and its own scope. No shared state between projects, ever.

The security gate is mandatory. Every bundle. Every iteration. Every publish. No way to skip it.

The user's experience is conversational and visual. They chat; they watch the preview update; they click publish. The complexity behind the curtain - the orchestration, the containers, the scanning, the deploy verification - is hidden by design.

The platform exists in that gap: invisible enough to feel like magic, structured enough to be safe.