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:

Install Wrangler, Cloudflare’s CLI tool for building and deploying Workers, as a local development dependency:

npm install --save-dev wrangler@latest

Project 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@latest

Install TypeScript and Cloudflare Worker types:

npm install --save-dev typescript @cloudflare/workers-types

Create 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" --preview

Copy 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 --remote

Wrangler 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 deploy

You’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.

© 2025 Oluwole Dada.