Frequently asked questions

Precise answers about deploying this Workers AI + Vectorize RAG HTML generator, using templates, costs, limits, and day-to-day operation.

Getting started & deployment

With Workers AI it is comparatively easy: you bind the AI service in wrangler.jsonc, call env.AI.run(modelId, inputs) from a Worker, and deploy with wrangler deploy. You do not manage GPUs, containers, or scaling.

This project adds Vectorize and R2 on top of that, which means a few extra one-time CLI steps (create index + bucket) and bindings. After that, deploy is still a single command. The hard parts are product design (prompts, RAG quality, frontend UX)—not infrastructure.

  1. npm install
  2. Create Vectorize: npx wrangler vectorize create html-templates --dimensions=768 --metric=cosine
  3. Create R2: npx wrangler r2 bucket create html-templates
  4. Confirm bindings in wrangler.jsonc
  5. npm run deploy
  6. Ingest at least one HTML template via POST /api/ingest

Optional: attach a custom domain in the Cloudflare dashboard (e.g. html-editor.registermysite.com).

In the Cloudflare dashboard: Workers & Pages → your worker → Settings → Domains & Routes → Add. Use a domain already on Cloudflare DNS. SSL is handled automatically. No extra code changes are required for static assets or /api/* routes.

Yes. Run npm run dev (wrangler dev). AI, Vectorize, and R2 can use your real account resources when you are logged in. Ingest templates against http://localhost:8787/api/ingest the same way you would in production.

Architecture & RAG

Retrieval-Augmented Generation: before the LLM writes HTML, the Worker embeds the user’s request, finds the most similar stored templates in Vectorize, loads their full HTML from R2, and injects them into the system prompt. The model then adapts those templates instead of inventing layouts from scratch.

Vectorize is optimized for fast similarity search over vectors and small metadata. Full HTML can be large and would hit metadata limits if stored only in Vectorize. R2 holds the complete files; Vectorize only stores the embedding plus a pointer (r2Key), name, and description.

@cf/baai/bge-base-en-v1.5 produces 768-dimensional vectors. The Vectorize index must be created with the same dimension count. Cosine metric is used for semantic similarity between the user query and template text.

Default: @cf/meta/llama-3.1-8b-instruct-fp8 (32k context). It is fast and cheap enough for streaming full pages. For higher quality on complex layouts, you can switch to a larger Workers AI model if available on your account (e.g. 70B-class or newer Llama variants) by changing MODEL_ID in src/index.ts.

Default is topK: 3. Each match’s HTML is truncated to about 6,000 characters when injected into the system prompt so the combined prompt still fits the model context window. You can lower topK to 1–2 if prompts get too large or quality drops.

Templates & ingest

No. sample-templates/ is only a local convenience folder. Runtime retrieval uses R2 + Vectorize. You must call POST /api/ingest (or a script that does) so each file is stored and embedded.

HTML=$(cat sample-templates/saas-landing.html | jq -Rs .)

curl -X POST https://html-editor.registermysite.com/api/ingest \
  -H "Content-Type: application/json" \
  -d "{
    \"id\": \"saas-landing\",
    \"name\": \"Modern SaaS Landing\",
    \"description\": \"Dark SaaS landing with hero, features, pricing\",
    \"tags\": \"saas,landing,pricing\",
    \"html\": $HTML
  }"

R2 can store large objects; Workers request bodies allow large payloads. Practical limits are quality-related:

  • Only the first 1,500 characters of HTML are used for the embedding
  • When retrieved, each template is capped at about 6,000 characters in the system prompt
  • 5–20 KB of clean HTML is the recommended range; above ~50 KB, split the page into logical sections
  • Write a rich name and description (page type, sections, style, use-case)
  • Put distinctive structure and class names near the top of the HTML (first ~1.5k chars are embedded)
  • Avoid huge minified CSS/JS blocks at the top of the file
  • Keep one clear page type per template

GET /api/templates lists R2 objects under templates/.

DELETE /api/templates?id=saas-landing removes the R2 object and the Vectorize vector for that id.

Protect these routes in production.

Frontend & user features

Yes. The frontend streams the response, extracts HTML as it arrives, writes it into CodeMirror, and updates the iframe preview on a short debounce (~120 ms). Editing the code after generation also updates the preview live.

In the browser’s localStorage under the key html_gen_saved_templates. They are per device/browser, not synced across machines, and are lost if the user clears site data. Up to 50 entries are kept. Account-backed storage can replace this later with OAuth + R2/D1.

It takes the current editor HTML, prompts for a name (defaulting from <title> or <h1>), and stores { id, name, html, savedAt } in localStorage. You can then open /dashboard.html to preview, rename, edit, download, delete, or send the HTML back to the generator.

CodeMirror 5 via CDN, mode htmlmixed (HTML + CSS + JS), theme material-darker. No build step is required; scripts are loaded from cdnjs on the generator and dashboard pages.

Models, parameters & quality

For Llama 3.1 8B FP8 (32k context) with RAG:

  • max_tokens: 4096–8192 (16384 is often too high once templates are injected)
  • temperature: 0.1–0.2 for structured HTML
  • top_p: ~0.9 · top_k: 30–40
  • repetition_penalty: ~1.05–1.1 to reduce repeated classes/blocks
  • stream: true

Input + output must fit in the 32k context window together.

Usually the model hit max_tokens or the combined prompt + completion approached the context limit. Fixes: lower retrieved template size, reduce topK, set max_tokens to ~6k, or use a larger-context model. Also ensure the system prompt asks for a complete document without unnecessary preamble.

Common causes: vague description fields, distinctive content buried after the first 1,500 characters of HTML, too few ingested templates, or user prompts that do not match how templates were described. Improve descriptions, re-ingest, and align example prompts with template language.

Cost, limits & operations

You pay for Workers AI (embeddings + generation tokens), Vectorize (queries/storage), R2 (storage + operations), and standard Workers requests. HTML generation is dominated by output tokens of the chat model. Check current rates under Workers AI pricing in the Cloudflare docs; FP8 8B models are among the cheaper options.

Yes. Workers AI enforces per-model request-per-minute limits (and neuron/token billing). Text generation is typically on the order of hundreds of RPM depending on the model. Burst traffic or parallel embeds + generates can hit limits; add retries or queueing if you productize heavily.

No. Client-side password checks are trivial to bypass (password lives in the page source). Use them only as a light gate. For real protection, put admin and ingest routes behind Cloudflare Access, or require a signed secret header / OAuth.

Options: Cloudflare Access on that path, require a shared secret header checked in the Worker, or only allow authenticated admin users after OAuth. Do not leave open ingest on a public production hostname.

Troubleshooting

Align @cloudflare/workers-types with the range required by your wrangler version (e.g. ^5.20260811.1 for recent wrangler 4.x). Then remove node_modules and the lockfile and reinstall. --legacy-peer-deps is a last resort.

Confirm vectors exist: ingest succeeded, GET /api/templates shows files, and the Vectorize index name matches the binding. Retrieval errors are logged and swallowed so chat still returns—check Worker logs. Also verify the user message is non-empty so embedding runs.

The app is designed same-origin (assets + /api/chat on one Worker). Cross-origin clients need explicit CORS headers on the chat response and must handle SSE. Prefer same-origin or a dedicated API gateway with CORS configured.

This stack is a custom RAG pipeline: you control chunking/embedding text, metadata, prompt injection, and the UI. AutoRAG is a managed product that can index an R2 bucket with less custom code. You can use either approach; this project deliberately keeps the pipeline explicit for HTML template generation.

No questions match that search.