Experiment Structure
Every experiment lives underexperiments/<name>/ with this standardized layout:
Directory Breakdown
src/index.ts
src/index.ts
The main entry point for the Worker. This file:
- Creates a new Hono app instance
- Mounts route handlers
- Registers global error handling
- Exports
{ fetch: app.fetch }
src/routes/
src/routes/
Contains route handlers only. Each file exports a Hono app with one or more related routes.Example from
src/routes/check.ts:src/lib/
src/lib/
Domain logic and business functionality. This includes:
- URL validation
- Fetch operations
- Data parsing
- External API interactions
src/lib/url.ts:src/utils/
src/utils/
Shared helper functions used across the experiment.Example from
src/utils/response.ts:src/constants/
src/constants/
Optional directory for configuration values and literals.Example from
src/constants/defaults.ts:src/types/
src/types/
All TypeScript type definitions. Worker environment bindings go in
env.d.ts.Example from src/types/env.d.ts:Core Principles
No shared code between experiments: Each experiment is standalone with its own
package.json and dependencies. Do not import from other experiments or the repo root.Single responsibility: One experiment = one Cloudflare capability (e.g. Workers AI, Browser Rendering, D1).
Edge-first, under ~60 seconds: Prefer stateless, fast request paths that complete quickly.
TypeScript and API Style
Strict TypeScript
- Use strict TypeScript; avoid
any - Type Worker env in
src/types/env.d.tsand useHono<{ Bindings: Env }> - All types should be explicitly defined
Error Handling
Use a shared helper for client errors:400for bad request (invalid input)404for not found502for server/upstream errors (don’t expose internals)
Success Responses
UsejsonSuccess(c, data) for JSON success responses:
Global Error Handler
Insrc/index.ts, register app.onError(...) so uncaught errors return consistent JSON:
URL Parameter Validation
For any endpoint that takes aurl query param:
- Validate with a shared
validateUrl(input)insrc/lib/url.ts - Allow only
http://andhttps:// - Return
jsonErrorwith a clear message and code (e.g.INVALID_URL) when invalid
Naming Conventions
- Error codes: Descriptive uppercase with underscores (e.g.
INVALID_URL,FETCH_ERROR,INTERNAL_ERROR) - Routes: Files in
src/routes/with kebab-case filenames matching the path (e.g.check.tsfor/check) - Functions: camelCase for functions and variables
- Types: PascalCase for interfaces and types
Real-World Examples
Error Handling Pattern
Fromsrc/lib/fetch.ts in the is-it-down experiment:
Database Operations with Error Handling
Fromsrc/routes/shorten.ts in the link-shortener experiment:
Configuration Files
wrangler.toml/wrangler.json
Declare all Cloudflare bindings (D1, KV, R2, AI, etc.) in this file. These bindings must also be typed insrc/types/env.d.ts.
package.json
Each experiment has its own dependencies. Common dependencies:hono- Web framework@cloudflare/workers-types- TypeScript types for Workers
tsconfig.json
Enable strict mode and configure paths appropriately for the experiment.Quality Checklist
Before submitting a PR, ensure:- TypeScript strict mode is enabled with no
anytypes - All errors use
jsonErrorwith descriptive codes - Global error handler is registered in
index.ts - URL parameters are validated with
validateUrl - Environment bindings are declared in both
wrangler.tomlandsrc/types/env.d.ts - Routes are in
src/routes/, logic insrc/lib/, helpers insrc/utils/ - The experiment can be deployed with
npx wrangler deploy - README.md documents the API and usage
Next Steps
- Learn how to add new experiments
- Review the Contributing Guide
- Explore existing experiments in the repository