Endpoint mapping contract

Pulse Routing

Pulse routing defines how source files map to same-origin /api routes and how those routes are exposed to runtime callers, embeds, and automation surfaces.

Route contract reference for mapping Pulse files to API endpoints.

Implementation focus

Use this page when creating or refactoring server routes so call paths and deployment behavior remain predictable.

Expected outcomes

The src/server/ (and server/) Convention

Vibecodr uses a file-based routing convention. TypeScript and JavaScript files inside src/server/ (preferred) or server/ publish as API endpoints when the project ships as a Pulse or Combo.

Mental model: src/server/ tells Vibecodr what should run as backend code, while /api/* is the URL surface people and browsers actually call.

The same convention applies to GitHub and ZIP imports. Framework apps like Vite + Svelte can keep their frontend source and add src/server/ endpoints. Frontend previews in Studio; server files deploy as /api/* routes when you publish. Built-only archives such as dist/ do not contain enough source to create backend routes.

How to deploy a Pulse (serverless compute)

  1. Add backend function files to src/server/ (preferred) or server/.
  2. Verify file-to-route mapping (src/server/foo.ts -> /api/foo).
  3. Publish from Studio; Vibecodr bundles and deploys the Pulse runtime automatically.
  4. Blueprint starters open in Studio as Pulse source with setup tasks, not as browser preview apps. Finish the checklist, publish, then test the deployed endpoint.
  5. PulseDescriptor normalizes Pulse setup metadata internally; simple one-file handlers remain simple, and setup UI, examples, local replay, API/OpenAPI, MCP, CLI, and deployment validation read the normalized descriptor projection.
  6. For standalone automations and webhooks, use the Pulse Operating Center or go straight to Pulse creation.

Vibes (Browser Code)

Files outside src/server/ run in the browser.

src/App.tsx, index.html

Pulses (Server Code)

Files inside src/server/ (or server/) become API endpoints.

src/server/weather.ts -> /api/weather

File Path to Route Mapping

Your file path determines your API route. Here's how the transformation works:

File Path

API Route

Notes

src/server/weather.ts

/api/weather

Basic route

src/server/index.ts

/api

Root endpoint

src/server/users/index.ts

/api/users

index.ts = folder route

src/server/users/[id].ts

/api/users/:id

Dynamic parameter

src/server/webhooks/stripe.ts

/api/webhooks/stripe

Nested paths

server/weather.ts

/api/weather

Legacy path (also supported)

Supported extensions: .ts, .js, .tsx, .jsx. Other files (like .json or .md) in src/server/ (or server/) are ignored. PHP and WordPress are not supported inside vibes or Pulses; .php files, WordPress themes/plugins, and WordPress admin routes are treated as unsupported source or scanner traffic.

Dynamic Route Parameters

Use square brackets [param] in filenames to create dynamic route segments. These become :param in the URL and are accessible in your handler.

src/server/users/[id].ts -> /api/users/:id

// File: src/server/users/[id].ts
// Route: /api/users/:id
import { definePulse } from "@vibecodr/pulse";

export default definePulse(async (input, env) => {
  // Access the dynamic parameter from the request URL
  const url = new URL(env.request.url);
  const id = url.pathname.split("/").pop();  // "123" from /api/users/123

  return { userId: id, message: "Found user" };
});

[id].ts matches /api/users/123, /api/users/abc, etc.

[...slug].ts catch-all routes are not currently supported

Project Types

Vibecodr automatically detects your project type based on file structure:

V

Vibe

Browser-only. No src/server/ (or server/) files.

Slot cost: 0 (unlimited)

P

Pulse

Server-only. Has src/server/ (or server/) files, no frontend entry.

Slot cost: 1 deployment slot

C

Combo

Full-stack. Frontend entry + src/server/ (or server/) files.

Slot cost: 1 deployment slot

Deployment slots limit how many pulse/combo projects you can have deployed at once. Free: 3 slots, Creator: 15 slots, Pro: 50 slots.

Creating Pulse Files

In Studio, create endpoints by adding a file under src/server/ (or server/). Use Configure → API → New endpoint, or right-click the folder in the file tree.

New API endpoint

This creates a new endpoint file with boilerplate code and shows the derived /api/* route.

Default pulse template

// src/server/my-endpoint.ts
// Route: /api/my-endpoint
import { definePulse } from "@vibecodr/pulse";

export default definePulse(async (input, env) => {
  // Your logic here
  return { message: "Hello from my-endpoint!" };
});

Advanced SQL compatibility is exposed as env.db on eligible plans. Use that surface only when you truly need SQL, treat it as advanced compatibility rather than the default Pulse backend model, and do not assume automatic Pulse State migration.

Handler Styles (Recommended)

We recommend using the definePulse helper to explicitly set your handler style. This ensures your code runs exactly as expected, even if you use default parameters or specialized bundlers.

Enhanced Style

Receives parsed input and Pulse backend capabilities. Best for business logic, policy fetch, connected accounts, and structured logs.

Enhanced handler

import { definePulse } from "@vibecodr/pulse";

export default definePulse(async (input, env) => {
  env.log.info("pulse.received", {
    method: env.request.method,
    hasName: typeof input?.name === "string",
  });

  return {
    greeting: `Hello ${typeof input?.name === "string" ? input.name : "there"}`,
    region: env.pulse.DEFAULT_REGION ?? "global",
  };
});

Web-Standard Style

Receives a standard Request and returns a Response. Best for proxying, streaming, or full control over HTTP headers.

Web-standard handler

import { defineWebPulse } from "@vibecodr/pulse";

export default defineWebPulse(async (req) => {
  const body = await req.json();
  return Response.json({ echo: body });
});

Legacy: Auto-detection

If you don't use the definePulse helper, the runtime guesses the style based on your function's argument count. This works for basic cases but can be brittle.

// Enhanced style: 2 arguments (input, env)
export default async function(input, env) { ... }

// Web-standard style: 1 argument (request)
export default async function(request) { ... }

Warning: Footguns

Fix: Always use definePulse() or defineWebPulse() to avoid these issues.

Deployment Flow

When you publish a project with pulse files, here's what happens:

1

Project type detection

Vibecodr scans for src/server/ (or server/) files and classifies as Vibe, Pulse, or Combo.

2

Slot check

If pulse/combo, checks if you have available deployment slots.

3

Bundle & deploy

Your code is bundled with the Vibecodr runtime and deployed automatically by Vibecodr (no manual deploy wiring).

4

Verification

Vibecodr verifies the deployed endpoint responds before marking the Pulse active.

5

Status update

Pulse status set to "active" (success) or "failed" (error).

Troubleshooting

Pulse not detected

Deployment failed

Route not working

Best Practices

Routing Guidelines

File-to-route mapping

Pulse routing maps server-side source files to same-origin /api endpoints. The route shape should be predictable enough that vibe code, embeds, docs, and automation can call it without guessing where behavior lives.

Route collisions and unclear ownership become production bugs quickly. Name endpoints around behavior and keep handler files close to the capability they own.

  • Keep Pulse routes stable once public callers depend on them.
  • Avoid overlapping route names with different auth expectations.
  • Use `.ts`, `.js`, `.tsx`, or `.jsx` for Pulse route files; PHP and WordPress are not supported inside vibes or Pulses.
  • Document payload shape and error behavior for each public endpoint.

Exposure model

A deployed Pulse endpoint can be public HTTP while the source remains private. Those are different visibility planes. Do not rely on source privacy as endpoint access control.

If a route should be owner-only, signed, or session-gated, enforce that in the handler.

  • Public callable does not mean public source.
  • Public source does not mean safe to expose secrets.
  • Runtime routing should not leak platform capabilities, deployment details, or logs.

Example and read next

Example: server/contact.ts should become a stable same-origin route such as /api/contact. Keep route names intentional, avoid collisions, and update callers when the route contract changes.

Use these related pages when you need the next layer of guidance. They point to the most likely follow-up tasks, not every page that happens to touch the same system.

Related documentation