The API is built with Hono framework, TypeScript, and Zod OpenAPI for type-safe, self-documenting endpoints running on Cloudflare Pages Functions.
- Runtime: Cloudflare Workers (via Pages Functions)
- Framework: Hono 4.x (edge-optimized web framework)
- Language: TypeScript 5.x with strict mode
- Validation: Zod 4.x with OpenAPI integration
- OpenAPI: @hono/zod-openapi for automatic spec generation
- Build: TypeScript compiler (tsc) for type checking
functions/
├── _worker.ts # Main Hono app entry point
├── types/
│ ├── env.ts # Environment & context types
│ └── data.ts # Data model types (Region, Service, etc.)
├── schemas/
│ └── common.ts # Shared Zod schemas with OpenAPI metadata
├── routes/
│ └── v1/
│ ├── ping.ts # GET /api/v1/ping
│ ├── health.ts # GET /api/v1/health
│ ├── services.ts # GET /api/v1/services (with statistics)
│ ├── services-by-id.ts # GET /api/v1/services/{serviceId}
│ ├── regions.ts # GET /api/v1/regions
│ └── regions-by-id.ts # GET /api/v1/regions/{id}
├── middleware/ # Custom middleware (future)
├── utils/
│ ├── data.ts # Data access & statistics helpers
│ ├── response.ts # Response formatting helpers
│ └── validation.ts # Validation utilities
└── regions.json # Generated region data (build artifact)
- Request → Cloudflare Pages Functions
- _worker.ts → Hono router
- Global Middleware:
- Security headers (X-Content-Type-Options, X-Frame-Options, etc.)
- CORS headers (allow all origins)
- X-API-Version header
- Cache-Control header (for API endpoints)
- Route Handler:
- Zod validates request parameters
- Business logic executes
- Response formatted with type safety
- Response → Client
Applied in order:
secureHeaders()- Hono's built-in security headerscors()- CORS configuration for cross-origin requests- Custom API version header middleware
- Custom cache control middleware (API routes only)
Routes are registered in _worker.ts:
import { OpenAPIHono } from '@hono/zod-openapi'
import { registerPingRoute } from './routes/v1/ping'
// ... other imports
const app = new OpenAPIHono<{ Bindings: Env }>()
// Global middleware
app.use('*', secureHeaders())
app.use('*', cors({ origin: '*' }))
// Register routes
registerPingRoute(app)
registerHealthRoute(app)
// ... other routes
export default appexport interface Env {
ENVIRONMENT?: string // 'production' | 'preview' | 'unknown'
}All data models are defined in types/data.ts:
Region- Cloud region with servicesService- VDC service metadataVdcVaultConfig- Vault tier/edition configurationRegionServices- Available services per region
Schemas in schemas/common.ts provide:
- Runtime validation
- TypeScript type inference
- OpenAPI documentation generation
- Automatic request/response validation
Example:
export const RegionSchema = z.object({
id: z.string().openapi({
description: 'Unique region identifier',
example: 'aws-us-east-1'
}),
// ... more fields
}).openapi('Region')The API automatically generates OpenAPI 3.1 specification at /api/openapi.json.
- ✅ Automatic schema generation from Zod types
- ✅ Request parameter validation
- ✅ Response schema validation
- ✅ Rich descriptions for LLM consumption
- ✅ Examples for all fields
- ✅ Error response documentation
GET /api/openapi.jsonReturns all VDC services with regional availability statistics.
Response includes:
- Service metadata (id, name, type, description)
regionCount: Total regions supporting the serviceproviderBreakdown: Count of AWS vs Azure regionsconfigurationBreakdown: For tiered services, count per edition-tier combination
Use cases:
- Compare service coverage across VDC offerings
- Understand which services have the widest availability
- See distribution of services across cloud providers
Returns detailed information about a specific service.
Path parameters:
serviceId: Service identifier (vdc_vault, vdc_m365, vdc_entra_id, vdc_salesforce, vdc_azure_backup)
Response includes:
- Complete service metadata
- List of all region IDs supporting the service
- Provider breakdown with region lists
- Configuration breakdown with region lists (for tiered services)
Use cases:
- Get all regions supporting a specific service
- Find which regions support specific edition-tier combinations
- Understand geographic distribution of a service
Returns all regions with optional filtering.
Query parameters:
provider: Filter by AWS or Azureservice: Filter by service IDtier: Filter by tier (vdc_vault only)edition: Filter by edition (vdc_vault only)country: Search by country/location name
Returns detailed information about a specific region.
Path parameters:
id: Region identifier (e.g., aws-us-east-1)
Simple health check endpoint.
Detailed health status with environment information.
All errors follow a consistent format:
{
"error": "Short error message",
"code": "ERROR_CODE_ENUM",
"message": "Detailed explanation",
"parameter": "fieldName",
"value": "invalidValue",
"allowedValues": ["valid", "values"]
}Error codes:
REGION_NOT_FOUND- Region ID doesn't existSERVICE_NOT_FOUND- Service ID doesn't existINVALID_PARAMETER- Query parameter invalidINTERNAL_ERROR- Server error
npm run build:data # Generate regions.json from YAML
npm run typecheck # Validate TypeScript
npm run build # Full build (data + typecheck + hugo)- Source:
data/regions/*.yamlfiles - Build:
scripts/build-api-data.jsprocesses YAML - Output:
functions/regions.json - Import: Routes import via
utils/data.ts - Type Safety: Validated against
Regiontype
The API deploys automatically via Cloudflare Pages:
- Build Command:
npm run build - Output Directory:
public - Functions: Auto-compiled from
functions/_worker.ts - TypeScript: Cloudflare Pages compiles TS automatically
Set in Cloudflare Pages dashboard or wrangler.toml:
[env.production.vars]
ENVIRONMENT = "production"
[env.preview.vars]
ENVIRONMENT = "preview"- ✅ Hono is optimized for Cloudflare Workers (minimal overhead)
- ✅ Static data loaded once at Worker initialization
- ✅ Response caching via Cache-Control headers (1 hour)
- ✅ CORS preflight handled by middleware
- ✅ No database queries (static JSON data)
- Hono core: ~12KB
- Zod + OpenAPI: ~30KB
- Application code: ~20KB
- Total: ~62KB (well within Workers limits)
X-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-Policy: strict-origin-when-cross-originAccess-Control-Allow-Origin: *(public API)
- All request parameters validated by Zod
- Type safety prevents injection attacks
- Read-only data source (no mutations)
- Rate limiting middleware
- API key authentication (optional)
- Request logging/analytics
- GraphQL endpoint
- Webhooks for data updates
- Complete rich documentation porting (4-6 hours)
- Add response examples for all endpoints
- Generate OpenAPI YAML output
- OpenAPI UI (Swagger/Redoc)
# Build data
npm run build:data
# Type check
npm run typecheck
# Deploy to preview for testing
git push origin <branch>- Create route file in
routes/v1/ - Define Zod schemas with OpenAPI metadata
- Create route using
createRoute() - Implement handler function
- Register in
_worker.ts - Export registration function
Example:
// routes/v1/example.ts
import { createRoute } from '@hono/zod-openapi'
import { z } from '@hono/zod-openapi'
const exampleRoute = createRoute({
method: 'get',
path: '/api/v1/example',
summary: 'Example endpoint',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({ message: z.string() })
}
}
}
}
})
export function registerExampleRoute(app) {
app.openapi(exampleRoute, (c) => {
return c.json({ message: 'Hello!' })
})
}