Backend guide

The power of Pulses. Trusted backend capability for vibes.

A Pulse is the backend side you add when a vibe needs more help than the browser should give it. Use one for secrets, storage writes, OAuth-connected actions, automations, and other work that should stay private or keep running after someone closes the tab.

Server-side by design

Pulses are where the private or long-running work belongs.

They are there for secrets, storage writes, authenticated API calls, and automations that would feel wrong or risky inside the client-side vibe runtime.

One folder

Backend power starts with src/server/ or server/.

That folder gives the server-side part of the project a clear home instead of nudging you into a second repo or a second platform just to add one protected route.

Scoped storage

KV and D1 stay attached to the Pulse side of the project.

Storage lives in the backend layer where it belongs instead of being awkwardly bolted onto a browser runtime that should stay light and readable.

Safe credentials

Secrets and OAuth connections stay on the server side.

That gives the project more range without asking the browser to hold tokens or other sensitive access it was never meant to carry.

A Pulse is the backend side you add when the vibe needs more than the browser can safely do.

Pulses keep the model concrete. They are the server-side pieces you add when a vibe needs private execution, durable state, or integration work that should not happen in public client code.

Definition

A Pulse is the backend helper you add to a vibe.

It does not replace the client-side experience. It is the extra backend help you add when the project needs trusted execution, durable state, or work that should keep running after the tab closes.

Publishing model

