Add Dynamic Features to Static Sites with Cloudflare KV and Workers


Oluwole Dada
June 29th, 2025
4 Min Read
Static sites are fast, secure, and easy to deploy. However, they’ve traditionally lacked dynamic capabilities, often relying on external APIs or backend infrastructure. Cloudflare KV offers a compelling middle ground: a globally distributed key-value store that enables lightweight, persistent state to be directly stored at the edge.
By combining KV with Cloudflare Workers, developers can introduce dynamic features such as page view counters, feedback widgets, poll voting, and feature toggles to static or JAMstack applications. All of this is possible without requiring a database or server.
This post demonstrates how to build a dynamic page view counter using Cloudflare Workers and KV. The pattern shown here can be adapted for other dynamic features in static or serverless web applications.
What You’ll Build
The goal is to create a lightweight page view counter that runs entirely at the edge. Each time a user visits a page:
The Worker receives the request and extracts the path.
A value associated with that path is fetched from Cloudflare KV.
The view count is incremented and stored again.
The updated count is returned in the response.
This dynamic logic runs on Cloudflare’s global network without requiring a traditional backend or database.
What You’ll Need
Before getting started, ensure the following tools and services are available:
Node.js installed on your machine
Access to a terminal
Install Wrangler, Cloudflare’s CLI tool for building and deploying Workers, as a local development dependency:
npm install --save-dev wrangler@latestProject Setup
Create a new folder and initialise your project:
mkdir page-view-counter
cd page-view-counter
npm init -y
npm install --save-dev wrangler@latestInstall TypeScript and Cloudflare Worker types:
npm install --save-dev typescript @cloudflare/workers-typesCreate a minimal tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"lib": ["ES2022", "WebWorker"],
"moduleResolution": "Node",
"types": ["@cloudflare/workers-types"],
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"include": ["src"]
}Worker Logic
Create a src/index.ts file with the following content:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.pathname;
const current = await env.METRICS.get(key);
const views = current ? parseInt(current) + 1 : 1;
await env.METRICS.put(key, views.toString());
return new Response(`This page (${key}) has been viewed ${views} times.`, {
headers: { 'Content-Type': 'text/plain' },
});
},
};
interface Env {
METRICS: KVNamespace;
}Configure Wrangler
Create a wrangler.toml file in the root of the project:
name = "page-view-counter"
main = "src/index.ts"
compatibility_date = "2025-06-29"Next, create two KV namespaces—one for production and one for preview:
npx wrangler kv namespace create "METRICS"
npx wrangler kv namespace create "METRICS" --previewCopy the id and preview_id into your wrangler.toml like so:
[[kv_namespaces]]
binding = "METRICS"
id = "your-production-namespace-id"
preview_id = "your-preview-namespace-id"This ensures that Wrangler uses the correct KV binding when testing remotely or deploying to production.
Test the Worker Remotely
Local development using Cloudflare KV requires remote execution. Run:
npx wrangler dev --remoteWrangler will print a preview URL similar to https://page-view-counter.demo-account.workers.dev. Visit that URL in a browser. Refresh the page multiple times to see the view count increase.
Each route (e.g. /, /about) is counted independently in KV storage.
Deploy the Worker
npx wrangler deployYou’ll receive a public *.workers.dev URL where the Worker is live and KV-backed view counts persist across sessions and regions.
Extending the Pattern
This page view counter can serve as a foundation for more dynamic features, including:
Like buttons or upvotes
Feature toggles using booleans in KV
Simple poll voting
Capturing short-form feedback (e.g. comments or ratings)
Cloudflare KV is optimised for lightweight reads and writes, and it integrates seamlessly into Workers for edge-first development. For more complex use cases that require atomic writes or strong consistency, consider Durable Objects.
Cloudflare KV opens up a wide range of possibilities for adding dynamic behaviour to static sites. Combined with Workers, it allows developers to build fast, distributed applications without managing traditional infrastructure. The example in this post offers one way to get started, but the same approach can be applied to many other edge-powered use cases.
Read More Articles
Short-Circuit Logic: Writing Smarter Conditions with some() and every()

Short-Circuit Logic: Writing Smarter Conditions with some() and every()
How JavaScript’s some() and every() methods make condition checking faster, clearer, and more intentional through short-circuit logic.
October 30th, 2025
8 Min Read
The Many Faces of reduce(): How Folding Shapes Modern JavaScript

The Many Faces of reduce(): How Folding Shapes Modern JavaScript
This post explains how JavaScript’s reduce() method transforms collections into a single, meaningful result, and how understanding its accumulator pattern leads to clearer, more intentional code.
October 30th, 2025
7 Min Read