Skip to content

Pre-GA Design Partner and Early Access only. Request access

Helix Docs

How Helix works

Where Helix code runs: a local Nitro dev server on localhost:3000, a managed production runtime per project, and shared platform services.

For developers Updated Sep 18, 2026
View as Markdown

A Helix project is a set of TypeScript functions plus an optional React SPA, and the same code runs in two places. During development the CLI serves everything from one local server on localhost

. In production each project runs on a managed runtime behind https://{project-id}.helix-app.ai, and both runtimes call the same platform services for auth, scheduling, and the project key-value store.

Local development

helix dev starts a Nitro dev server on localhost

. It serves three kinds of traffic from one origin:

  • Function routes go to the Nitro function runtime, which maps file paths in functions/ to URLs.
  • Static assets are served by Vite, integrated as a Nitro plugin.
  • Everything else falls back to the SPA’s index.html.

Because functions and the SPA share an origin, there is no CORS configuration in development. The deployed project keeps the same single-origin layout, so there is none in production either.

helix dev (localhost:3000)
  |
  |-- Function routes  -> Nitro function runtime
  |-- Static assets    -> Vite (Nitro plugin)
  |-- SPA fallback     -> index.html
  |
  |-- Local KV, in memory  <- ctx.kv()    (always local)
  |
  +-- Remote auth service  <- ctx.http.authed()  (always remote)

The one exception is authentication. ctx.http.authed('alias') always resolves against the remote Helix auth service, even during local development, because credentials are never stored on your machine. Schedules in functions/_scheduled/ fire in production only; helix dev warns if you hit those routes locally.

Production

helix deploy builds the project and ships it to the platform. The build bundles your functions into a deployable package that routes each request to the correct handler, compiles the SPA with vite build if app/ exists, and generates a manifest describing routes, schedules, and schemas. The deploy then:

  1. Uploads the function bundle to the project’s managed runtime.
  2. Uploads SPA assets for CDN delivery.
  3. Registers triggers: the platform reconciles the schedules extracted from the build.
  4. Updates routing and switches traffic to the new version.

All production traffic arrives at the project’s subdomain and routes by match priority:

{project-id}.helix-app.ai
        |
      CDN edge
        |
        |-- 1. Function route match -> project runtime
        |-- 2. Static asset match   -> CDN cache
        +-- 3. SPA fallback         -> index.html

Nitro exists only in development; production uses the managed Helix runtime. Functions scale with demand, scale to zero when idle, and each project’s concurrency cap keeps one project from consuming unbounded resources. See the deployment guide.

Platform services

Services that both runtimes call:

ServiceWhat it does
Credential resolutionResolves auth aliases to credential records, injects credentials server-side, and logs every authenticated call. See the security model.
SchedulesHolds each project’s schedules and fires functions/_scheduled/ functions in production. helix dev does not run schedules locally; see scheduled functions.
Key-value storeProject-scoped ctx.kv() storage. Local runs use an in-memory store; production uses the managed store. See the key-value store guide.

There is no managed database in the shipped product today. Use ctx.kv() for project state, or reach an external database through an authenticated HTTP API.

The life of a request

Here is what happens when a browser calls GET https://{project-id}.helix-app.ai/api/v1/orders on a deployed project:

  1. The CDN edge receives the request and checks it against the deployed route table. /api/v1/orders matches a function route.
  2. The request reaches the project’s runtime, which routes to the handler compiled from functions/api/v1/orders.get.ts.
  3. The runtime validates the merged input (body, params, and query) against the function’s exported Zod schema, then calls the handler with ctx.
  4. Inside the handler, ctx.kv() reads or writes project state, and any ctx.http.authed('alias') call has its credentials injected by the platform before the request is forwarded.
  5. The handler’s return value becomes the response and travels back through the edge to the browser.
  6. Every step is recorded under one execution ID, which you can trace in the dashboard at https://app.helix.tray.ai.

A request for a static asset such as /assets/main-abc123.js never reaches the function runtime: the CDN serves it from cache at step one.

Loading search…

Jump to a section

tab to move · esc to close