Plain HTML, CSS and JavaScript
A portfolio, landing page, business website, documentation site or browser-only tool. These files can be published directly; no React, Node server or build step is required.
Learn the static deployment path ↓The practical handbook · 18 October 2026
A human-friendly, step-by-step guide to taking a website from your computer to the internet with Cloudflare. Learn the requirements, choose the right platform, deploy plain HTML/CSS/JavaScript or a framework, and prepare your project for real users.
01 / Before you begin
Do not add complicated tools just because they are popular. First decide what the website needs to do.
A portfolio, landing page, business website, documentation site or browser-only tool. These files can be published directly; no React, Node server or build step is required.
Learn the static deployment path ↓React, Vue, Svelte, Angular, Astro and similar tools often compile source code into a folder of static files. The build command and output folder must match the project.
Learn framework settings ↓Login, protected APIs, webhooks, database access, scheduled tasks and server-rendered routes need server-side logic. Cloudflare Workers can run that logic.
Learn Workers ↓02 / Choose the right product
Both can deliver websites. The right choice depends on the project and the kind of runtime it needs.
Useful for straightforward static websites, static framework output and existing Pages projects. Git integration can rebuild the site whenever you push changes. Pages Functions can add server-side endpoints to a Pages project.
Useful for APIs, request handling, server-side logic, and modern full-stack applications. Workers Static Assets can serve frontend files and combine them with Worker code.
03 / Deployment tutorial
Follow these steps in order. This is the simplest path for a site made of files such as index.html, styles.css and script.js.
Keep your homepage at the top of the folder you intend to publish. For example:
my-website/
├── index.html
├── about.html
├── css/
│ └── styles.css
├── js/
│ └── app.js
└── images/
└── logo.pngCheck that paths in your HTML match the real folders and filenames. Deployed environments are case-sensitive, so Logo.png and logo.png may be different files.
Open index.html in a browser for a basic check. If your project uses JavaScript modules or fetch requests, use a local development server. Test on mobile and desktop; click every link; inspect the browser console for errors.
A form that looks correct is not automatically functional. Static hosting alone does not process submissions. A working form needs a backend, form service or suitable API.
Create a repository on GitHub. In a terminal opened inside the project folder, run:
git init
git add .
git commit -m "Add website"
git branch -M main
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.git
git push -u origin mainReplace the sample URL with your own repository. If the project already has Git configured, check git status and git remote -v first instead of reinitializing it. Never commit access tokens or passwords.
Sign in to Cloudflare and open Workers & Pages. Choose to create an application, select Pages, then connect to Git. Authorize access to the right GitHub account/repository, select the repository and production branch (commonly main).
For plain static files that need no build:
main (or the branch you actually use)exit 0 is the documented no-build optionindex.htmlIf the files are at the repository root, use the dashboard's root-directory option. If they live in a folder such as site, use that folder. Do not enter dist unless the files really are in dist.
Start the deployment and wait for the successful status. Cloudflare gives the project a *.pages.dev URL. Open it on your phone and computer. Check the homepage, navigation, stylesheets, images, links, mobile layout and any forms. A green deployment status does not guarantee every feature works.
With Git integration enabled, pushes to the configured production branch trigger deployments. A safer workflow is to create a branch, make a change, preview it, and merge when it looks right. Check the deployment result after every production update.
Official reference: Cloudflare's Static HTML deployment guide ↗
04 / Dynamic websites
Your browser code is public. A Worker can perform trusted server-side work without asking you to manage a traditional server.
This example returns a JSON health response. It is a learning example, not a complete production API.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/api/health") {
return Response.json({ status: "ok" });
}
return new Response("Not found", { status: 404 });
}
};
The env argument provides configured bindings and secrets. The example does not use it yet. A real API may need authentication, authorization, input validation, rate limits, safe error handling and logging that avoids sensitive data.
For the CLI workflow, Cloudflare provides a project starter. One common starting command is:
npm create cloudflare@latest -- my-static-site
Follow the prompts and select a static-site or suitable full-stack starter. For an existing project, follow the current Workers Static Assets instructions and point the asset directory at the actual deployable files. Use npx wrangler dev to test locally and npx wrangler deploy when the project is configured and ready. Exact setup depends on the starter and its Wrangler configuration.
These resources are not automatically created just because you deploy a Worker. Create the resource, configure its binding securely, and design access permissions and data handling.
Official references: Workers Static Assets ↗ · Workers secrets ↗ · Pages Functions ↗
05 / Frameworks
Cloudflare supports many frameworks. What matters is whether your app produces static files or requires server-side rendering and framework-specific runtime support.
Vite, React, Vue, Angular, Svelte and similar frontend stacks. React is a UI library, so check whether the project uses Vite, Next.js or another build system.
Astro, Hugo, Jekyll, Eleventy, Docusaurus, VitePress and other static site generators.
Next.js, Nuxt, SvelteKit, Remix and other frameworks with server routes or SSR. Confirm the current Cloudflare adapter and feature support before deploying.
Hono and other supported JavaScript frameworks can be used for Worker request handlers and APIs.
npm run build.dist; other projects may use build, out or another folder. Check the actual project.main.package.json scripts and the lockfile.Official references: Cloudflare framework guides ↗ · Next.js static deployment ↗
06 / Go live
A successful first deployment is the start. Make sure people can find the right site, use it safely and recover when something breaks.
www.example.com or example.com.Do not delete DNS records just to make the website work. MX, SPF, DKIM and DMARC records may be needed for business email. DNS changes can affect services other than the website.
These checkboxes are a local checklist for your browser; they do not change Cloudflare settings. For payment or personal-data systems, use a proper security review and follow applicable laws and provider requirements.
For a static site, confirm there is a top-level index.html in the deployed output directory. For a framework, check that the configured output directory matches the folder the build actually created.
Inspect browser developer tools → Network, check capitalization and path spelling, and confirm the files were committed and included in the deployed output. A leading slash points to the domain root.
Read the first useful error in the build log. Confirm the branch, root directory, build command, dependencies, environment variables and output directory. Do not use a framework build command for plain static files.
Check for hard-coded localhost URLs, missing production variables, CORS/authentication settings, unsupported runtime APIs, and browser console/network errors.
Static hosting does not process a form by itself. Connect a real backend endpoint or form service, validate input, handle success and failure, and protect any sensitive operation on the server.
Review Worker or Function logs, verify binding names and database permissions, and add safe error handling. Do not print secret values or expose raw stack traces to users.
Review the domain status and exact DNS validation instructions in Cloudflare. Avoid repeatedly changing records or deleting email records without understanding their purpose.
07 / Business email
Your website domain and your email service share DNS, but they are different services. Set up email deliberately so a website change does not break business email.
hello@yourdomain.com) to an existing inbox. It is not, by itself, a full mailbox hosting service with a separate inbox, folders, IMAP/POP access, or a complete outbound email system.hello@yourdomain.com, support@yourdomain.com, sales@yourdomain.com and billing@yourdomain.com.Official setup: Route emails with Cloudflare Email Service ↗ · Email Service documentation ↗
Tells other mail systems where incoming mail for your domain should be delivered. Incorrect MX records can stop mail from reaching your current provider.
Help receiving mail systems evaluate whether messages are authorized and authenticated. Follow the exact records supplied by your email provider; do not copy records from a different domain.
Typically connect a website hostname to a hosting destination. These records do not create an email inbox. Keep web and mail records distinct.
Changes may take time to appear across the internet. Check the record values and status before making repeated edits.
Incoming forwarding and outbound email are separate. A contact form, password reset, receipt or booking confirmation needs a sending service or a supported email API. Cloudflare Email Service includes sending capabilities, but you must configure the domain and sending workflow according to its current documentation. A third-party provider is also an option.
Useful references: Cloudflare Email Service ↗ · Cloudflare DNS ↗
08 / Operating the site
A professional website needs more than a successful deploy. Make it discoverable, measurable, accessible and maintainable.
robots.txt and sitemap when appropriate; submit the sitemap to search tools you use.Cloudflare Web Analytics can provide website traffic measurements. Enable it from the dashboard or follow the current setup guide, then check that the site is actually receiving data. Explain tracking honestly and follow privacy requirements applicable to your audience. Do not collect more personal information than you need.
Cloudflare Web Analytics guide ↗
HTML can display a contact form, but static hosting does not automatically store or deliver its submissions. Connect a secure Worker/Pages Function or a reputable form service. Validate fields on the server, protect against spam, show clear success and error states, and do not collect payment-card data yourself.
Keep the source in Git, document DNS and environment settings, and maintain a recovery path. Review deployment logs after changes, test critical journeys and keep secrets out of logs. Pages supports deployment history and rollbacks; use the dashboard to return to a known-good deployment when appropriate. A rollback does not automatically reverse database migrations or external side effects.
Check current Cloudflare plan limits and the pricing of every connected service before launch. Domain registration, paid mailbox hosting, third-party APIs, databases and email sending may cost extra even if static hosting is inexpensive. Set usage alerts where available and avoid assuming every feature is unlimited or free.
09 / Files and object storage
R2 is object storage. Think of it as a place for files your application needs to save and retrieve, rather than a folder that automatically appears inside your website.
christech-public-assets-dev for development. Use separate buckets or clearly separated policies for production and private uploads.ASSETS; your code then accesses env.ASSETS. Use the exact bucket name and configuration generated for your project.// Illustrative Worker pattern — add the matching R2 binding first.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/health") {
return Response.json({ ok: true });
}
if (url.pathname === "/example-file" && request.method === "GET") {
const object = await env.ASSETS.get("demo/hello.txt");
if (!object) return new Response("Not found", { status: 404 });
return new Response(object.body, {
headers: { "Content-Type": object.httpMetadata?.contentType || "text/plain" }
});
}
return new Response("Not found", { status: 404 });
}
};
This example assumes a binding called ASSETS exists and an object called demo/hello.txt has been uploaded. It is not a public upload endpoint and should not be mistaken for a complete file manager.
r2.dev development URL, but it is rate-limited and intended for non-production use.Official guides: R2 quick start ↗ · Public buckets ↗ · Presigned URLs ↗ · R2 CORS ↗
10 / Databases and state
These tools solve different problems. Choose based on the data shape and consistency you need, not because every Cloudflare project must use every service.
D1 is a serverless SQL database built on SQLite. It is suitable for many small and medium application data models, such as users, products, posts, bookings and settings, when used within its documented limits.
npx wrangler d1 create my-app-db. Follow the CLI output and official docs for the exact command and generated identifier.wrangler.jsonc (or let Wrangler update it). Choose a clear binding name such as DB and reference it as env.DB in the Worker.migrations folder and a numbered SQL migration file. Define tables, primary keys, constraints and indexes intentionally.-- Example migration: migrations/0001_create_notes.sql
CREATE TABLE notes (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_notes_created_at ON notes(created_at);
Migration files are the source of truth for schema evolution. Do not make undocumented dashboard-only schema edits and then forget to reproduce them in the project.
Workers KV is a distributed key-value store for data that is read frequently and can tolerate its documented eventual-consistency behavior. Common examples include public configuration, cached lookup data and feature flags. It is not a substitute for SQL joins, transactions or a strongly consistent account balance.
SETTINGS.env.SETTINGS.get() and put() from server-side code, setting expiration or TTL where appropriate.Durable Objects provide a unique, addressable coordination point with strongly consistent storage. They are useful for room-based collaboration, multiplayer sessions, WebSocket coordination, rate-limiting coordination and other workloads that need one authoritative state owner.
Queues let a producer send a message for later processing by a consumer. Use them for tasks that should not hold up the original web request, such as email jobs, image processing, webhook follow-up work or batch tasks.
Official guides: D1 getting started ↗ · D1 migrations ↗ · Workers KV ↗ · Durable Objects ↗ · Queues ↗
11 / AI on Cloudflare
AI Gateway helps you observe and control model traffic. Workers AI runs supported models. Vectorize stores embeddings for semantic search. They are related, but they are not the same service.
AI Gateway sits between your application and supported AI providers. It can provide analytics, request logging, caching, rate limiting, retries and related controls. It does not magically make every provider free, and it does not replace your application's authorization.
christech-learning.Official guide: AI Gateway overview ↗ · AI Gateway pricing and logging ↗
Workers AI lets your Worker call models available in Cloudflare's model catalog without you managing a GPU server. Model availability, context sizes, features, quotas and pricing can change, so check the current catalog before choosing a model.
AI).env.AI, following the model's required input and output schema.Official guide: Workers AI getting started ↗ · Workers AI with Wrangler ↗
Vectorize is a vector database. An embedding model turns text or other supported inputs into arrays of numbers that represent semantic features. Vectorize stores and searches those vectors; it does not automatically store or secure all of the original documents for you.
For retrieval-augmented generation (RAG), the common flow is: user question → query embedding → vector search → permission-filtered source passages → model prompt → answer with source references. Keep the original sources so the answer can be checked.
Official guide: Vectorize getting started ↗ · Vectorize with Workers AI embeddings ↗
12 / More platform services
These services solve specific problems. Start with the smallest tool that fits, and check feature availability and pricing before building around it.
Cloudflare Images can help manage and deliver images with transformations. Before using it, decide whether you need a managed image product, transformations for public images, or simply R2 storage for files. Uploading an image to R2 does not automatically grant the same transformation features as Cloudflare Images.
Cloudflare Images documentation ↗
Stream is designed for video upload, storage, encoding and delivery. It is different from simply placing an MP4 in R2. Use access controls or signed playback when the video should not be public, and review encoding, storage and delivery costs before launching a video-heavy product.
Cloudflare Stream documentation ↗
Hyperdrive helps Workers connect to supported external PostgreSQL or MySQL databases with connection pooling and related optimizations. It is not itself a database. Use it when you already have a compatible database and need to connect from Workers; use D1 when its SQL model and limits fit your app better.
Browser Rendering provides browser-based automation capabilities for supported tasks such as rendering pages, screenshots and browser-driven workflows. It is not a reason to expose a public endpoint that lets anyone navigate arbitrary websites. Restrict who can trigger jobs, validate targets, set limits and review the provider's acceptable-use and security guidance.
Browser Rendering documentation ↗
Cron Triggers can invoke a Worker on a schedule for tasks such as periodic cleanup, summaries or synchronization. Configure the schedule in the Worker configuration, deploy it, and inspect execution logs. Schedules are generally defined in UTC, so convert carefully when planning local Kenyan time. Make scheduled tasks idempotent and safe to retry.
Cloudflare's network features can help protect and accelerate websites. Begin by understanding which DNS records are proxied, then review security events and caching behavior. Add WAF/custom rules and rate limits carefully; a broad rule can block legitimate users or APIs. Do not cache private account pages or personalized API responses as public content.
WAF documentation ↗ · Cache documentation ↗ · Waiting Room documentation ↗
07 / Official references
Cloudflare updates its dashboard and supported framework workflows. Use official documentation to verify the exact steps for your project.
Keep learning
Start small, deploy a working version, test it with real devices and add complexity only when the project needs it.
Found this guide useful? You can support more practical learning resources through Chris Tech.