Design — Stack pinning (April 2026)
- Date: 2026-04-16
- Sourced from: live npm + GitHub + vendor docs, agent-verified
- Policy: pin minor versions in
package.json; Renovate auto-PRs patch bumps; humans review minor+ bumps
All packages below are current stable as of 2026-04-16. Scaffolding uses these exact versions.
Runtimes + toolchain
Section titled “Runtimes + toolchain”| Package | Version | Notes |
|---|---|---|
| Bun | 1.3.12 | Primary package manager + runtime for local dev |
| Node.js | 24 LTS | CI fallback; Node 20 EOL 2026-04-30; Astro 6 requires ≥22 |
| pnpm | 10.33.0 | Workspace manager (v11 beta; stay on 10) |
| Turborepo | 2.9.6 | Affected-only builds, remote cache |
| TypeScript | 6.0 | Last JS-based; TS 7 (Go-native) previewing mid-2026 — not yet |
| Biome | 2.4 | Lint + format; embedded CSS/GraphQL, 15 HTML a11y rules |
| Wrangler | 4.82 | Stay on wrangler@4; cf next-gen CLI is preview-only |
Frontend frameworks
Section titled “Frontend frameworks”| Package | Version | Notes |
|---|---|---|
| Astro | 6.1.6 | Marketing site; requires Node 22+, Vite Env API |
| @astrojs/cloudflare | 13.1.x | v13 required for Astro 6 |
| @astrojs/sitemap | 3.7.2 | — |
| @astrojs/mdx | 5.0.3 | — |
| @astrojs/react | 5.0.3 | For React islands on marketing |
| SvelteKit | 2.57.1 | App framework |
| Svelte | 5.53.0 | Runes mode is the default; legacy $: still supported |
| @sveltejs/adapter-cloudflare | 7.2.8 | — |
| React | 19.2.5 | For Astro islands only |
Styling + UI primitives
Section titled “Styling + UI primitives”| Package | Version | Notes |
|---|---|---|
| Tailwind CSS | 4.2.1 | CSS-first config via @theme — no tailwind.config.ts |
| @tailwindcss/vite | 4.2.2 | Required integration (not PostCSS) |
| shadcn-svelte | 1.2.7 | Svelte 5 compatible; CLI + components |
| bits-ui | 2.17.3 | Svelte headless primitives (Radix-equivalent) |
| cmdk-sv | latest | Svelte port; upstream cmdk is stale |
| tiptap (@tiptap/core) | 3.22.3 | MD editor for admin UI; v3 adds SSR |
| motion | 12.38.0 | Animation; import from motion/react (not framer-motion) |
Backend + data
Section titled “Backend + data”| Package | Version | Notes |
|---|---|---|
| Hono | 4.12.12 | Streaming/LLM routes |
| Drizzle ORM | 0.45.2 | v1 beta available; stay on 0.45 |
| drizzle-kit | 0.31.9 | Schema migrations |
| better-auth | 1.6.2 | OpenTelemetry spans in 1.6 |
| Zod | 4.3.6 | v4 default export |
| nanoid | 5.1.7 | ESM-only since v5 |
| @paralleldrive/cuid2 | 2.x | Preferred for security-sensitive IDs (API keys, session tokens) |
AI + LLM
Section titled “AI + LLM”| Package / Model | Version / ID | Notes |
|---|---|---|
| ai (Vercel AI SDK) | 6.0.161 | v6 is current; greenfield starts here |
| @ai-sdk/svelte | 4.0.138 | Aligned with AI SDK 6 |
| @ai-sdk/anthropic | 3.0.69 | Anthropic provider |
| @ai-sdk/react | 3.0.158 | Marketing-site islands only |
| Claude Haiku | claude-haiku-4-5-20251001 |
No Haiku 5; still latest |
| Claude Sonnet | claude-sonnet-4-6 |
1M context, Feb 2026 |
| Claude Opus | claude-opus-4-6 |
1M context, Feb 2026 |
| Workers AI — Thai LLM (exit ramp) | @cf/aisingapore/gemma-sea-lion-v4-27b-it |
SEA-tuned, best Thai fluency on CF; use this if we ever route off Anthropic |
| Workers AI — Thai LLM (alt) | @cf/meta/llama-3.3-70b-instruct-fp8-fast |
Generic; Thai OK, not great |
| Workers AI — embedder | @cf/baai/bge-m3 |
Multilingual incl. Thai |
| Workers AI — reranker | @cf/baai/bge-reranker-base |
English-only; NOT sufficient for Thai — see ADR-0004 §10 for our path |
Forms + editor
Section titled “Forms + editor”| Package | Version | Notes |
|---|---|---|
| sveltekit-superforms | 2.x | Stable |
| Formsnap | 2.0.1 | Slow cadence but still recommended; monitor |
Ingestion helpers
Section titled “Ingestion helpers”| Package | Version | Notes |
|---|---|---|
| unpdf | 1.x | Replaces pdf-parse — edge/Workers-compatible pdf.js wrapper |
| mammoth | 1.11.0 | DOCX → HTML (MD output is deprecated — chain with turndown) |
| turndown | 7.x | HTML → MD |
| unified / remark / rehype | 11.x / 15.x / 13.x | Workers-compatible |
| micromark | 4.x | Smallest CommonMark parser; used in widget |
| markdown-it | 14.x | App-side rendering (richer plugin ecosystem) |
Testing + quality
Section titled “Testing + quality”| Package | Version | Notes |
|---|---|---|
| Vitest | 4.1.4 | Needs Vite ≥6, Node ≥20 |
| @vitest/coverage-v8 | 4.1.4 | Version-locked to Vitest |
| Playwright | 1.59.1 | E2E |
| Promptfoo | 0.121.4 | Eval harness; OpenAI acquired team Mar 2026, still MIT |
Observability + payments + email
Section titled “Observability + payments + email”| Package | Version | Notes |
|---|---|---|
| @sentry/sveltekit | 10.45.0 | — |
| @sentry/cloudflare | 10.48.0 | Use this name; @sentry/cloudflare-workers is deprecated |
| stripe | 22.0.0 | API version 2026-03-25.dahlia; Thai entity invoicing |
| resend | 6.11.0 | Transactional email |
Cloudflare bindings
Section titled “Cloudflare bindings”| Package | Version | Notes |
|---|---|---|
| @cloudflare/workers-types | 4.20260411.1 | CF now recommends wrangler types over this package — use wrangler types by default, fall back to pkg if needed |
| miniflare | bundled | Ships inside workers-sdk; standalone v2 deprecated |
| Turnstile | script tag | https://challenges.cloudflare.com/turnstile/v0/api.js — no official npm; react-turnstile@1.1.5 unofficial for React islands |
Breaking-change notes for Puccha
Section titled “Breaking-change notes for Puccha”- AI SDK v5 → v6:
useChatinput state is now external;append→sendMessage;convertToCoreMessages→convertToModelMessages;toDataStreamResponse→toUIMessageStreamResponse;experimental_providerMetadata→providerOptions. All our ADR-0004 snippets already use v6 names. - Node 20 EOL 2026-04-30: CI and production targets must be Node 24 by Beta launch.
- Astro 6 + @astrojs/cloudflare 13: mandatory pairing.
- Tailwind v4 CSS-first: move config into
src/styles/tokens.cssas@theme { … }; deletetailwind.config.ts. - Svelte 5 runes: use
$state,$derived,$effect— no legacy$:. - TypeScript 6: no action needed now; TS 7 (Go) will be breaking — start with
--stableTypeOrderingflag enabled. - Drizzle 0.31+ drizzle-kit: dropped
IF NOT EXISTSDDL emission — migrations are explicit creates/drops. - nanoid ESM-only: ensure
package.jsonhas"type": "module"or use.mjs. - mammoth MD deprecated: DOCX ingest chain =
mammoth.convertToHtml()→turndown()→ normalize. - pdf-parse broken on Workers: use
unpdfinstead. Fixes ADR-0004 §2. - Stripe API pinning: pin
apiVersion: '2026-03-25.dahlia'in SDK client; set explicitly in webhook handler. - @sentry/cloudflare-workers deprecated: import from
@sentry/cloudflare. - wrangler types: prefer
wrangler typesover@cloudflare/workers-typespackage; keeps in sync with yourwrangler.toml. - cmdk stale: use
cmdk-svon Svelte side; no replacement needed for React islands (shadcn-svelte handles palette).
Pin policy
Section titled “Pin policy”- package.json: exact-minor pins (
"svelte": "5.53.0","ai": "6.0.161"). No^ranges on the top 20 packages. - Renovate auto-PRs patch bumps with
automerge: trueafter CI passes. - Minor bumps require human review in PR.
- Major bumps create a tracked migration issue; handled by a dedicated PR, never bundled with features.
- Quarterly audit: re-run this research; update file; bump any stalled packages.