cloudflare-pages | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / cloudflare-pages

cloudflare-pages

maintained by mgd34msu

star 3 account_tree 0 verified_user MIT License
bolt View GitHub

name: cloudflare-pages description: Deploys applications to Cloudflare Pages including Functions, KV, D1, and R2 bindings. Use when deploying to the edge, building globally distributed applications, or using Cloudflare's ecosystem.

Cloudflare Pages

Full-stack deployment platform with global edge network.

Quick Start

Install Wrangler CLI:

npm install -g wrangler

Login:

wrangler login

Create project:

npm create cloudflare@latest my-app

Deploy:

wrangler pages deploy dist

Project Setup

Connect Git Repository

  1. Go to dash.cloudflare.com > Pages
  2. Create a project > Connect to Git
  3. Select repository
  4. Configure build settings
  5. Deploy

wrangler.toml Configuration

name = "my-app"
compatibility_date = "2024-01-01"
pages_build_output_dir = "dist"

# KV Namespace binding
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"

# D1 Database binding
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xyz789"

# R2 Bucket binding
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"

# Environment variables
[vars]
API_URL = "https://api.example.com"

# Secrets (set via CLI)
# wrangler secret put API_KEY

Pages Functions

Basic Function

// functions/api/hello.ts
export const onRequest: PagesFunction = async (context) => {
  return new Response(JSON.stringify({ message: 'Hello, World!' }), {
    headers: { 'Content-Type': 'application/json' },
  });
};

HTTP Methods

// functions/api/users.ts
export const onRequestGet: PagesFunction = async (context) => {
  const users = await getUsers();
  return Response.json(users);
};

export const onRequestPost: PagesFunction = async (context) => {
  const body = await context.request.json();
  const user = await createUser(body);
  return Response.json(user, { status: 201 });
};

export const onRequestDelete: PagesFunction = async (context) => {
  const { id } = context.params;
  await deleteUser(id);
  return new Response(null, { status: 204 });
};

Dynamic Routes

// functions/api/users/[id].ts
export const onRequestGet: PagesFunction = async (context) => {
  const { id } = context.params;
  const user = await getUser(id);

  if (!user) {
    return new Response('Not Found', { status: 404 });
  }

  return Response.json(user);
};

Middleware

// functions/_middleware.ts
export const onRequest: PagesFunction = async (context) => {
  // Auth check
  const token = context.request.headers.get('Authorization');

  if (!token) {
    return new Response('Unauthorized', { status: 401 });
  }

  // Continue to next handler
  return context.next();
};

Typed Context

// functions/api/data.ts
interface Env {
  MY_KV: KVNamespace;
  DB: D1Database;
  MY_BUCKET: R2Bucket;
  API_KEY: string;
}

export const onRequest: PagesFunction<Env> = async (context) => {
  const { MY_KV, DB, MY_BUCKET, API_KEY } = context.env;

  // Use bindings
  const value = await MY_KV.get('key');
  const result = await DB.prepare('SELECT * FROM users').all();

  return Response.json({ value, users: result.results });
};

KV Storage

Basic Operations

// functions/api/kv.ts
interface Env {
  MY_KV: KVNamespace;
}

export const onRequest: PagesFunction<Env> = async (context) => {
  const { MY_KV } = context.env;

  // Write
  await MY_KV.put('user:123', JSON.stringify({ name: 'John' }));

  // Write with expiration
  await MY_KV.put('session:abc', 'token', { expirationTtl: 3600 });

  // Read
  const user = await MY_KV.get('user:123', 'json');

  // Delete
  await MY_KV.delete('user:123');

  // List keys
  const keys = await MY_KV.list({ prefix: 'user:' });

  return Response.json({ user, keys: keys.keys });
};

D1 Database

Queries

// functions/api/users.ts
interface Env {
  DB: D1Database;
}

export const onRequestGet: PagesFunction<Env> = async (context) => {
  const { DB } = context.env;

  // Simple query
  const { results } = await DB.prepare('SELECT * FROM users').all();

  return Response.json(results);
};

export const onRequestPost: PagesFunction<Env> = async (context) => {
  const { DB } = context.env;
  const { name, email } = await context.request.json();

  // Parameterized query
  const result = await DB.prepare(
    'INSERT INTO users (name, email) VALUES (?, ?)'
  )
    .bind(name, email)
    .run();

  return Response.json({ id: result.meta.last_row_id }, { status: 201 });
};

