cloudflare workers hono angular saas
via PatrickJS/awesome-cursorrules
Full-stack SaaS on Cloudflare Workers with Hono APIs, Angular frontends, and enterprise integrations.
What is cloudflare workers hono angular saas?
This rule configures a complete SaaS stack combining Cloudflare Workers (Hono v4.12+), Angular 21+ frontend, D1/Neon databases, and production observability tools. Use it when building scalable, type-safe SaaS applications with strict TypeScript, RPC-style APIs, and enterprise security requirements.
- Enforces strict TypeScript with Zod validation and inline Hono handlers for type-safe RPC client generation
- Configures Angular 21+ standalone components with signals, control flow syntax, and PrimeNG UI components
- Provides Drizzle v1 ORM patterns for D1/Neon with batch APIs and prepared statements
- Implements OWASP Top 10:2025 security controls including CSP, HSTS, Turnstile, and Stripe webhook verification
- Defines Inngest v4 background job patterns with step functions and idempotent retries on Cloudflare Workers
- Establishes testing strategy with Playwright E2E (6 breakpoints), Vitest units, and Lighthouse/WCAG 2.2 AA quality gates
Applies to
File patterns this rule matches.
Rule definition (reference)
Source of truth, from the repository.
Cloudflare Workers + Hono + Angular SaaS
Full-stack SaaS on Cloudflare Workers with Hono API, Angular frontend, and enterprise integrations.
Stack
CF Workers+Hono v4.12+ | Angular 21+Ionic 8+PrimeNG 21 | D1/Neon | Drizzle v1 | Zod | Clerk Core 3 | Stripe | Inngest v4 | Resend | Bun 1.3 | Playwright v1.59+ | Vitest | ESLint+Prettier | PostHog | Sentry
TypeScript
- Strict mode, never
any(useunknown), preferinterfaceovertype readonlywhen not reassigned,undefinedovernull- Zod as source of truth for validation
- ESLint flat config (
eslint.config.ts) + typescript-eslint + Prettier
Hono API
- Inline handlers for RPC type inference (never separate controller files)
- Method chaining:
app.use().get().post()preserves types hc<AppType>(BASE_URL)for typed client@hono/zod-validatoron ALL request bodiesapp.onError()+app.notFound()centralized- Split large apps:
app.route('/path', subApp) - Error envelope:
{ error: string, code?: string, details?: unknown } createFactory<{ Bindings: Env }>()for reusable middleware chainsGET /healthreturns{ status, version, timestamp }
Angular
- Standalone only (no NgModules), Angular 21 zoneless by default
- Signals stable:
signal(),computed(),effect(),linkedSignal(),resource() HttpResourcefor data fetching- Control flow:
@if/@for/@switch/@defer(not*ngIf/*ngFor) - kebab-case files, one component per file,
providedIn: 'root' - PrimeNG for UI components
Drizzle v1
sqliteTablefor D1, plural snake_case tables$inferSelect/$inferInsertfor typescreateInsertSchema/createSelectSchemafromdrizzle-orm/zod- Batch API (not
BEGIN— D1 doesn't support transactions) - Prepared statements for repeated queries
CF Workers
- CPU limit: 10ms free / 30s paid
ctx.waitUntil()for async post-response workctx.passThroughOnException()for graceful degradation- Bindings typed via
Envinterface - D1 global read replication for latency reduction
- Workers Builds for native CI/CD (preview URLs per branch)
Inngest v4 (Background Jobs)
eventType('name', { schema: z.object({...}) })per-event (v4 breaking)inngest/cloudflareadapter +inngest.setEnvVars(c.env)for Workers- Step functions:
step.run(),step.sleep(),step.waitForEvent(),step.sendEvent() step.ai.infer()offloads inference (zero compute during wait)step.realtime.publish()for durable pub/sub- Each step idempotent, retried independently
Testing (TDD)
- Failing test FIRST, then implement
- Playwright for E2E: 6 breakpoints (375, 390, 768, 1024, 1280, 1920)
- Vitest for unit tests
- No sleeps — use
waitFor/toBeVisible() - Selectors:
data-testid> role > text - axe-core 0 violations
PROD_URLenv var for production testing
Security (OWASP Top 10:2025)
- Must: HSTS, CSP (nonce-based strict), X-Content-Type-Options, X-Frame-Options
- Must: Referrer-Policy, Permissions-Policy, COOP, COEP, CORP
- Remove: X-XSS-Protection, Expect-CT, Server, X-Powered-By
- Turnstile on all forms, Zod validation on all inputs
- Stripe webhooks: verify signature, deduplicate via KV
Auth (Clerk)
- JWT verified per-request (no session store)
- Webhook sync: Clerk → D1 for user data
- RBAC: Clerk org roles for org-scoped, D1 for app-level
- Route layers: public → auth-only → role-gated → owner-only
Quality
- Lighthouse: a11y ≥95, perf ≥75
- WCAG 2.2 AA compliance
- LCP ≤2.5s, CLS ≤0.1, INP ≤200ms
- JS ≤200KB gz, CSS ≤50KB gz
- Functions ≤50 lines, cyclomatic complexity ≤10
Deploy
npx wrangler deploy && curl -sX POST \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"purge_everything":true}'
Hono Worker Starter
import { Hono } from 'hono';
import { secureHeaders } from 'hono/secure-headers';
import { cors } from 'hono/cors';
interface Env {
DB: D1Database;
KV: KVNamespace;
AI: Ai;
TURNSTILE_SECRET: string;
}
const app = new Hono<{ Bindings: Env }>();
app.use('*', secureHeaders());
app.use('/api/*', cors({ origin: ['https://yourdomain.com'] }));
app.get('/health', (c) => c.json({ status: 'ok', timestamp: new Date().toISOString() }));
export default app;
Related rules
Code development guidelines for precise, efficient AI-assisted changes without unnecessary commentary.
Guidelines for writing clean, interview-ready code during pair programming sessions.
Analyze codebase patterns and adapt new code to match established style conventions.
Enforce disciplined code review practices and focused AI assistance behavior.

Best practices and syntax guidelines for Convex backend development.

Modern C++ and CMake with RAII, const-correctness, and safe error handling.