Backend guide

Cloudflare Workers, without the setup drag.

If you like Cloudflare Workers but do not want to spend your energy rebuilding the same backend setup every time, this is the shape Vibecodr gives you: env.pulse config, policy fetch, setup capabilities, structured logs, sanitized request access, and managed file workflows wrapped around a publishable product.

Workers for Platforms

The backend path is Cloudflare Workers-backed from the start.

You are not inventing a separate backend setup from scratch. Vibecodr already gives the server-side part of the project a Workers-powered home.

Public config

.pulse shows up as env.pulse, not flat env variables.

Public defaults stay explicit while credentials and platform wiring stay out of public source.

Policy fetch

Outbound requests go through env.fetch policy.

The public docs teach policy fetch rather than arbitrary unconstrained fetch or internal dispatch details.

R2 stays platform-managed

File workflows are handled through Studio and the API layer, not a casual env.r2 binding.

That keeps bundle, asset, and capsule storage aligned with the product's publishing and access model.

Cloudflare Workers show up here as a ready-to-use backend path, not an empty box.

The important question is not whether Workers are involved. It is how that infrastructure turns into something practical for API routes, automations, integrations, and durable state without draining the fun out of building.

Write the fun part

You focus on what the Pulse should do, not the shared-platform wiring around it.

The useful Cloudflare pieces show up where you need them, while the account-separation and storage plumbing stay out of your way.

Same-origin API routes

Pulse files publish into the project's own /api/* surface.

That keeps the public app and the backend routes under one project shape instead of splitting the mental model across multiple deployment surfaces, and BUMP IT keeps future releases on that same app identity.

App-focused bindings

The useful Cloudflare pieces are exposed where they matter.

env.pulse, env.fetch, env.secrets, env.connections, env.log, env.request, and env.state are the practical beginner surface. R2 remains managed through product workflows.

Access map

Direct beginner surface: env.pulse, env.fetch, env.secrets, env.connections, env.log, env.request, env.state. Managed: R2 and shared-platform wiring.

Use those documented capabilities for runtime work, use env.runtime.capabilities() when you need a safe picture of what the Pulse can access, treat env.db as advanced compatibility SQL, and let Vibecodr keep hold of file workflows, deployment setup, and account separation.

You write backend logic in one folder and it shows up inside the same project.