Migrations

-- migrations/0001_create_users.sql
CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
# Apply migrations
wrangler d1 migrations apply my-database

R2 Object Storage

// functions/api/files.ts
interface Env {
  MY_BUCKET: R2Bucket;
}

export const onRequestGet: PagesFunction<Env> = async (context) => {
  const { MY_BUCKET } = context.env;
  const { key } = context.params;

  const object = await MY_BUCKET.get(key as string);

  if (!object) {
    return new Response('Not Found', { status: 404 });
  }

  return new Response(object.body, {
    headers: {
      'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream',
    },
  });
};

export const onRequestPut: PagesFunction<Env> = async (context) => {
  const { MY_BUCKET } = context.env;
  const { key } = context.params;
  const body = await context.request.arrayBuffer();

  await MY_BUCKET.put(key as string, body, {
    httpMetadata: {
      contentType: context.request.headers.get('Content-Type') ?? undefined,
    },
  });

  return new Response('Uploaded', { status: 201 });
};

export const onRequestDelete: PagesFunction<Env> = async (context) => {
  const { MY_BUCKET } = context.env;
  const { key } = context.params;

  await MY_BUCKET.delete(key as string);

  return new Response(null, { status: 204 });
};

Environment Variables

Setting Variables

Via Dashboard: Pages project > Settings > Environment variables

Via wrangler.toml:

[vars]
API_URL = "https://api.example.com"
DEBUG = "false"

[env.production.vars]
API_URL = "https://api.example.com"

[env.preview.vars]
API_URL = "https://staging-api.example.com"

Secrets

# Set secret
wrangler secret put API_KEY

# List secrets
wrangler secret list

# Delete secret
wrangler secret delete API_KEY

Headers & Redirects

_headers File

# Custom headers
/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff

/api/*
  Access-Control-Allow-Origin: *

/*.js
  Cache-Control: public, max-age=31536000

_redirects File

# Redirects
/old-page /new-page 301
/blog/* /posts/:splat 301
/api/* /api/:splat 200

# SPA fallback
/* /index.html 200

Durable Objects

// src/counter.ts
export class Counter implements DurableObject {
  private value: number = 0;

  async fetch(request: Request) {
    const url = new URL(request.url);

    switch (url.pathname) {
      case '/increment':
        this.value++;
        return new Response(String(this.value));

      case '/get':
        return new Response(String(this.value));

      default:
        return new Response('Not Found', { status: 404 });
    }
  }
}

// functions/api/counter.ts
interface Env {
  COUNTER: DurableObjectNamespace;
}

export const onRequest: PagesFunction<Env> = async (context) => {
  const id = context.env.COUNTER.idFromName('global');
  const stub = context.env.COUNTER.get(id);

  return stub.fetch(context.request);
};

Local Development

# Start dev server
wrangler pages dev dist

# With bindings
wrangler pages dev dist --kv MY_KV --d1 DB

# With local persistence
wrangler pages dev dist --persist-to .wrangler/state

Deployment

Production Deploy

# Deploy to production
wrangler pages deploy dist --project-name my-app

Preview Deploy

# Deploy to preview
wrangler pages deploy dist --project-name my-app --branch preview

Rollback

Via Dashboard: Pages > Deployments > [deployment] > Rollback

Analytics

// Enable Web Analytics in dashboard
// Or add snippet to HTML
<script
  defer
  src="https://static.cloudflareinsights.com/beacon.min.js"
  data-cf-beacon='{"token": "YOUR_TOKEN"}'
></script>

Best Practices

  1. Use bindings - KV, D1, R2 for data storage
  2. Set proper headers - Security and caching
  3. Use environment-specific config - Separate prod/preview
  4. Enable web analytics - Monitor performance
  5. Use Durable Objects - For stateful edge compute

Common Mistakes

Mistake Fix
Missing compatibility_date Add to wrangler.toml
Wrong output directory Match framework output
Binding not configured Add to wrangler.toml
Function not found Use functions/ directory
Secrets in code Use wrangler secret

Reference Files

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 3
GitHub Forks 0
Created Jan 2026
Last Updated 5个月前
tools tools productivity tools

Related Skills

ui-ux-pro-max
chevron_right
planning-with-files
chevron_right
agent-browser
chevron_right
building-agents
chevron_right
ui-ux-pro-max
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.