Cloudcore

Public API

The Cloudcore Public API is a separate, read-only Cloudflare Worker that serves published content from your CMS database. It is designed to be the only internet-facing endpoint while the CMS admin stays behind Cloudflare Access or a VPN.

Why a separate API?

The CMS has authentication, user management, media uploads, and write operations. By splitting the public-facing read API into its own worker, you can:

  • Lock down the CMS behind Cloudflare Access (zero trust) or restrict it to a private network
  • Expose only reads — this API has zero write operations, zero auth endpoints, zero user data
  • Cache aggressively — read-only responses with configurable TTL for CDN edge caching
  • Rate limit independently — different limits for public traffic vs admin usage
  • Deploy and update separately — update the CMS without touching the public API, and vice versa

Architecture

Internet -> cloudcore-api (read-only) -> D1/R2 <- cloudcore-cms (locked down)
           api.example.com                          cms.example.com (CF Access)

Both workers share the same D1 database and R2 bucket. The CMS writes content, the Public API reads it. They deploy as independent workers so you can restrict access to each independently.

Security guarantees

  • Zero write operations — no INSERT, UPDATE, or DELETE anywhere in the codebase
  • Zero auth/user data — never reads users, sessions, passwords, audit logs, or settings
  • Zero admin endpoints — no login, no setup, no management
  • Method enforcement — rejects all POST/PUT/PATCH/DELETE at the middleware level
  • Rate limited — 120 requests/minute per IP
  • CORS configurable — restrict to your frontend domains
  • Single dependency — only Hono, zero npm vulnerabilities

Endpoints

MethodEndpointDescription
GET/Health check and endpoint list
GET/contentList published content. Query: ?type=page&limit=20&offset=0
GET/content/:type/:slugGet published content by type and slug
GET/categoriesList all categories
GET/tagsList all tags
GET/media/:idServe a media file

All other HTTP methods return 405 Method Not Allowed.

Deploy

cd packages/api
npm install

# Update wrangler.toml with your D1 database_id (same as the CMS)

npx wrangler deploy
# Live at https://cloudcore-api.your-subdomain.workers.dev

Configuration

VariableRequiredDescription
ALLOWED_ORIGINSRecommendedComma-separated allowed origins for CORS. Leave empty to allow all (dev only).
CACHE_TTLOptionalCache TTL in seconds for content responses (default: 60, max: 86400).

Connect your frontend

Point your frontend at the Public API instead of the CMS directly:

# React (Vite)
VITE_CMS_URL=https://api.yourdomain.com

# Next.js
NEXT_PUBLIC_CMS_URL=https://api.yourdomain.com

# Astro
PUBLIC_CMS_URL=https://api.yourdomain.com

Alternative: CMS built-in public routes

If you prefer not to deploy a separate worker, the CMS itself includes public read-only routes at /api/v1/public/*. These work the same way but share the worker with the admin endpoints. The separate Public API is recommended for production to reduce attack surface.