Put backend code in src/server/ or server/. Supported files publish as same-origin /api/* routes, so the public project keeps one surface while the Worker-backed backend lives behind it.

Route model

Pulse files publish into same-origin /api routes.

That keeps the client-side experience and backend endpoints under one project instead of making you explain a second deployment surface to everyone who touches the app.

Managed infrastructure

Some capabilities are direct in code, while storage and deployment plumbing stay managed for you.

Reach for documented capabilities like env.pulse, policy fetch, credentials, structured logs, and sanitized request access in Pulse code, then let Vibecodr handle asset storage, publish wiring, and the shared-platform safety work around them.

The direct Worker surface stays intentionally small: env.pulse, policy fetch, credentials, logs, and sanitized request access.

Use this section to see what can live directly in Pulse code today, what needs a Pro upgrade, and what still stays managed instead of turning into another thing you have to wire yourself.

Public .pulse config

env.pulse

Free, Creator, Pro

Read non-secret user-configurable defaults without teaching flat public config like env.MODEL.

Usage: Put public values in .pulse and read them as env.pulse.NAME inside server-side Pulses.

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

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.fetch with env.secrets.bearer/header/query so secret values stay policy-bound.

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

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

Provider-scoped account capability via dispatch

env.connections

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

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

Usage: Use setup-reviewed connected accounts for provider calls.

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

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

Usage: Use env.fetch for public outbound calls that should follow platform egress policy.

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

Pulse State operation coordination

env.state

Free, Creator, Pro

Coordinate backend work across Pulse calls on the Workers-backed runtime with stable operation keys.

Usage: Use descriptor-declared state resources with runOnce(), claim(), keyFromRequest(), and guarded effects when repeated calls need to agree on the same protected operation; retentionTtlSeconds controls duplicate-memory retention and is capped by plan. 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.

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

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

Structured logs + sanitized request access

env.log + env.request

Free, Creator, Pro

Write request-scoped logs and inspect sanitized request metadata without platform credential headers.

Usage: Use env.log directly for structured runtime logging. env.waitUntil is only best-effort after-response work, not durable processing.

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

Descriptor-backed runtime capability snapshot

env.runtime.capabilities()

Free, Creator, Pro

Inspect the Pulse's creator-facing capability surface without probing raw env bindings or platform internals.

Usage: Use it when the Pulse needs to confirm which public config keys, secret names, provider connections, raw-body routes, state resources, or advanced SQL compatibility were exposed to this deployment.

const caps = env.runtime.capabilities();

return {
  publicConfig: caps.pulse.publicConfigKeys,
  providers: caps.connections.declaredProviders,
  stateResources: caps.state.activeResources,
};

What you get directly, what is optional, and what Vibecodr still owns.

This is the clearest honest map of the current Cloudflare story on Vibecodr, without pretending every feature is already exposed the same way.

Capability How you access it Availability Truth status
.pulse config env.pulse.* All Pulse plans Public, non-secret user config only.
Advanced SQL compatibility env.db Explicit advanced path Not the beginner backend model and not auto-migrated to Pulse State.
R2 Studio and API file workflows Platform-managed No direct env.r2 binding in PulseEnv today.
Secrets and connections env.secrets and env.connections via env.fetch Plan-aware Credential access is server-mediated rather than direct raw token access.
Pulse State coordination env.state.<name>.runOnce()/claim()/keyFromRequest() All Pulse plans with plan-shaped monthly caps Tracks operation lifecycle across Pulse calls: new, pending, completed, failed, conflicting, replay-aware, and quota-admitted. Use a data surface or connected service for app records.
Runtime capability reflection env.runtime.capabilities() All Pulse plans Safe creator-facing reflection only: declared keys and availability, never secret values or raw platform binding internals.

Here is the provider currently exposed through env.connections.

The connection story is intentionally narrow for now. That is more honest than pretending every provider is already surfaced equally inside the runtime.

OAuth-backed provider

Provider currently surfaced in the Pulse runtime.

github

Use direct bindings for app logic, and let the platform keep hold of the risky plumbing.

The important boundary is straightforward: use documented Pulse capabilities for backend logic, treat advanced SQL compatibility separately, and let Vibecodr keep file storage, deployment wiring, and project separation under platform control.

No direct env.r2 today

R2 is part of the platform workflow, not the Pulse runtime surface.

That distinction matters because bundle and asset storage are tied to publishing, Studio, and API pathways rather than arbitrary Worker-side file access.

No platform handles

Pulse code gets product capabilities instead of shared-platform handles.

That keeps implementation plumbing out of beginner examples and public source.

Pro gates are explicit

Advanced SQL is not the beginner state story.

That keeps the Worker story honest: compatibility SQL exists separately from beginner documentation and future Pulse State work.

Follow the guide that matches the question you actually have right now.

Start with backend capability, client-side runtime, or the broader publish-and-share loop, depending on which part still feels fuzzy.

Use the Workers-backed path for real backend logic, then let Vibecodr carry the setup burden around it.

The result is a cleaner backend workflow: direct access where you need it, less setup noise where you do not, and a much clearer picture of how Pulse capabilities and platform-managed storage fit into a real project.

Questions? Here are the straight answers.

Do beginner Pulses need raw storage bindings?

No. Beginner Pulses should start with input, env.pulse public config, env.fetch policy outbound fetch, env.log structured logs, env.request sanitized request access, env.state coordination, secrets, and connections.

Is env.db the default Pulse backend model?

No. env.db is advanced compatibility SQL, not the starter model, and no automatic Pulse State migration is promised by that compatibility surface.

Is R2 exposed as env.r2 inside Pulse code?

Not currently. R2 is platform-managed for capsule files, bundles, and assets through Studio and API workflows instead of being exposed as a direct Pulse binding.

Can a Pulse read platform binding internals?

No. Raw binding names, route catalogs, grants, logs, state, and ops metadata stay owner/platform projections rather than public projection metadata.

How should a Pulse check what Vibecodr exposed to it?

Use env.runtime.capabilities(). It reflects a safe creator-facing view of declared config keys, secrets, connections, raw-body routes, and Pulse State resources without exposing secret values or platform binding internals.

What is the practical Cloudflare story here?

You get a Workers-backed backend path that already feels shaped for apps: env.pulse config, policy fetch, setup capabilities, structured logs, sanitized requests, and managed file storage, without having to rebuild the same app plumbing from scratch.