onvibe.run

← All docs

Handler Pattern

Every app deployed on onvibe runs inside a managed server. Your code must export a default handler function — do NOT call Deno.serve() yourself.

Correct pattern

export default async function handler(req: Request): Promise<Response> {
  const url = new URL(req.url);

  if (url.pathname === "/") {
    return new Response("Hello from onvibe!", {
      headers: { "content-type": "text/plain" },
    });
  }

  return new Response("Not found", { status: 404 });
}

With context (env vars)

interface Context {
  env: Readonly<Record<string, string>>;
}

export default async function handler(req: Request, ctx: Context): Promise<Response> {
  const appURL = ctx.env.APP_URL;
  return new Response("Running at " + appURL);
}

HTML responses — always use template literals

Use backtick template literals (`) for HTML. They support multiline content, avoid quote escaping inside attributes, and allow ${expression} interpolation:

export default async function handler(req: Request): Promise<Response> {
  const name = "world";
  const html = `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My App</title>
</head>
<body>
  <h1 class="title">Hello, ${name}!</h1>
  <a href="/about">About</a>
  <input type="text" placeholder="Search...">
</body>
</html>`;

  return new Response(html, {
    headers: { "content-type": "text/html; charset=utf-8" },
  });
}

With regular strings you would need to escape every " inside attributes (class=\"title\"). With template literals there is no escaping at all — use " for HTML attributes and ' or ${...} inside them freely.

Rules

Available env vars (injected automatically)

Variable Value
APP_URL Public URL of this app
APP_ID Internal app identifier
DATABASE_URL PostgreSQL connection string (provisioned automatically for every project)

Read this page as Markdown (best for LLMs) · plain text
onvibe.run · home · all docs