Skip to content

PRD: Cloudflare standards, deploy readiness, AI-readiness & maintainability improvements (2026-08 audit) #21

Description

@tkowalczyk

PRD: Bring tstack-on-cf to current Cloudflare standards (deploy readiness, AI-readiness, maintainability)

Audit date: 2026-08-07 · Baseline: Cloudflare Workers Best Practices guide (2026-02-15), Wrangler v4 standards, Workers Logs/Traces/Source Maps, Smart Placement, Hyperdrive, versioned deployments, vitest-pool-workers, llms.txt/AGENTS.md agent conventions.

Background

tstack-on-cf is the TanStack Start + Hono template on Cloudflare Workers (@cloudflare/vite-plugin, Neon Postgres via drizzle neon-http, three wrangler envs, Biome 2 + GritQL plugins, Vitest 4, semantic-release). The audit found a strong base — observability logs (100%) + traces (1%) enabled, compat-date auto-bump bot, weekly taze bumps, clean secrets hygiene, accurate llms.txt with a symlinked AGENTS.md, meta-tests that keep config/docs honest, and a completed workers-best-practices issue series (#5#16) that must not be re-proposed. This PRD covers what remains.

Goals

  1. Close the remaining Cloudflare-standards gaps (source maps, placement, Hyperdrive decision, env routing posture, CI-safe typegen).
  2. Gate and automate the path to production (PR CI, CD, migration story, rollback guidance).
  3. Keep agent-facing docs truthful (dead /docs pointer, README drift, missing LICENSE) and extend agent tooling (.mcp.json, Codex parity).
  4. Make tests exercise the real runtime and clean up masked dead dependencies.

Non-goals

  • New product features or UI work.
  • Replacing Neon/Drizzle or the TanStack/Hono architecture.
  • Re-doing anything from the closed workers-best-practices series (secrets out of vars, observability, env blocks, onError, structured logging, /api routing, DB singleton, cf-typegen pre-push).

Workstream 1 — Cloudflare standards conformance

  • Enable source map upload. No upload_source_maps in wrangler.jsonc — production stack traces are minified in Workers Logs despite logs+traces being on. Add "upload_source_maps": true (top-level, inherited by envs).
  • Enable Smart Placement for staging/production. The Worker makes sequential round-trips to Neon pinned in eu-central-1 (src/db/setup.ts) — the canonical Smart Placement case. Add placement: { "mode": "smart" } and measure.
  • Decide Hyperdrive vs neon-http, and record it. Cloudflare's standard for external Postgres is a Hyperdrive binding (pooling + edge caching); the repo uses the neon-http fetch driver directly. Evaluate Hyperdrive (drizzle-orm/node-postgres) against neon-http and document the decision either way.
  • Give staging/production a routing posture. wrangler.jsonc:15-24 env blocks are name+vars only — no routes/custom_domain, no explicit workers_dev/preview_urls, despite the repo's own .claude/rules/cloudflare-deployment.md recommending custom_domain: true. Add commented placeholders + explicit posture per env.
  • Make cf-typegen CI-safe. Typegen currently depends on gitignored .dev.vars for secret inference, forcing SKIP_SIMPLE_GIT_HOOKS=1 in all three workflows and a deliberate typegen skip in compat-date.yml:96-101. Type the secrets explicitly in committed service-bindings.d.ts (interface Env extends BaseEnv { DATABASE_HOST: string; … }) — then typegen runs anywhere and the workarounds get deleted. (Also evaluate the new secrets.required wrangler config property as the declared source of truth.)

Workstream 2 — Deployment readiness

  • Add PR CI. .github/workflows/ has only release.yml (post-merge), deps-update.yml, compat-date.yml; nothing validates pull requests, including the bots' own PRs. Add ci.yml on pull_request + push running lint:ci, types, test, knip, and vite build.
  • Add CD. Deploys run from a laptop with local wrangler auth (package.json:13-15). Add staged CD via cloudflare/wrangler-action (staging on main push, production on release tag, CLOUDFLARE_API_TOKEN secret) or Workers Builds; include the env-scoped build first.
  • Finish the per-env migration story. Only src/db/migrations/dev/ exists; .staging.vars/.production.vars are empty placeholders and migrations run manually via dotenvx. Wire db:migrate:<env> into the CD flow (migrate → deploy) or document the manual gate explicitly.
  • Document the auth/security posture of the API. src/hono/api/clients.ts is public unauthenticated CRUD with no rate limiting or CORS anywhere. For a template that's acceptable only if loud: add an auth middleware slot in src/hono/factory.ts (e.g. bearer/JWT) and a security-posture section in README.
  • Pin Node. No engines, no .nvmrc; CI floats on lts/*. Add both.
  • Add rollback/gradual-rollout guidance. Nothing in README about wrangler versions upload, gradual deployments, or wrangler rollback for incidents.

Workstream 3 — AI-readiness

  • Fix the dead /docs pointer. AGENTS.md:86-89 and README.md:437 declare /docs the single source of truth for business requirements; the directory doesn't exist. Create it with a stub or remove the claim.
  • Fix README drift (3 spots). README.md:155 shows compatibility_date: "2025-09-02" vs actual 2026-05-25; README.md:112 claims migrations/{dev,staging,production}/ but only dev/ exists; README.md:454 links a LICENSE file that doesn't exist despite the MIT claim. Fix all three, add the LICENSE, and consider extending the repo's meta-test pattern to enforce the wrangler snippet.
  • Add .mcp.json. Ship Cloudflare docs/bindings MCP servers (and optionally Neon MCP) as project-scoped config — the template already commits to agent-assisted workflows.
  • Close the Codex parity gap or declare it. .codex/agents/ has 1 of the 3 .claude/agents/ (only mvp-e); hooks are mirrored but agents aren't. Mirror them or state the supported-agent matrix (same for the absent .cursor/).

Workstream 4 — Maintainability

  • Make tests exercise the real runtime. 10 files / ~27 cases, all config-heavy: no @cloudflare/vitest-pool-workers (so src/server.ts dispatch, env wiring, and SSR never run in workerd) and zero component tests (vitest.config.ts doesn't even set jsdom). Add a Vitest workspace: workers-pool project for server/Hono + jsdom project for components — or delete the unused testing deps.
  • Remove dead devDependencies masked by knip config. web-vitals, @tanstack/react-form, @testing-library/dom, @testing-library/react have zero usages but are hidden via knip.json ignoreDependencies; knip also ignores all of src/db/** and src/core/errors.ts. Remove the deps and shrink the ignore list.
  • Create a major-upgrade cadence. Vite is exact-pinned at 7.1.2 with Vite 8.2.1 out; taze minor mode never proposes majors and nothing tracks them (also pending: Biome 2.5.x, TS 7/tsgo evaluation). Add a scheduled majors report that opens/updates an issue.
  • Explain pnpm-workspace.yaml. It exists solely for pnpm 10 allowBuilds with no packages: key — add a comment so humans and agents stop assuming a monorepo.
  • Minor: align .example.vars naming with wrangler's .dev.vars.example convention; enable verbatimModuleSyntax (Biome already enforces useImportType).

Prioritization

Priority Items
P0 PR CI; CD pipeline; CI-safe typegen (unblocks the bot workflows)
P1 upload_source_maps; Smart Placement; migration story; README drift + LICENSE; /docs pointer; workers-pool tests
P2 Hyperdrive decision record; routing posture; auth slot + security docs; .mcp.json; Codex parity; dead deps; majors cadence; Node pin

Acceptance criteria

  • PRs cannot merge without lint/types/test/build passing; staging deploys on main, production on release, both from CI.
  • pnpm run cf-typegen produces identical output with or without .dev.vars present; the SKIP_SIMPLE_GIT_HOOKS workarounds are gone from workflows.
  • wrangler.jsonc has upload_source_maps and Smart Placement on server envs; a written decision exists for Hyperdrive vs neon-http.
  • README contains no stale snippets or dead links; LICENSE exists; AGENTS.md pointers all resolve.
  • At least one test suite runs inside workerd via vitest-pool-workers; knip passes with a minimal ignore list.

Out of scope

Executing the Vite 8 / TS 7 majors (tracked by the new cadence), replacing Neon, building real auth (only the middleware slot + docs are in scope).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestworkers-best-practicesCloudflare Workers best-practices audit finding

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions