Backends without servers

Your app grows a backend the day it earns one.

A vibe runs in the browser the moment you publish it. The day it needs to keep a secret, remember something, or talk to another service, you don't go set up a server — you drop a file in src/server/ and it becomes a real /api endpoint with secrets, a database, scheduled jobs, and calls to Stripe, GitHub, or OpenAI. That backend helper is a Pulse.

01 — Start as a vibe

Most of what you make never needs a server.

A vibe runs entirely in the browser — the page, the toy, the tool, the game. It opens instantly for anyone, it is safe to share, and it is yours to remix. You only think about a backend the day the project actually asks for one.

02 — Drop a file in src/server/

Backend work goes in one folder. That is the whole setup.

When the project needs to keep a secret, remember something, or talk to another service, put that code in src/server/. That folder says "this part is backend." There is no second repo to spin up and no platform to go configure first.

03 — It becomes an /api endpoint

Publish and your file is a live route on the same app.

Supported files in src/server/ ship as same-origin /api/* routes alongside the app people open — one link, one project. Vibecodr runs that code on managed edge infrastructure, so there is no server to rent, scale, or babysit.

04 — Reach the real stuff, safely

Secrets, a database, scheduled jobs, and calls to other services.

From the server side your code can hold an API key, store and read data, run work on a schedule, and call out to Stripe, GitHub, or OpenAI — none of which the browser should ever be trusted with. That backend helper is what we call a Pulse.

It starts as a vibe — and grows a backend only when it earns one.

No setup ritual, no second platform. The project runs first; the backend appears as a file you drop in the day the work calls for it, and publishes as a same-origin /api/* route on the same app.

01 — Start as a vibe

Most of what you make never needs a server.

A vibe runs entirely in the browser — the page, the toy, the tool, the game. It opens instantly for anyone, it is safe to share, and it is yours to remix. You only think about a backend the day the project actually asks for one.

02 — Drop a file in src/server/

Backend work goes in one folder. That is the whole setup.

When the project needs to keep a secret, remember something, or talk to another service, put that code in src/server/. That folder says "this part is backend." There is no second repo to spin up and no platform to go configure first.

03 — It becomes an /api endpoint

Publish and your file is a live route on the same app.

Supported files in src/server/ ship as same-origin /api/* routes alongside the app people open — one link, one project. Vibecodr runs that code on managed edge infrastructure, so there is no server to rent, scale, or babysit.

04 — Reach the real stuff, safely

Secrets, a database, scheduled jobs, and calls to other services.

From the server side your code can hold an API key, store and read data, run work on a schedule, and call out to Stripe, GitHub, or OpenAI — none of which the browser should ever be trusted with. That backend helper is what we call a Pulse.

A few named powers — not a pile of raw server access.

Each one says what it is for and shows the lines that use it. Read the first line of each if you are new; read the code if you are not. Secrets, connected accounts, once-only coordination, policy fetch, public config, and structured logs each show up as a clear, plan-aware capability.

Dispatch proxy + encrypted secret storage

env.secrets

Creator, Pro

Call an external API with a key the browser never sees.

Usage: Your code attaches the secret to a request with env.fetch and env.secrets.bearer/header/query; the plaintext value stays on the server.

const res = await env.fetch("https://api.example.com/v1/messages", {
  method: "POST",
  auth: env.secrets.bearer("PROVIDER_API_KEY"),
});
return await res.json();

Pulse State operation coordination

env.state

Free, Creator, Pro

Make a charge or a write happen exactly once, even on a retry.

Usage: Declare named state resources in the descriptor, derive a stable key from the request, then runOnce(). Vibecodr persists the coordination record in platform-owned durable storage, so cold starts do not erase it and idle retention mostly costs tiny stored metadata. retentionTtlSeconds controls duplicate-memory retention and is capped by plan.

const key = await env.state.payments.keyFromRequest(env.request);

return env.state.payments.runOnce(key, async () => {
  await chargeCustomer();
  return { accepted: true };
});

Provider-scoped account capability via dispatch

env.connections

Free (1), Creator (3), Pro (unlimited)

Act as a connected account — like GitHub — without storing its token in your code.

Usage: Connect the account once in setup, then call it from the server side.

const github = env.connections.use("github");
const me = await github.fetch("/user", {
  headers: { "User-Agent": "vibecodr-pulse" },
});
return await me.json();

Policy outbound fetch

env.fetch

Free, Creator, Pro

Make outbound calls through the platform's egress policy, not from the page.

Usage: Use env.fetch for public outbound requests that should follow the server-side rules.

const res = await env.fetch("https://api.weather.com/v1/forecast?city=SF");
if (!res.ok) {
  return { error: "Upstream error: " + res.status };
}
return await res.json();

Public .pulse config

env.pulse

Free, Creator, Pro

Read tunable, non-secret defaults you set in a .pulse config file.

Usage: Put public values in .pulse and read them as env.pulse.NAME inside server-side Pulses. Secrets and wiring never live here.

const units = env.pulse.DEFAULT_UNITS || "metric";
const queue = env.pulse.SUPPORT_QUEUE || "support";
return { units, queue };

Structured logs + sanitized request access

env.log + env.request

Free, Creator, Pro

Write structured runtime logs and read sanitized request details.

Usage: Use env.log directly for structured logging and env.request for sanitized metadata — never platform credential headers. env.waitUntil is only best-effort after-response work, not durable processing.

const url = new URL(env.request.url);
env.log.info("pulse.request", { path: url.pathname });
return { received: true, path: url.pathname };

Plans set how much backend a project can lean on.

Pulse slots, monthly runs, secrets, and connected accounts all shape the room you get. Use this to size what your project actually needs.

Plan Price Pulse slots Runs / month Once-only operations / month Runtime / run Subrequests / run Secrets Connections Advanced SQL
Free $0 3 1,500 1,500 5s 5 0 1 Advanced path
Creator $19/mo 15 150,000 150,000 15s 25 25 3 Advanced path
Pro $39/mo 50 1,000,000 1,000,000 30s 50 200 Unlimited Advanced compatibility

Snapshot source: packages/shared/src/plans.ts. Once-only operations are the public meter for descriptor-backed Pulse State coordination — the budget env.state spends on retries and duplicate deliveries — tracked separately from general Pulse runs. Advanced SQL remains a compatibility path, not the starter model.

Here is the provider currently surfaced through env.connections.

The connection story is intentionally narrow for now. That keeps the credential model understandable and avoids pretending every provider is already equally first-class.

OAuth-backed provider

Providers your backend can act as without storing a token.

github

The split is the whole reason the front end can stay open.

Keep the public part playful and remixable; let the private, durable, long-running work move to the server side where it belongs.

Public stays public

The front end is meant to be read and remixed.

Because credentials and durable writes never live in the page, anyone can open your app, look under the hood, and fork it without ever seeing anything they shouldn't.

Private stays private

Keys and tokens are handled, not handed out.

A Pulse gives the project one public endpoint surface while source, secrets, and operational details stay owner-only behind opaque handles.

It keeps running

Work can finish after the tab closes.

A scheduled job or a once-only write runs on managed infrastructure, not in someone's open browser, so it does not depend on a person sitting and waiting for it.

Plan-shaped room

How much backend a project can lean on scales with the plan.

Secrets, connected accounts, Pulse slots, monthly run budgets, and owner-scoped platform resources set how far you can push it. Advanced compatibility SQL stays outside the beginner path.

The pages around this one.

What a vibe does on its own, what changes when a backend joins in, and how the pieces fit together.

Build the vibe. Add the backend when it earns one.

Open the Studio, ship the part people can run, and drop a file in src/server/ the day your project needs a secret, a database, or a call to another service. No servers, no deploy.

Questions? Here are the straight answers.

What is a Pulse, in one sentence?

A Pulse is the backend helper you add to a vibe — the server-side code that holds secrets, stores data, runs scheduled jobs, and calls other services on your behalf.

Do I have to add a backend?

No. Most vibes are happy running entirely in the browser. You reach for a Pulse only the day your project actually needs a secret, a database, a scheduled job, or a call to another service.

Where does the backend code go?

In src/server/ (or server/) inside your project. Supported files there publish as same-origin /api/* routes. Use /pulses/new when you want a standalone backend helper that lives outside one project.

Is there a server I have to run or deploy?

No. There are no servers to rent and no deploy step. Vibecodr runs your backend on managed edge infrastructure the moment you publish, right next to the app people open.

Can my backend code read a secret's plaintext value?

No. Secrets are injected on the server side and reached through opaque handles, so your code can use a key to make a call without ever becoming a place that key could leak from. env.db is advanced compatibility SQL, not the beginner backend story.

What is a Combo?

A vibe is the part people open and play with. A Pulse is the backend helper. When a project uses both together, that is a Combo.