# Cloudflare Bundler Apps

Author Cloudflare Worker Bundler-compatible apps that build and preview correctly...

- Repository: https://github.com/cloudflare/vibesdk (5447 stars)
- Category: DevOps
- License: MIT
- Last updated: 2026-10-22
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add cloudflare/vibesdk --skill cloudflare-bundler-apps -g -a claude-code -y`
Codex: `npx skills add cloudflare/vibesdk --skill cloudflare-bundler-apps -g -a codex -y`
Cursor: `npx skills add cloudflare/vibesdk --skill cloudflare-bundler-apps -g -a cursor -y`
Gemini CLI: `npx skills add cloudflare/vibesdk --skill cloudflare-bundler-apps -g -a gemini-cli -y`

## Description

Author Cloudflare Worker Bundler-compatible apps that build and preview correctly inside a space. Use this skill whenever you scaffold, modify, or deploy a project that will be built with `@cloudflare/worker-bundler` (i.e. anything served from `/space/:name/preview/:branch/`). Covers wrangler config, project layout, static asset rules, server entry conventions, npm dependency limits, and the most common cause of blank previews (JSX in browser scripts).

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

This skill teaches how to build apps that deploy cleanly through the space deploy pipeline. Every project committed to a space is built by `@cloudflare/worker-bundler` (`createApp` when there are static assets, `createWorker` when there are none) and served on a Dynamic Worker via `WorkerLoader`. Get the conventions right and the preview "just works". Get them wrong and you get a blank page, a 500, or a `Build failed` error.

## How the pipeline works

When `deploy_space(branch)` is called, the space DO:

1. Reads every file from the branch's working tree (skipping `.git/`).
2. Parses `wrangler.json` / `wrangler.jsonc` / `wrangler.toml` for `main`, `compatibility_date`, `compatibility_flags`, and `[assets]`.
3. If `[assets].directory` is set, files under that directory become static assets served host-side by `handleAssetRequest`. Everything else is built into a Worker via `createApp` (with `server: <main>`).
4. If no assets directory is configured, only `createWorker({ entryPoint: <main> })` is run. The output is loaded as a Dynamic Worker; all requests go to the Worker.
5. Previews are served at `/space/:name/preview/:branch/*`. Responses with `content-type: text/html` are run through `HTMLRewriter`, which prefixes root-relative `src` / `href` / `action` attributes with the preview base path. **JS-side fetches and dynamic imports are NOT rewritten.**

Practical consequences:

- **You can rely on root-relative `src="/foo.js"` and `href="/style.css"` in HTML.** They will be rewritten to the preview path automatically.
- **You cannot rely on root-relative paths inside JS strings**: `fetch("/api/x")`, `new URL("/foo", location.origin)`, dynamic `import("/lib.js")`. These hit the wrong path under the preview prefix. Use relative paths (`./api/x`, `import.meta.url`) or read the base path from `<base href>` / a meta tag injected at build time.
- The `<base href>` tag is also rewritten if present, using it lets all relative URLs resolve against the preview path.

The rest: https://github.com/cloudflare/vibesdk/blob/HEAD/worker/agents/think/skills/app-file-structure/SKILL.md
