Skip to main content
skill CX Codex

cloudflare-workers-testing — Claude Code skill: Workers tests

A skill for writing Cloudflare Workers tests with Vitest and real D1, KV, R2 and Durable Objects bindings. Useful when tests break on mocks or can't see the environment.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add secondsky/claude-skills --skill cloudflare-workers-testing -a claude-code
Open on GitHub

What cloudflare-workers-testing does

The skill walks through setting up Vitest and @cloudflare/vitest-pool-workers so tests run in the actual Workers runtime instead of hand-rolled stubs. It covers install steps, a ready vitest.config.ts, test examples and eight common errors. Templates and reference material are included.

One rule matters most: pull the environment from the cloudflare:test module rather than building it yourself. Bindings come from wrangler.jsonc, so if your Vitest config doesn't point at that file, env ends up empty — that's the first thing people hit. Second: call waitOnExecutionContext after invoking the worker, or background work scheduled through ctx.waitUntil never finishes and the test lies to you.

Every test gets isolated storage, so data from one test doesn't leak into the next. You need Node.js 20+ and Vitest ^2.0.0. Keep the compatibility date in the Miniflare config identical to the one in wrangler.jsonc, otherwise test behaviour drifts from production.

What it helps with

  • set up Vitest for Cloudflare Workers from scratch
  • wire real D1, KV, R2 and Durable Objects bindings into tests
  • fix failing tests caused by unfinished ctx.waitUntil work
  • figure out why env is empty inside a test
  • keep test data isolated between cases

Example prompts for the agent

  • Help me set up Cloudflare Workers tests with Vitest and bindings from wrangler.jsonc
  • My test fails because env is empty even though the bindings are declared. Find out why
  • Write a worker test against D1 and make sure ctx.waitUntil tasks complete

How to install cloudflare-workers-testing

1Skills CLI (Vercel)

npx skills add secondsky/claude-skills --skill cloudflare-workers-testing -a claude-code

2Manually: put the files in place

~/.claude/skills/cloudflare-workers-testing/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/cloudflare-workers-testing/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about cloudflare-workers-testing

How do I install cloudflare-workers-testing in Claude?

Run npx skills add secondsky/claude-skills --skill cloudflare-workers-testing -a claude-code. The skill lands in ~/.claude/skills/cloudflare-workers-testing/SKILL.md.

What does cloudflare-workers-testing do?

It guides you through Cloudflare Workers testing with Vitest and @cloudflare/vitest-pool-workers: config, test examples, binding usage and common error fixes.

What do I need for this skill to work?

Node.js 20+ and Vitest ^2.0.0. Bindings are read from wrangler.jsonc, so without that file tests won't see the environment.

Source text

SKILL.md · MIT
---
name: cloudflare-workers-testing
description: Comprehensive testing guide for Cloudflare Workers using Vitest and @cloudflare/vitest-pool-workers. Use for test setup, binding mocks (D1/KV/R2/DO), integration tests, or encountering test failures, mock errors, coverage issues.
license: MIT
metadata:
  keywords: "cloudflare-workers, workers-testing, vitest, vitest-workers, miniflare, cloudflare-test, unit-testing, integration-testing, binding-mocks, d1-testing, kv-testing, r2-testing, durable-objects-testing, queue-testing, workers-ai-testing, test-coverage, test-failures, mock-errors, @cloudflare/vitest-pool-workers, cloudflare:test, env-mocking, execution-context, workers-test-setup, vitest-config, test-driven-development, tdd-workers"
  version: "1.0.0"
  last_verified: "2025-01-27"
  production_tested: true
  token_savings: "~70%"
  errors_prevented: 8
  templates_included: 3
  references_included: 5
  scripts_included: 2
  vitest_version: "^2.0.0"
  workers_types_version: "4.20260408.0"
  vitest_pool_workers_version: "0.7.2"
---

# Cloudflare Workers Testing with Vitest

**Status**: ✅ Production Ready | Last Verified: 2025-01-27
**Vitest**: ^2.0.0 | **@cloudflare/vitest-pool-workers**: 0.7.2 | **Miniflare**: Latest

## Table of Contents