Pulse files become same-origin /api/* routes when you ship.

The project keeps one public home while the backend pieces live in the server folder and publish right alongside the app's immutable artifact and live Drop.

Capability model

Pulses expose a clear backend surface instead of a grab-bag of server access.

KV, secrets, connections, protected fetch, and optional Pro D1 show up as named capabilities, so you can tell what is available without digging through mystery behavior.

Combo path

When a vibe needs backend help, it grows into a Combo.

That keeps the story easy to follow: vibe for the client experience, Pulse for backend work, Combo when both are present, and BUMP IT when the same app ships its next version.

Put the backend code in one folder, publish it with the rest of the app, and keep the public side simple.

Put backend code in src/server/ or server/. Supported files publish as same-origin /api/* routes, so the project keeps one public home while the private work stays behind the server-side line.

Route model

Pulse files publish into same-origin API routes.

That keeps the client-side experience and backend endpoints under one project instead of splitting the app into separate worlds just to explain where the private code lives.

Trust boundary

Credentials and privileged resources stay behind the server-side line.

The vibe stays isolated in the browser while the Pulse becomes the place for protected fetches, storage writes, and automation work that should not depend on a user session staying open.

The backend surface stays intentionally clear: storage, credentials, protected fetch, and optional Pro D1.

Pulses expose named capabilities with a clear plan model, so you can see what storage, credentials, connections, fetch access, and database features are available before you build around them.

Cloudflare KV

env.kv

Free, Creator, Pro

Scoped key-value storage for counters, caches, idempotency keys, and lightweight state between runs.

Usage: Each key is prefixed per Pulse at runtime, so the code stays clean while storage stays isolated.

const count = Number((await env.kv.get("visits")) ?? "0");
await env.kv.put("visits", String(count + 1), { expirationTtl: 300 });
return { visits: count + 1 };

Dispatch proxy + encrypted secret storage

env.secrets

Creator, Pro

Call external APIs without turning your Pulse code into a plain secret viewer.

Usage: Use env.secrets.get() with env.fetch(), or env.secrets.fetch() when you want explicit server-side injection rules.

if (!env.secrets.has("OPENAI_API_KEY")) {
  return { error: "Configure OPENAI_API_KEY first" };
}

const token = env.secrets.get("OPENAI_API_KEY");
const response = await env.fetch("https://api.openai.com/v1/models", {
  headers: { Authorization: "Bearer " + token },
});
return await response.json();

OAuth connection tokens via dispatch

env.connections

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

Use connected provider accounts without manually storing provider access tokens inside user code.

Usage: Get an opaque provider token handle and pass it through env.fetch().

const githubToken = env.connections.get("github");
const me = await env.fetch("https://api.github.com/user", {
  headers: {
    Authorization: "Bearer " + githubToken,
    "User-Agent": "vibecodr-pulse",
  },
});
return await me.json();

Native Cloudflare D1 binding

env.db / env.Pro_User_Binding

Pro only

Run SQL queries against the per-user D1 database for relational and transactional workflows.

Usage: The binding is added at deploy time when the project uses env.db and the owner is eligible for Pro D1.

if (!env.db) {
  return { error: "This Pulse needs Pro for env.db" };
}

await env.db.query(
  "CREATE TABLE IF NOT EXISTS Pulse_orders (id TEXT PRIMARY KEY, total_cents INTEGER)"
);
await env.db.query(
  "INSERT INTO Pulse_orders (id, total_cents) VALUES (?, ?)",
  [crypto.randomUUID(), 1999]
);
const { results } = await env.db.query("SELECT COUNT(*) AS total FROM Pulse_orders");
return results[0];

Protected fetch wrapper + outbound policy checks

env.fetch

Free, Creator, Pro

Perform outbound HTTP requests through the server-side trust boundary instead of from the client-side vibe.

Usage: Use env.fetch for normal outbound calls. It is also token-aware for env.secrets and env.connections patterns.

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();

Runtime metadata + execution context

env.env + env.log + env.waitUntil

Free, Creator, Pro

Access Pulse identifiers and version metadata, write request-scoped logs, and schedule non-blocking follow-up work.

Usage: Use env.env for metadata, env.log for traceability, and env.waitUntil() for async work that can continue after the response.

env.log.info("pulse metadata", env.env);
env.waitUntil(env.kv.put("last-run-at", new Date().toISOString()));
return { pulseId: env.env.pulseId, version: env.env.version };

Plans change how much backend help a project can lean on.

Pulse slots, monthly runs, runtime budget, secrets, connections, and D1 eligibility all shape what feels comfortable here. Use this to decide how much room your project really needs.

Plan Price Pulse slots Runs / month Runtime / run Subrequests / run Secrets Connections D1 SQL
Free $0 3 1,500 5s 5 0 1 No
Creator $9/mo 15 150,000 15s 25 25 3 No
Pro $39/mo 50 1,000,000 30s 50 200 Unlimited Yes (per-user D1)

Snapshot source: packages/shared/src/plans.ts. D1 binding: workers/api/src/lib/pulseDeployer.ts.

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 currently surfaced in the Pulse runtime.

github

Pulse power only works if the line between public code and private work stays obvious.

Pulses keep privileged work on the server-side path, so the browser-side vibe stays focused on interaction while credentials, durable writes, and automation stay protected.

Not the browser runtime

Pulses are server-side, not a workaround for vibe limits.

They exist so the browser-side vibe can stay focused and isolated while private work moves to the backend layer on purpose.

No plaintext secret free-for-all

Credential access is intentionally mediated.

Secrets and OAuth grants are routed through server-side injection patterns and dispatch-backed enforcement, not handed to user code like loose strings.

Plan-aware backend

Not every backend capability is available on every plan.

D1 SQL is a Pro capability, connections scale by plan, and the monthly run budget shapes how much backend help a project can lean on.

If you want the fuller picture, these pages explain the parts around Pulses.

These pages help if you want the fuller picture: what a vibe does on its own, what changes when a Pulse joins in, and how the pieces fit together.

Keep the vibe interactive. Add a Pulse when the project needs private or long-running help.

Let the vibe stay focused on what people can see and use. Bring in a Pulse when the project needs private data, outside APIs, durable storage, or work that should keep going after the tab closes.

Questions? Here are the straight answers.

What is a Pulse, simply put?

A Pulse is the backend side of a Vibecodr project. It is the part you add when the vibe needs help with things like secrets, storage, outside APIs, or automations.

Where do I put Pulse code?

Put it in src/server/ or server/. That folder is the clear signal that says, "this part is backend," and when you publish, supported files there turn into same-origin /api/* routes for that same project.

Can Pulse code read plaintext secret values directly?

No. The runtime is designed around server-side injection and opaque handles so user-authored code does not become a plain secret dump.

When does env.db appear?

env.db is a Pro capability. It appears when the project uses env.db or env.Pro_User_Binding and the owner is eligible for the per-user D1 binding.

How do Pulses relate to vibes and combos?

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