- [What Is Workers Testing?](#what-is-workers-testing)
- [New in 2025](#new-in-2025)
- [Quick Start (5 Minutes)](#quick-start-5-minutes)
- [Critical Rules](#critical-rules)
- [Core Concepts](#core-concepts)
- [Top 5 Use Cases](#top-5-use-cases)
- [Best Practices](#best-practices)
- [Top 8 Errors Prevented](#top-8-errors-prevented)
- [When to Load References](#when-to-load-references)

---

## What Is Workers Testing?

Testing Cloudflare Workers with **Vitest** and **@cloudflare/vitest-pool-workers** enables writing unit and integration tests that run in a real Workers environment with full binding support (D1, KV, R2, Durable Objects, Queues, AI). Tests execute in Miniflare for local development and can run in CI/CD with actual Workers runtime behavior.

**Key capabilities**: Binding mocks, execution context testing, edge runtime simulation, coverage tracking, fast test execution.

---

## New in 2025

**@cloudflare/vitest-pool-workers 0.7.2** (January 2025):
- **BREAKING**: Miniflare v3 → requires Node.js 20+
- **NEW**: `cloudflare:test` module for env/ctx access
- **IMPROVED**: Faster isolated storage for bindings
- **FIXED**: Worker-to-worker service bindings now work correctly
- **ADDED**: Support for Vectorize and Workers AI bindings

**Migration from older versions**:
```bash
# Update dependencies
bun add -D vitest@^2.1.8 @cloudflare/vitest-pool-workers@^0.7.2

# Update vitest.config.ts (new pool configuration format)
export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: './wrangler.jsonc' },
        miniflare: { compatibilityDate: '2025-01-27' }
      }
    }
  }
});
```

---

## Quick Start (5 Minutes)

### 1. Install Dependencies

```bash
bun add -D vitest @cloudflare/vitest-pool-workers
```

### 2. Create `vitest.config.ts`

```typescript
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';

export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: './wrangler.jsonc' },
        miniflare: {
          compatibilityDate: '2025-01-27',
          compatibilityFlags: ['nodejs_compat']
        }
      }
    }
  }
});
```

### 3. Write Your First Test

```typescript
import { describe, it, expect } from 'vitest';
import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test';
import worker from '../src/index';

describe('Worker', () => {
  it('responds with 200', async () => {
    const request = new Request('http://example.com/');
    const ctx = createExecutionContext();
    const response = await worker.fetch(request, env, ctx);
    await waitOnExecutionContext(ctx);

    expect(response.status).toBe(200);
  });
});
```

### 4. Run Tests

```bash
bun test
# or
bunx vitest
```

---

## Critical Rules

### 1. Always Use `cloudflare:test` for Env Access

**✅ CORRECT**:
```typescript
import { env } from 'cloudflare:test';

it('queries D1', async () => {
  const result = await env.DB.prepare('SELECT * FROM users').all();
  expect(result.results).toHaveLength(0); // Fresh isolated DB per test
});
```

**❌ WRONG**:
```typescript
// Don't manually create env object
const env = { DB: mockDB }; // ❌ Won't use real D1 binding
```

**Why**: `cloudflare:test` provides real bindings configured from `wrangler.jsonc` with isolated storage per test.

### 2. Always Wait on Execution Context

**✅ CORRECT**:
```typescript
it('handles async operations', async () => {
  const ctx = createExecutionContext();
  const response = await worker.fetch(request, env, ctx);
  await waitOnExecutionContext(ctx); // ✅ Ensures ctx.waitUntil completes

  expect(response.status).toBe(200);
});
```

**❌ WRONG**:
```typescript
it('missing wait', async () => {
  const ctx = createExecutionContext();
  const response = await worker.fetch(request, env, ctx);
  // ❌ Missing waitOnExecutionContext - ctx.waitUntil tasks may not complete
  expect(response.status).toBe(200);
});
```

**Why**: Workers use `ctx.waitUntil()` for background tasks (logging, analytics). Without waiting, these tasks may not complete in tests.

### 3. Each Test Gets Isolated Storage

**✅ CORRECT**:
```typescript
describe('KV Operations', () => {
  it('test 1: writes to KV', async () => {
    await env.CACHE.put('key', 'value1');
    const val = await env.CACHE.get('key');
    expect(val).toBe('value1'); // ✅ Isolated
  });

  it('test 2: clean state', async () => {
    const val = await env.CACHE.get('key');
    expect(val).toBeNull(); // ✅ Test 1's data doesn't leak here
  });
});
```

**Why**: Each test runs with fresh binding storage (automatic isolation).

### 4. Use Wrangler Config for Bindings

**✅ CORRECT**:
```typescript
// vitest.config.ts
export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: './wrangler.jsonc' } // ✅ Reads bindings from wrangler
      }
    }
  }
});
```

**❌ WRONG**:
```typescript
// vitest.config.ts
export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        // ❌ No wrangler config - bindings won't be available
        miniflare: { compatibilityDate: '2025-01-27' }
      }
    }
  }
});
```

**Why**: Wrangler config defines all bindings (D1, KV, R2, etc.). Without it, `env` will be empty.

### 5. Match Compatibility Date

**✅ CORRECT**:
```typescript
// vitest.config.ts
miniflare: {
  compatibilityDate: '2025-01-27' // ✅ Matches wrangler.jsonc
}

// wrangler.jsonc
{
  "compatibility_date": "2025-01-27"
}
```

**Why**: Ensures test environment matches production runtime behavior.

---

## Core Concepts

### Binding Testing Patterns

**D1 Database**:
```typescript
import { env } from 'cloudflare:test';

it('queries D1', async () => {
  // Insert test data
  await env.DB.prepare('INSERT INTO users (name) VALUES (?)').bind('Alice').run();

  // Query
  const result = await env.DB.prepare('SELECT * FROM users WHERE name = ?').bind('Alice').first();
  expect(result?.name).toBe('Alice');
});
```

**KV Namespace**:
```typescript
it('reads from KV', async () => {
  await env.CACHE.put('test-key', 'test-value');
  const value = await env.CACHE.get('test-key');
  expect(value).toBe('test-value');
});
```

**R2 Bucket**:
```typescript
it('uploads to R2', async () => {
  await env.BUCKET.put('file.txt', 'Hello World');
  const object = await env.BUCKET.get('file.txt');
  expect(await object?.text()).toBe('Hello World');
});
```

**Durable Objects**:
```typescript
it('interacts with Durable Object', async () => {
  const id = env.COUNTER.idFromName('test-counter');
  const stub = env.COUNTER.get(id);

  const response = await stub.fetch('http://fake/increment');
  const data = await response.json();
  expect(data.count).toBe(1);
});
```

### Unit vs Integration Tests

**Unit Test** (single function):
```typescript
import { validateInput } from '../src/utils/validator';

it('validates input', () => {
  const result = validateInput({ name: 'Alice', age: 30 });
  expect(result.valid).toBe(true);
});
```

**Integration Test** (full fetch handler):
```typescript
import worker from '../src/index';
import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test';

it('handles full request flow', async () => {
  const request = new Request('http://example.com/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'Alice' })
  });

  const ctx = createExecutionContext();
  const response = await worker.fetch(request, env, ctx);
  await waitOnExecutionContext(ctx);

  expect(response.status).toBe(201);
  const user = await response.json();
  expect(user.name).toBe('Alice');
});
```

### Coverage Configuration

Add to `vitest.config.ts`:
```typescript
export default defineWorkersConfig({
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
      include: ['src/**/*.ts'],
      exclude: ['src/**/*.test.ts', 'src/**/*.spec.ts'],
      thresholds: {
        lines: 80,
        functions: 80,
        branches: 80,
        statements: 80
      }
    }
  }
});
```

Run with coverage:
```bash
bunx vitest run --coverage
```

---

## Top 5 Use Cases

### 1. Testing API Endpoints with D1

```typescript
it('creates user via API', async () => {
  const request = new Request('http://example.com/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'Bob', email: '[email protected]' })
  });

  const ctx = createExecutionContext();
  const response = await worker.fetch(request, env, ctx);
  await waitOnExecutionContext(ctx);

  expect(response.status).toBe(201);

  // Verify DB insert
  const user = await env.DB.prepare('SELECT * FROM users WHERE email = ?')
    .bind('[email protected]')
    .first();
  expect(user?.name).toBe('Bob');
});
```

### 2. Testing Caching with KV

```typescript
it('caches API responses', async () => {
  // First request (cache miss)
  const req1 = new Request('http://example.com/api/data');
  const ctx1 = createExecutionContext();
  const res1 = await worker.fetch(req1, env, ctx1);
  await waitOnExecutionContext(ctx1);

  expect(res1.headers.get('X-Cache')).toBe('MISS');

  // Second request (cache hit)
  const req2 = new Request('http://example.com/api/data');
  const ctx2 = createExecutionContext();
  const res2 = await worker.fetch(req2, env, ctx2);
  await waitOnExecutionContext(ctx2);

  expect(res2.headers.get('X-Cache')).toBe('HIT');
});
```

### 3. Testing File Uploads to R2

```typescript
it('handles file upload', async () => {
  const formData = new FormData();
  formData.append('file', new Blob(['test content'], { type: 'text/plain' }), 'test.txt');

  const request = new Request('http://example.com/upload', {
    method: 'POST',
    body: formData
  });

  const ctx = createExecutionContext();
  const response = await worker.fetch(request, env, ctx);
  await waitOnExecutionContext(ctx);

  expect(response.status).toBe(200);

  // Verify R2 upload
  const object = await env.BUCKET.get('test.txt');
  expect(await object?.text()).toBe('test content');
});
```

### 4. Testing Durable Objects State

```typescript
it('maintains counter state', async () => {
  const id = env.COUNTER.idFromName('my-counter');
  const stub = env.COUNTER.get(id);

  // Increment 3 times
  for (let i = 0; i < 3; i++) {
    await stub.fetch('http://fake/increment');
  }

  // Verify state
  const response = await stub.fetch('http://fake/value');
  const data = await response.json();
  expect(data.count).toBe(3);
});
```

### 5. Testing Queue Consumers

```typescript
it('processes queue messages', async () => {
  const messages = [
    { id: '1', body: { action: 'email', to: '[email protected]' }, timestamp: new Date() }
  ];

  // Simulate queue batch
  await worker.queue(
    {
      queue: 'my-queue',
      messages,
      retryAll: () => {},
      ackAll: () => {}
    },
    env
  );

  // Verify processing (check DB, logs, etc.)
  const log = await env.DB.prepare('SELECT * FROM email_log WHERE id = ?').bind('1').first();
  expect(log?.status).toBe('sent');
});
```

---

## Best Practices

### ✅ DO

1. **Use descriptive test names**:
   ```typescript
   it('returns 404 when user not found', async () => {});
   it('validates email format before saving', async () => {});
   ```

2. **Test error cases**:
   ```typescript
   it('returns 400 for invalid JSON', async () => {
     const request = new Request('http://example.com/api', {
       method: 'POST',
       headers: { 'Content-Type': 'application/json' },
       body: 'invalid json'
     });

     const ctx = createExecutionContext();
     const response = await worker.fetch(request, env, ctx);
     await waitOnExecutionContext(ctx);

     expect(response.status).toBe(400);
   });
   ```

3. **Group related tests**:
   ```typescript
   describe('User API', () => {
     describe('POST /users', () => {
       it('creates user with valid data', async () => {});
       it('rejects duplicate email', async () => {});
       it('validates required fields', async () => {});
     });
   });
   ```

4. **Use beforeEach for setup**:
   ```typescript
   describe('Database tests', () => {
     beforeEach(async () => {
       // Seed test data
       await env.DB.prepare('INSERT INTO users (name) VALUES (?)').bind('Test User').run();
     });

     it('queries users', async () => {
       const result = await env.DB.prepare('SELECT * FROM users').all();
       expect(result.results).toHaveLength(1);
     });
   });
   ```

5. **Test realistic scenarios**:
   ```typescript
   it('handles concurrent requests', async () => {
     const requests = Array(10).fill(null).map(() =>
       worker.fetch(new Request('http://example.com/'), env, createExecutionContext())
     );

     const responses = await Promise.all(requests);
     expect(responses.every(r => r.status === 200)).toBe(true);
   });
   ```

### ❌ DON'T

1. **Don't share state between tests**:
   ```typescript
   // ❌ BAD: Leaky state
   let counter = 0;
   it('test 1', () => { counter++; });
   it('test 2', () => { expect(counter).toBe(1); }); // Fragile!

   // ✅ GOOD: Isolated
   it('test 1', () => { const counter = 0; counter++; });
   it('test 2', () => { const counter = 0; /* fresh state */ });
   ```

2. **Don't forget to wait**:
   ```typescript
   // ❌ BAD
   const response = await worker.fetch(request, env, ctx);
   expect(response.status).toBe(200); // ctx.waitUntil not finished

   // ✅ GOOD
   const response = await worker.fetch(request, env, ctx);
   await waitOnExecutionContext(ctx);
   expect(response.status).toBe(200);
   ```

3. **Don't hardcode URLs**:
   ```typescript
   // ❌ BAD
   const request = new Request('http://example.com/test');

   // ✅ GOOD
   const request = new Request('http://fake-host/test'); // Host doesn't matter in tests
   ```

4. **Don't test implementation details**:
   ```typescript
   // ❌ BAD: Testing internals
   expect(worker.privateHelperFunction).toBeDefined();

   // ✅ GOOD: Testing behavior
   const response = await worker.fetch(request, env, ctx);
   expect(response.status).toBe(200);
   ```

---

## Top 8 Errors Prevented

### 1. ❌ `ReferenceError: env is not defined`

**Cause**: Not importing `env` from `cloudflare:test`.

**Fix**:
```typescript
import { env } from 'cloudflare:test'; // ✅ Add this import
```

**Prevention**: Always use `cloudflare:test` module for env access.

---

### 2. ❌ `TypeError: Cannot read property 'DB' of undefined`

**Cause**: `wrangler.jsonc` not loaded in `vitest.config.ts`.

**Fix**:
```typescript
export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: './wrangler.jsonc' } // ✅ Add this
      }
    }
  }
});
```

**Prevention**: Always configure wrangler path in vitest config.

---

### 3. ❌ `Error: D1_ERROR: no such table: users`

**Cause**: D1 database schema not applied in tests.

**Fix**:
```typescript
// Option 1: Seed in beforeEach
beforeEach(async () => {
  await env.DB.exec(`
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY,
      name TEXT NOT NULL
    )
  `);
});

// Option 2: Use migrations (load from file)
beforeEach(async () => {
  const schema = await fs.readFile('./migrations/schema.sql', 'utf-8');
  await env.DB.exec(schema);
});
```

**Prevention**: Create schema before each test or use shared setup.

---

### 4. ❌ `Error: ctx.waitUntil tasks did not complete`

**Cause**: Missing `await waitOnExecutionContext(ctx)`.

**Fix**:
```typescript
const ctx = createExecutionContext();
const response = await worker.fetch(request, env, ctx);
await waitOnExecutionContext(ctx); // ✅ Add this
```

**Prevention**: Always wait on execution context in tests.

---

### 5. ❌ `Error: SELF is not defined`

**Cause**: Using old `SELF.fetch()` pattern instead of direct worker import.

**Fix**:
```typescript
// ❌ OLD (vitest-pool-workers <0.5)
import { SELF } from 'cloudflare:test';
await SELF.fetch(request);

// ✅ NEW (vitest-pool-workers ≥0.7)
import worker from '../src/index';
await worker.fetch(request, env, ctx);
```

**Prevention**: Use direct worker imports (modern pattern).

---

### 6. ❌ `Error: KV.get() returned data from previous test`

**Cause**: Believing storage is shared (it's not, but may indicate test leak).

**Fix**: Each test is isolated. If seeing this, check for:
```typescript
// ❌ Test pollution (shared variable)
let cache = {};
it('test 1', () => { cache.key = 'value'; });
it('test 2', () => { expect(cache.key).toBeUndefined(); }); // Fails!

// ✅ Proper isolation
it('test 1', async () => { await env.CACHE.put('key', 'value1'); });
it('test 2', async () => { const val = await env.CACHE.get('key'); expect(val).toBeNull(); });
```

**Prevention**: Don't use shared variables for test data.

---

### 7. ❌ `TypeError: env.BUCKET.put is not a function`

**Cause**: R2 binding not configured in `wrangler.jsonc`.

**Fix**:
```jsonc
// wrangler.jsonc
{
  "r2_buckets": [
    { "binding": "BUCKET", "bucket_name": "test-bucket" }
  ]
}
```

**Prevention**: Define all bindings in wrangler config.

---

### 8. ❌ `Error: Pool 'workers' is not supported`

**Cause**: Missing `@cloudflare/vitest-pool-workers` dependency.

**Fix**:
```bash
bun add -D @cloudflare/vitest-pool-workers
```

**Prevention**: Install pool package for Workers testing.

---

## When to Load References

Load reference files for detailed, specialized content:

**Load `references/vitest-setup.md` when:**
- Setting up Vitest from scratch
- Configuring custom pool options
- Troubleshooting Miniflare configuration
- Migrating from older vitest-pool-workers versions

**Load `references/binding-mocks.md` when:**
- Testing specific bindings (D1, KV, R2, DO, Queues, AI, Vectorize)
- Mocking service bindings (worker-to-worker)
- Creating test fixtures for bindings
- Understanding isolated storage behavior

**Load `references/integration-testing.md` when:**
- Writing full request/response tests
- Testing multi-step workflows
- Simulating production scenarios
- Testing WebSocket or streaming responses

**Load `references/coverage-optimization.md` when:**
- Setting up coverage thresholds
- Identifying untested code paths
- Optimizing test suite performance
- Configuring coverage reporters

**Load `references/troubleshooting.md` when:**
- Debugging failing tests
- Resolving binding errors
- Fixing timeout issues
- Understanding error messages

**Load `templates/vitest-config.ts` for:**
- Complete vitest.config.ts example
- Advanced configuration options
- Multiple wrangler environments

**Load `templates/basic-test.ts` for:**
- Test file structure template
- Common test patterns
- beforeEach/afterEach examples

**Load `templates/binding-mock-test.ts` for:**
- Binding-specific test examples
- D1, KV, R2, DO test patterns
- Queue and AI testing examples

**Load `scripts/setup-vitest.sh` for:**
- Automated Vitest installation
- Project configuration script

**Load `scripts/run-tests.sh` for:**
- CI/CD test execution
- Coverage reporting automation

---

## Related Cloudflare Plugins

**For service-specific testing patterns, load:**
- **cloudflare-d1** - D1 database testing, migrations, seeding
- **cloudflare-kv** - KV namespace testing, TTL verification
- **cloudflare-r2** - R2 bucket testing, file upload/download
- **cloudflare-durable-objects** - DO testing, WebSocket testing
- **cloudflare-queues** - Queue testing, batch processing
- **cloudflare-workers-ai** - AI model testing, inference mocking

**This skill focuses on cross-cutting Workers testing patterns** applicable to ALL binding types and Workers features.

---

**Questions?** Load `references/troubleshooting.md` or use `/workers-debug` command for interactive help.

© secondsky · MIT · secondsky/claude-skills

Similar skills

Everything for Testing and QA →

From the same set89

thesys-generative-ui A skill that teaches your agent to build React components from plain-language prompts with the Thesys SDK. Handy when you want a UI sketched out from a description. CX Codex +1 371installs maz-ui This skill teaches your agent Maz-UI v4: 50+ components, composables and directives for Vue 3 and Nuxt 3. Handy when you build forms, dialogs or data tables. CX Codex +1 369installs woocommerce-dev-cycle A skill that walks you through the WooCommerce dev cycle: run tests, fix code style, sort out linting errors. CX Codex +1 361installs woocommerce-copy-guidelines A skill that sets the rules for user-facing text in WooCommerce: button labels, field names, messages and docs. Useful when more than one person writes the storefront strings. CX Codex +1 363installs nuxt-seo A skill covering the eight Nuxt SEO v5 modules: robots.txt, sitemaps, OG images, Schema.org and meta tags. Useful when a Nuxt app needs SEO wired up. CX Codex +1 324installs cloudflare-workers-performance A Claude skill for Cloudflare Workers performance: CPU, memory, caching, bundle size. Useful when a worker is slow or hitting limits. CX Codex +1 315installs cloudflare-workers-runtime-apis A skill covering the Cloudflare Workers runtime APIs: Fetch, Streams, Crypto, Cache, WebSockets and text encoding. Handy when a worker trips over requests, streams or cache. CX Codex +1 311installs cloudflare-workers-frameworks Tells your agent how to run Hono, Remix, Next.js, Astro, SvelteKit, Qwik or Nuxt on Cloudflare Workers, and walks through the usual build errors. CX Codex +1 309installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor