opencodekit 0.15.4 → 0.15.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/dist/index.js +2 -2
  2. package/dist/template/.opencode/agent/explore.md +13 -12
  3. package/dist/template/.opencode/command/cloudflare.md +70 -0
  4. package/dist/template/.opencode/memory/observations/2026-01-19-learning-oh-my-opencode-slim-vs-opencodekit-templ.md +27 -0
  5. package/dist/template/.opencode/package.json +1 -1
  6. package/dist/template/.opencode/plugin/sessions.ts +38 -4
  7. package/dist/template/.opencode/skill/cloudflare/SKILL.md +233 -0
  8. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/README.md +35 -0
  9. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/api.md +100 -0
  10. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/configuration.md +99 -0
  11. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/gotchas.md +59 -0
  12. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/patterns.md +89 -0
  13. package/dist/template/.opencode/skill/cloudflare/references/ai-gateway/README.md +695 -0
  14. package/dist/template/.opencode/skill/cloudflare/references/ai-search/README.md +14 -0
  15. package/dist/template/.opencode/skill/cloudflare/references/ai-search/api.md +38 -0
  16. package/dist/template/.opencode/skill/cloudflare/references/ai-search/configuration.md +52 -0
  17. package/dist/template/.opencode/skill/cloudflare/references/ai-search/gotchas.md +41 -0
  18. package/dist/template/.opencode/skill/cloudflare/references/ai-search/patterns.md +45 -0
  19. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/README.md +14 -0
  20. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/api.md +27 -0
  21. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/configuration.md +45 -0
  22. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/gotchas.md +3 -0
  23. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/patterns.md +36 -0
  24. package/dist/template/.opencode/skill/cloudflare/references/api/README.md +21 -0
  25. package/dist/template/.opencode/skill/cloudflare/references/api/api.md +31 -0
  26. package/dist/template/.opencode/skill/cloudflare/references/api/configuration.md +20 -0
  27. package/dist/template/.opencode/skill/cloudflare/references/api/gotchas.md +28 -0
  28. package/dist/template/.opencode/skill/cloudflare/references/api/patterns.md +47 -0
  29. package/dist/template/.opencode/skill/cloudflare/references/api-shield/README.md +20 -0
  30. package/dist/template/.opencode/skill/cloudflare/references/api-shield/api.md +78 -0
  31. package/dist/template/.opencode/skill/cloudflare/references/api-shield/configuration.md +128 -0
  32. package/dist/template/.opencode/skill/cloudflare/references/api-shield/gotchas.md +51 -0
  33. package/dist/template/.opencode/skill/cloudflare/references/api-shield/patterns.md +145 -0
  34. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/README.md +16 -0
  35. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/api.md +50 -0
  36. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/configuration.md +53 -0
  37. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/gotchas.md +16 -0
  38. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/patterns.md +45 -0
  39. package/dist/template/.opencode/skill/cloudflare/references/bindings/README.md +14 -0
  40. package/dist/template/.opencode/skill/cloudflare/references/bindings/api.md +3 -0
  41. package/dist/template/.opencode/skill/cloudflare/references/bindings/configuration.md +58 -0
  42. package/dist/template/.opencode/skill/cloudflare/references/bindings/gotchas.md +35 -0
  43. package/dist/template/.opencode/skill/cloudflare/references/bindings/patterns.md +37 -0
  44. package/dist/template/.opencode/skill/cloudflare/references/bot-management/README.md +71 -0
  45. package/dist/template/.opencode/skill/cloudflare/references/bot-management/api.md +168 -0
  46. package/dist/template/.opencode/skill/cloudflare/references/bot-management/configuration.md +114 -0
  47. package/dist/template/.opencode/skill/cloudflare/references/bot-management/gotchas.md +99 -0
  48. package/dist/template/.opencode/skill/cloudflare/references/bot-management/patterns.md +125 -0
  49. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/README.md +16 -0
  50. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/api.md +54 -0
  51. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/configuration.md +47 -0
  52. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/gotchas.md +29 -0
  53. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/patterns.md +29 -0
  54. package/dist/template/.opencode/skill/cloudflare/references/c3/README.md +264 -0
  55. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/README.md +93 -0
  56. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/api.md +176 -0
  57. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/configuration.md +164 -0
  58. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/gotchas.md +203 -0
  59. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/patterns.md +180 -0
  60. package/dist/template/.opencode/skill/cloudflare/references/containers/README.md +16 -0
  61. package/dist/template/.opencode/skill/cloudflare/references/containers/api.md +43 -0
  62. package/dist/template/.opencode/skill/cloudflare/references/containers/configuration.md +56 -0
  63. package/dist/template/.opencode/skill/cloudflare/references/containers/gotchas.md +21 -0
  64. package/dist/template/.opencode/skill/cloudflare/references/containers/patterns.md +40 -0
  65. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/README.md +85 -0
  66. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/api.md +198 -0
  67. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/configuration.md +151 -0
  68. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/gotchas.md +129 -0
  69. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/patterns.md +122 -0
  70. package/dist/template/.opencode/skill/cloudflare/references/d1/README.md +92 -0
  71. package/dist/template/.opencode/skill/cloudflare/references/d1/api.md +141 -0
  72. package/dist/template/.opencode/skill/cloudflare/references/d1/configuration.md +127 -0
  73. package/dist/template/.opencode/skill/cloudflare/references/d1/gotchas.md +70 -0
  74. package/dist/template/.opencode/skill/cloudflare/references/d1/patterns.md +144 -0
  75. package/dist/template/.opencode/skill/cloudflare/references/ddos/README.md +34 -0
  76. package/dist/template/.opencode/skill/cloudflare/references/ddos/api.md +136 -0
  77. package/dist/template/.opencode/skill/cloudflare/references/ddos/configuration.md +67 -0
  78. package/dist/template/.opencode/skill/cloudflare/references/ddos/gotchas.md +114 -0
  79. package/dist/template/.opencode/skill/cloudflare/references/ddos/patterns.md +158 -0
  80. package/dist/template/.opencode/skill/cloudflare/references/do-storage/README.md +62 -0
  81. package/dist/template/.opencode/skill/cloudflare/references/do-storage/api.md +89 -0
  82. package/dist/template/.opencode/skill/cloudflare/references/do-storage/configuration.md +116 -0
  83. package/dist/template/.opencode/skill/cloudflare/references/do-storage/gotchas.md +93 -0
  84. package/dist/template/.opencode/skill/cloudflare/references/do-storage/patterns.md +112 -0
  85. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/README.md +125 -0
  86. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/api.md +152 -0
  87. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/configuration.md +148 -0
  88. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/gotchas.md +158 -0
  89. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/patterns.md +255 -0
  90. package/dist/template/.opencode/skill/cloudflare/references/email-routing/README.md +18 -0
  91. package/dist/template/.opencode/skill/cloudflare/references/email-routing/api.md +46 -0
  92. package/dist/template/.opencode/skill/cloudflare/references/email-routing/configuration.md +63 -0
  93. package/dist/template/.opencode/skill/cloudflare/references/email-routing/gotchas.md +16 -0
  94. package/dist/template/.opencode/skill/cloudflare/references/email-routing/patterns.md +46 -0
  95. package/dist/template/.opencode/skill/cloudflare/references/email-workers/README.md +598 -0
  96. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/README.md +62 -0
  97. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/api.md +137 -0
  98. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/configuration.md +133 -0
  99. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/gotchas.md +184 -0
  100. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/patterns.md +176 -0
  101. package/dist/template/.opencode/skill/cloudflare/references/images/README.md +14 -0
  102. package/dist/template/.opencode/skill/cloudflare/references/images/api.md +3 -0
  103. package/dist/template/.opencode/skill/cloudflare/references/images/configuration.md +45 -0
  104. package/dist/template/.opencode/skill/cloudflare/references/images/gotchas.md +23 -0
  105. package/dist/template/.opencode/skill/cloudflare/references/images/patterns.md +31 -0
  106. package/dist/template/.opencode/skill/cloudflare/references/kv/README.md +60 -0
  107. package/dist/template/.opencode/skill/cloudflare/references/kv/api.md +114 -0
  108. package/dist/template/.opencode/skill/cloudflare/references/kv/configuration.md +92 -0
  109. package/dist/template/.opencode/skill/cloudflare/references/kv/gotchas.md +117 -0
  110. package/dist/template/.opencode/skill/cloudflare/references/kv/patterns.md +139 -0
  111. package/dist/template/.opencode/skill/cloudflare/references/miniflare/README.md +64 -0
  112. package/dist/template/.opencode/skill/cloudflare/references/miniflare/api.md +144 -0
  113. package/dist/template/.opencode/skill/cloudflare/references/miniflare/configuration.md +203 -0
  114. package/dist/template/.opencode/skill/cloudflare/references/miniflare/gotchas.md +187 -0
  115. package/dist/template/.opencode/skill/cloudflare/references/miniflare/patterns.md +211 -0
  116. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/README.md +60 -0
  117. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/api.md +240 -0
  118. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/configuration.md +127 -0
  119. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/gotchas.md +171 -0
  120. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/patterns.md +171 -0
  121. package/dist/template/.opencode/skill/cloudflare/references/observability/README.md +18 -0
  122. package/dist/template/.opencode/skill/cloudflare/references/observability/api.md +51 -0
  123. package/dist/template/.opencode/skill/cloudflare/references/observability/configuration.md +60 -0
  124. package/dist/template/.opencode/skill/cloudflare/references/observability/gotchas.md +36 -0
  125. package/dist/template/.opencode/skill/cloudflare/references/observability/patterns.md +42 -0
  126. package/dist/template/.opencode/skill/cloudflare/references/pages/README.md +76 -0
  127. package/dist/template/.opencode/skill/cloudflare/references/pages/api.md +200 -0
  128. package/dist/template/.opencode/skill/cloudflare/references/pages/configuration.md +228 -0
  129. package/dist/template/.opencode/skill/cloudflare/references/pages/gotchas.md +161 -0
  130. package/dist/template/.opencode/skill/cloudflare/references/pages/patterns.md +145 -0
  131. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/README.md +57 -0
  132. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/api.md +201 -0
  133. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/configuration.md +159 -0
  134. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/gotchas.md +151 -0
  135. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/patterns.md +190 -0
  136. package/dist/template/.opencode/skill/cloudflare/references/pipelines/README.md +664 -0
  137. package/dist/template/.opencode/skill/cloudflare/references/pulumi/README.md +107 -0
  138. package/dist/template/.opencode/skill/cloudflare/references/pulumi/api.md +194 -0
  139. package/dist/template/.opencode/skill/cloudflare/references/pulumi/configuration.md +216 -0
  140. package/dist/template/.opencode/skill/cloudflare/references/pulumi/gotchas.md +223 -0
  141. package/dist/template/.opencode/skill/cloudflare/references/pulumi/patterns.md +139 -0
  142. package/dist/template/.opencode/skill/cloudflare/references/queues/README.md +69 -0
  143. package/dist/template/.opencode/skill/cloudflare/references/queues/api.md +138 -0
  144. package/dist/template/.opencode/skill/cloudflare/references/queues/configuration.md +125 -0
  145. package/dist/template/.opencode/skill/cloudflare/references/queues/gotchas.md +112 -0
  146. package/dist/template/.opencode/skill/cloudflare/references/queues/patterns.md +155 -0
  147. package/dist/template/.opencode/skill/cloudflare/references/r2/README.md +61 -0
  148. package/dist/template/.opencode/skill/cloudflare/references/r2/api.md +127 -0
  149. package/dist/template/.opencode/skill/cloudflare/references/r2/configuration.md +76 -0
  150. package/dist/template/.opencode/skill/cloudflare/references/r2/gotchas.md +94 -0
  151. package/dist/template/.opencode/skill/cloudflare/references/r2/patterns.md +127 -0
  152. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/README.md +18 -0
  153. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/api.md +29 -0
  154. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/configuration.md +39 -0
  155. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/gotchas.md +20 -0
  156. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/patterns.md +46 -0
  157. package/dist/template/.opencode/skill/cloudflare/references/r2-sql/README.md +512 -0
  158. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/README.md +21 -0
  159. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/api.md +135 -0
  160. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/configuration.md +63 -0
  161. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/gotchas.md +75 -0
  162. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/patterns.md +102 -0
  163. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/README.md +81 -0
  164. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/api.md +164 -0
  165. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/configuration.md +147 -0
  166. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/gotchas.md +172 -0
  167. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/patterns.md +155 -0
  168. package/dist/template/.opencode/skill/cloudflare/references/sandbox/README.md +90 -0
  169. package/dist/template/.opencode/skill/cloudflare/references/sandbox/api.md +178 -0
  170. package/dist/template/.opencode/skill/cloudflare/references/sandbox/configuration.md +131 -0
  171. package/dist/template/.opencode/skill/cloudflare/references/sandbox/gotchas.md +156 -0
  172. package/dist/template/.opencode/skill/cloudflare/references/sandbox/patterns.md +203 -0
  173. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/README.md +58 -0
  174. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/api.md +182 -0
  175. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/configuration.md +140 -0
  176. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/gotchas.md +129 -0
  177. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/patterns.md +218 -0
  178. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/README.md +91 -0
  179. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/api.md +139 -0
  180. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/configuration.md +129 -0
  181. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/gotchas.md +87 -0
  182. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/patterns.md +135 -0
  183. package/dist/template/.opencode/skill/cloudflare/references/snippets/README.md +15 -0
  184. package/dist/template/.opencode/skill/cloudflare/references/snippets/api.md +47 -0
  185. package/dist/template/.opencode/skill/cloudflare/references/snippets/configuration.md +33 -0
  186. package/dist/template/.opencode/skill/cloudflare/references/snippets/gotchas.md +21 -0
  187. package/dist/template/.opencode/skill/cloudflare/references/snippets/patterns.md +34 -0
  188. package/dist/template/.opencode/skill/cloudflare/references/spectrum/README.md +16 -0
  189. package/dist/template/.opencode/skill/cloudflare/references/spectrum/api.md +24 -0
  190. package/dist/template/.opencode/skill/cloudflare/references/spectrum/configuration.md +43 -0
  191. package/dist/template/.opencode/skill/cloudflare/references/spectrum/gotchas.md +42 -0
  192. package/dist/template/.opencode/skill/cloudflare/references/spectrum/patterns.md +40 -0
  193. package/dist/template/.opencode/skill/cloudflare/references/static-assets/README.md +14 -0
  194. package/dist/template/.opencode/skill/cloudflare/references/static-assets/api.md +3 -0
  195. package/dist/template/.opencode/skill/cloudflare/references/static-assets/configuration.md +47 -0
  196. package/dist/template/.opencode/skill/cloudflare/references/static-assets/gotchas.md +44 -0
  197. package/dist/template/.opencode/skill/cloudflare/references/static-assets/patterns.md +42 -0
  198. package/dist/template/.opencode/skill/cloudflare/references/stream/README.md +103 -0
  199. package/dist/template/.opencode/skill/cloudflare/references/stream/api.md +204 -0
  200. package/dist/template/.opencode/skill/cloudflare/references/stream/configuration.md +127 -0
  201. package/dist/template/.opencode/skill/cloudflare/references/stream/gotchas.md +131 -0
  202. package/dist/template/.opencode/skill/cloudflare/references/stream/patterns.md +152 -0
  203. package/dist/template/.opencode/skill/cloudflare/references/tail-workers/README.md +640 -0
  204. package/dist/template/.opencode/skill/cloudflare/references/terraform/README.md +76 -0
  205. package/dist/template/.opencode/skill/cloudflare/references/terraform/api.md +159 -0
  206. package/dist/template/.opencode/skill/cloudflare/references/terraform/configuration.md +156 -0
  207. package/dist/template/.opencode/skill/cloudflare/references/terraform/gotchas.md +207 -0
  208. package/dist/template/.opencode/skill/cloudflare/references/terraform/patterns.md +135 -0
  209. package/dist/template/.opencode/skill/cloudflare/references/tunnel/README.md +82 -0
  210. package/dist/template/.opencode/skill/cloudflare/references/tunnel/api.md +105 -0
  211. package/dist/template/.opencode/skill/cloudflare/references/tunnel/configuration.md +113 -0
  212. package/dist/template/.opencode/skill/cloudflare/references/tunnel/gotchas.md +115 -0
  213. package/dist/template/.opencode/skill/cloudflare/references/tunnel/patterns.md +157 -0
  214. package/dist/template/.opencode/skill/cloudflare/references/turn/README.md +699 -0
  215. package/dist/template/.opencode/skill/cloudflare/references/turnstile/README.md +14 -0
  216. package/dist/template/.opencode/skill/cloudflare/references/turnstile/api.md +3 -0
  217. package/dist/template/.opencode/skill/cloudflare/references/turnstile/configuration.md +19 -0
  218. package/dist/template/.opencode/skill/cloudflare/references/turnstile/gotchas.md +27 -0
  219. package/dist/template/.opencode/skill/cloudflare/references/turnstile/patterns.md +41 -0
  220. package/dist/template/.opencode/skill/cloudflare/references/vectorize/README.md +682 -0
  221. package/dist/template/.opencode/skill/cloudflare/references/waf/README.md +14 -0
  222. package/dist/template/.opencode/skill/cloudflare/references/waf/api.md +3 -0
  223. package/dist/template/.opencode/skill/cloudflare/references/waf/configuration.md +44 -0
  224. package/dist/template/.opencode/skill/cloudflare/references/waf/gotchas.md +24 -0
  225. package/dist/template/.opencode/skill/cloudflare/references/waf/patterns.md +29 -0
  226. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/README.md +19 -0
  227. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/api.md +52 -0
  228. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/configuration.md +31 -0
  229. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/gotchas.md +28 -0
  230. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/patterns.md +52 -0
  231. package/dist/template/.opencode/skill/cloudflare/references/workerd/README.md +47 -0
  232. package/dist/template/.opencode/skill/cloudflare/references/workerd/api.md +199 -0
  233. package/dist/template/.opencode/skill/cloudflare/references/workerd/configuration.md +185 -0
  234. package/dist/template/.opencode/skill/cloudflare/references/workerd/gotchas.md +203 -0
  235. package/dist/template/.opencode/skill/cloudflare/references/workerd/patterns.md +216 -0
  236. package/dist/template/.opencode/skill/cloudflare/references/workers/README.md +96 -0
  237. package/dist/template/.opencode/skill/cloudflare/references/workers/api.md +137 -0
  238. package/dist/template/.opencode/skill/cloudflare/references/workers/configuration.md +147 -0
  239. package/dist/template/.opencode/skill/cloudflare/references/workers/gotchas.md +99 -0
  240. package/dist/template/.opencode/skill/cloudflare/references/workers/patterns.md +149 -0
  241. package/dist/template/.opencode/skill/cloudflare/references/workers-ai/README.md +116 -0
  242. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/README.md +48 -0
  243. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/api.md +169 -0
  244. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/configuration.md +136 -0
  245. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/gotchas.md +130 -0
  246. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/patterns.md +170 -0
  247. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/README.md +16 -0
  248. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/api.md +20 -0
  249. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/configuration.md +3 -0
  250. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/gotchas.md +35 -0
  251. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/patterns.md +42 -0
  252. package/dist/template/.opencode/skill/cloudflare/references/workers-vpc/README.md +579 -0
  253. package/dist/template/.opencode/skill/cloudflare/references/workflows/README.md +62 -0
  254. package/dist/template/.opencode/skill/cloudflare/references/workflows/api.md +125 -0
  255. package/dist/template/.opencode/skill/cloudflare/references/workflows/configuration.md +177 -0
  256. package/dist/template/.opencode/skill/cloudflare/references/workflows/gotchas.md +136 -0
  257. package/dist/template/.opencode/skill/cloudflare/references/workflows/patterns.md +132 -0
  258. package/dist/template/.opencode/skill/cloudflare/references/wrangler/README.md +90 -0
  259. package/dist/template/.opencode/skill/cloudflare/references/wrangler/api.md +140 -0
  260. package/dist/template/.opencode/skill/cloudflare/references/wrangler/configuration.md +128 -0
  261. package/dist/template/.opencode/skill/cloudflare/references/wrangler/gotchas.md +93 -0
  262. package/dist/template/.opencode/skill/cloudflare/references/wrangler/patterns.md +150 -0
  263. package/dist/template/.opencode/skill/cloudflare/references/zaraz/README.md +360 -0
  264. package/dist/template/.opencode/skill/react-best-practices/AGENTS.md +2410 -0
  265. package/dist/template/.opencode/skill/react-best-practices/README.md +123 -0
  266. package/dist/template/.opencode/skill/react-best-practices/SKILL.md +125 -0
  267. package/dist/template/.opencode/skill/react-best-practices/metadata.json +15 -0
  268. package/dist/template/.opencode/skill/react-best-practices/rules/_sections.md +46 -0
  269. package/dist/template/.opencode/skill/react-best-practices/rules/_template.md +28 -0
  270. package/dist/template/.opencode/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  271. package/dist/template/.opencode/skill/react-best-practices/rules/advanced-use-latest.md +49 -0
  272. package/dist/template/.opencode/skill/react-best-practices/rules/async-api-routes.md +38 -0
  273. package/dist/template/.opencode/skill/react-best-practices/rules/async-defer-await.md +80 -0
  274. package/dist/template/.opencode/skill/react-best-practices/rules/async-dependencies.md +36 -0
  275. package/dist/template/.opencode/skill/react-best-practices/rules/async-parallel.md +28 -0
  276. package/dist/template/.opencode/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  277. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  278. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-conditional.md +31 -0
  279. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  280. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  281. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-preload.md +50 -0
  282. package/dist/template/.opencode/skill/react-best-practices/rules/client-event-listeners.md +74 -0
  283. package/dist/template/.opencode/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
  284. package/dist/template/.opencode/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  285. package/dist/template/.opencode/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
  286. package/dist/template/.opencode/skill/react-best-practices/rules/js-batch-dom-css.md +82 -0
  287. package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
  288. package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
  289. package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-storage.md +70 -0
  290. package/dist/template/.opencode/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
  291. package/dist/template/.opencode/skill/react-best-practices/rules/js-early-exit.md +50 -0
  292. package/dist/template/.opencode/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
  293. package/dist/template/.opencode/skill/react-best-practices/rules/js-index-maps.md +37 -0
  294. package/dist/template/.opencode/skill/react-best-practices/rules/js-length-check-first.md +49 -0
  295. package/dist/template/.opencode/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
  296. package/dist/template/.opencode/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
  297. package/dist/template/.opencode/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  298. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-activity.md +26 -0
  299. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  300. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
  301. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
  302. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  303. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  304. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
  305. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
  306. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
  307. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
  308. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  309. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  310. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-memo.md +44 -0
  311. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-transitions.md +40 -0
  312. package/dist/template/.opencode/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
  313. package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-lru.md +41 -0
  314. package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-react.md +76 -0
  315. package/dist/template/.opencode/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
  316. package/dist/template/.opencode/skill/react-best-practices/rules/server-serialization.md +38 -0
  317. package/dist/template/.opencode/skill/supabase/SKILL.md +120 -0
  318. package/dist/template/.opencode/skill/supabase/mcp.json +27 -0
  319. package/dist/template/.opencode/skill/vercel-deploy-claimable/SKILL.md +112 -0
  320. package/dist/template/.opencode/skill/vercel-deploy-claimable/scripts/deploy.sh +249 -0
  321. package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +39 -0
  322. package/dist/template/.opencode/tool/memory-read.ts +64 -44
  323. package/dist/template/.opencode/tool/memory-search.ts +9 -2
  324. package/dist/template/.opencode/tool/memory-update.ts +59 -47
  325. package/dist/template/.opencode/tool/observation.ts +16 -2
  326. package/package.json +1 -1
@@ -0,0 +1,112 @@
1
+ # DO Storage Patterns & Best Practices
2
+
3
+ ## Schema Migration
4
+
5
+ ```typescript
6
+ export class MyDurableObject extends DurableObject {
7
+ constructor(ctx: DurableObjectState, env: Env) {
8
+ super(ctx, env);
9
+ this.sql = ctx.storage.sql;
10
+ this.sql.exec(`CREATE TABLE IF NOT EXISTS _meta(key TEXT PRIMARY KEY, value TEXT)`);
11
+ const ver = this.sql.exec("SELECT value FROM _meta WHERE key = 'schema_version'").toArray()[0]?.value || "0";
12
+ if (ver === "0") this.sql.exec(`CREATE TABLE users(id INTEGER PRIMARY KEY, name TEXT); INSERT OR REPLACE INTO _meta VALUES ('schema_version', '1')`);
13
+ if (ver === "1") this.sql.exec(`ALTER TABLE users ADD COLUMN email TEXT; UPDATE _meta SET value = '2' WHERE key = 'schema_version'`);
14
+ }
15
+ }
16
+ ```
17
+
18
+ ## In-Memory Caching
19
+
20
+ ```typescript
21
+ export class UserCache extends DurableObject {
22
+ cache = new Map<string, User>();
23
+ async getUser(id: string): Promise<User> {
24
+ if (this.cache.has(id)) return this.cache.get(id)!;
25
+ const user = await this.ctx.storage.get<User>(`user:${id}`);
26
+ if (user) this.cache.set(id, user);
27
+ return user;
28
+ }
29
+ async updateUser(id: string, data: Partial<User>) {
30
+ const updated = { ...await this.getUser(id), ...data };
31
+ this.cache.set(id, updated);
32
+ await this.ctx.storage.put(`user:${id}`, updated);
33
+ return updated;
34
+ }
35
+ }
36
+ ```
37
+
38
+ ## Rate Limiting
39
+
40
+ ```typescript
41
+ export class RateLimiter extends DurableObject {
42
+ async checkLimit(key: string, limit: number, window: number): Promise<boolean> {
43
+ const now = Date.now();
44
+ this.sql.exec('DELETE FROM requests WHERE key = ? AND timestamp < ?', key, now - window);
45
+ const count = this.sql.exec('SELECT COUNT(*) as count FROM requests WHERE key = ?', key).one().count;
46
+ if (count >= limit) return false;
47
+ this.sql.exec('INSERT INTO requests (key, timestamp) VALUES (?, ?)', key, now);
48
+ return true;
49
+ }
50
+ }
51
+ ```
52
+
53
+ ## Batch Processing with Alarms
54
+
55
+ ```typescript
56
+ export class BatchProcessor extends DurableObject {
57
+ pending: string[] = [];
58
+ async addItem(item: string) {
59
+ this.pending.push(item);
60
+ if (!await this.ctx.storage.getAlarm()) await this.ctx.storage.setAlarm(Date.now() + 5000);
61
+ }
62
+ async alarm() {
63
+ const items = [...this.pending];
64
+ this.pending = [];
65
+ this.sql.exec(`INSERT INTO processed_items (item, timestamp) VALUES ${items.map(() => "(?, ?)").join(", ")}`, ...items.flatMap(item => [item, Date.now()]));
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## Initialization Pattern
71
+
72
+ ```typescript
73
+ export class Counter extends DurableObject {
74
+ value: number;
75
+ constructor(ctx: DurableObjectState, env: Env) {
76
+ super(ctx, env);
77
+ ctx.blockConcurrencyWhile(async () => { this.value = (await ctx.storage.get("value")) || 0; });
78
+ }
79
+ async increment() {
80
+ this.value++;
81
+ this.ctx.storage.put("value", this.value); // Don't await (output gate protects)
82
+ return this.value;
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## Safe Counter / Optimized Write
88
+
89
+ ```typescript
90
+ // Input gate blocks other requests
91
+ async getUniqueNumber(): Promise<number> {
92
+ let val = await this.ctx.storage.get("counter");
93
+ await this.ctx.storage.put("counter", val + 1);
94
+ return val;
95
+ }
96
+
97
+ // No await on write - output gate delays response until write confirms
98
+ async increment(): Promise<Response> {
99
+ let val = await this.ctx.storage.get("counter");
100
+ this.ctx.storage.put("counter", val + 1);
101
+ return new Response(String(val));
102
+ }
103
+ ```
104
+
105
+ ## Cleanup
106
+
107
+ ```typescript
108
+ async cleanup() {
109
+ await this.ctx.storage.deleteAlarm(); // Separate from deleteAll
110
+ await this.ctx.storage.deleteAll();
111
+ }
112
+ ```
@@ -0,0 +1,125 @@
1
+ # Cloudflare Durable Objects
2
+
3
+ Expert guidance for building stateful applications with Cloudflare Durable Objects.
4
+
5
+ ## Overview
6
+
7
+ Durable Objects combine compute with storage in globally-unique, strongly-consistent packages:
8
+ - **Globally unique instances**: Each DO has unique ID for multi-client coordination
9
+ - **Co-located storage**: Fast, strongly-consistent storage with compute
10
+ - **Automatic placement**: Objects spawn near first request location
11
+ - **Stateful serverless**: In-memory state + persistent storage
12
+ - **Single-threaded**: Serial request processing (no race conditions)
13
+
14
+ ## When to Use DOs
15
+
16
+ Use DOs for **stateful coordination**, not stateless request handling:
17
+ - **Coordination**: Multiple clients interacting with shared state (chat rooms, multiplayer games)
18
+ - **Strong consistency**: Operations must serialize to avoid races (booking systems, inventory)
19
+ - **Per-entity storage**: Each user/tenant/resource needs isolated database (multi-tenant SaaS)
20
+ - **Persistent connections**: Long-lived WebSockets that survive across requests
21
+ - **Per-entity scheduled work**: Each entity needs its own timer (subscription renewals, game timeouts)
22
+
23
+ ## When NOT to Use DOs
24
+
25
+ | Scenario | Use Instead |
26
+ |----------|-------------|
27
+ | Stateless request handling | Workers |
28
+ | Maximum global distribution | Workers |
29
+ | High fan-out (independent requests) | Workers |
30
+ | Global singleton handling all traffic | Shard across multiple DOs |
31
+ | High-frequency pub/sub | Queues |
32
+ | Long-running continuous processes | Workers + Alarms |
33
+ | Chatty microservice (every request) | Reconsider architecture |
34
+ | Eventual consistency OK, read-heavy | KV |
35
+ | Relational queries across entities | D1 |
36
+
37
+ ## Design Heuristics
38
+
39
+ Model each DO around your **atom of coordination**—the logical unit needing serialized access (user, room, document, session).
40
+
41
+ | Characteristic | Feels Right | Question It | Reconsider |
42
+ |----------------|-------------|-------------|------------|
43
+ | Requests/sec (sustained) | < 100 | 100-500 | > 500 |
44
+ | Storage keys | < 100 | 100-1000 | > 1000 |
45
+ | Total state size | < 10MB | 10MB-100MB | > 1GB |
46
+ | Alarm frequency | Minutes-hours | Every 30s | Every few seconds |
47
+ | WebSocket duration | Short bursts | Hours (hibernating) | Days always-on |
48
+ | Fan-out from this DO | Never/rarely | To < 10 DOs | To 100+ DOs |
49
+
50
+ ## Core Concepts
51
+
52
+ ### Class Structure
53
+ All DOs extend `DurableObject` base class with constructor receiving `DurableObjectState` (storage, WebSockets, alarms) and `Env` (bindings).
54
+
55
+ ### Accessing from Workers
56
+ Workers use bindings to get stubs, then call RPC methods directly (recommended) or use fetch handler (legacy).
57
+
58
+ ### ID Generation
59
+ - `idFromName()`: Deterministic, named coordination
60
+ - `newUniqueId()`: Random IDs for sharding
61
+ - `idFromString()`: Derive from existing IDs
62
+ - Jurisdiction option: Data locality
63
+
64
+ ### Storage Options
65
+ - **SQLite** (recommended): Structured data, transactions, 10GB/DO
66
+ - **Synchronous KV API**: Simple key-value on SQLite objects
67
+ - **Asynchronous KV API**: Legacy/advanced use cases
68
+
69
+ ### Special Features
70
+ - **Alarms**: Schedule future execution per-DO
71
+ - **WebSocket Hibernation**: Zero-cost idle connections
72
+ - **Point-in-Time Recovery**: Restore to any point in 30 days
73
+
74
+ ## Quick Start
75
+
76
+ ```typescript
77
+ import { DurableObject } from "cloudflare:workers";
78
+
79
+ export class Counter extends DurableObject<Env> {
80
+ async increment(): Promise<number> {
81
+ const result = this.ctx.storage.sql.exec(
82
+ `INSERT INTO counters (id, value) VALUES (1, 1)
83
+ ON CONFLICT(id) DO UPDATE SET value = value + 1
84
+ RETURNING value`
85
+ ).one();
86
+ return result.value;
87
+ }
88
+ }
89
+
90
+ // Worker access
91
+ export default {
92
+ async fetch(request: Request, env: Env): Promise<Response> {
93
+ const id = env.COUNTER.idFromName("global");
94
+ const stub = env.COUNTER.get(id);
95
+ const count = await stub.increment();
96
+ return new Response(`Count: ${count}`);
97
+ }
98
+ };
99
+ ```
100
+
101
+ ## Essential Commands
102
+
103
+ ```bash
104
+ npx wrangler dev # Local dev with DOs
105
+ npx wrangler dev --remote # Test against prod DOs
106
+ npx wrangler deploy # Deploy + auto-apply migrations
107
+ ```
108
+
109
+ ## Resources
110
+
111
+ **Docs**: https://developers.cloudflare.com/durable-objects/
112
+ **API Reference**: https://developers.cloudflare.com/durable-objects/api/
113
+ **Examples**: https://developers.cloudflare.com/durable-objects/examples/
114
+
115
+ ## In This Reference
116
+
117
+ - [Configuration](./configuration.md) - wrangler.jsonc setup, migrations, bindings
118
+ - [API](./api.md) - Class structure, storage APIs, alarms, WebSockets
119
+ - [Patterns](./patterns.md) - Rate limiting, locks, real-time collab, sessions
120
+ - [Gotchas](./gotchas.md) - Limits, common issues, troubleshooting
121
+
122
+ ## See Also
123
+
124
+ - [Workers](../workers/README.md) - Core Workers runtime
125
+ - [DO Storage](../do-storage/README.md) - Deep dive on storage APIs
@@ -0,0 +1,152 @@
1
+ # Durable Objects API
2
+
3
+ ## Class Structure
4
+
5
+ ```typescript
6
+ import { DurableObject } from "cloudflare:workers";
7
+
8
+ export class MyDO extends DurableObject<Env> {
9
+ constructor(ctx: DurableObjectState, env: Env) {
10
+ super(ctx, env);
11
+ // Initialize storage/run migrations before any requests
12
+ ctx.blockConcurrencyWhile(async () => {
13
+ await this.migrate();
14
+ });
15
+ }
16
+ async myMethod(arg: string): Promise<string> { return arg; }
17
+ async alarm() { }
18
+ async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer) { }
19
+ }
20
+ ```
21
+
22
+ ## Concurrency Model
23
+
24
+ ### Input/Output Gates
25
+
26
+ DOs are single-threaded but async/await allows request interleaving. The runtime uses **gates** to prevent data races:
27
+
28
+ **Input gates** block new events while synchronous JS executes. Awaiting async ops opens the gate, allowing interleaving. Storage operations provide special protection.
29
+
30
+ **Output gates** hold outgoing network messages until pending storage writes complete—clients never see confirmation of unpersisted data.
31
+
32
+ ### Write Coalescing
33
+
34
+ Multiple storage writes without intervening `await` are automatically batched into a single atomic transaction:
35
+
36
+ ```typescript
37
+ async transfer(fromId: string, toId: string, amount: number) {
38
+ // All three writes commit together atomically
39
+ this.ctx.storage.sql.exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromId);
40
+ this.ctx.storage.sql.exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, toId);
41
+ this.ctx.storage.sql.exec("INSERT INTO transfers (from_id, to_id, amount) VALUES (?, ?, ?)", fromId, toId, amount);
42
+ }
43
+ ```
44
+
45
+ ### blockConcurrencyWhile()
46
+
47
+ Guarantees no other events process until callback completes. **Use sparingly**—only for initialization/migrations.
48
+
49
+ ```typescript
50
+ constructor(ctx: DurableObjectState, env: Env) {
51
+ super(ctx, env);
52
+ ctx.blockConcurrencyWhile(async () => {
53
+ const version = this.ctx.storage.sql.exec<{ version: number }>("PRAGMA user_version").one()?.version ?? 0;
54
+ if (version < 1) {
55
+ this.ctx.storage.sql.exec(`CREATE TABLE IF NOT EXISTS data (...); PRAGMA user_version = 1;`);
56
+ }
57
+ });
58
+ }
59
+ ```
60
+
61
+ **Anti-pattern**: Using `blockConcurrencyWhile()` on every request or across I/O (fetch, KV, R2) severely degrades throughput. For regular requests, rely on input/output gates and write coalescing.
62
+
63
+ ### Optimistic Locking (Non-Storage I/O)
64
+
65
+ Input gates only protect during storage ops. External I/O like `fetch()` allows interleaving. Use check-and-set:
66
+
67
+ ```typescript
68
+ async updateFromExternal(key: string) {
69
+ const version = this.ctx.storage.sql.exec<{ v: number }>("SELECT version as v FROM data WHERE key = ?", key).one()?.v;
70
+ const externalData = await fetch("https://api.example.com/data"); // Other requests can interleave here
71
+ const newVersion = this.ctx.storage.sql.exec<{ v: number }>("SELECT version as v FROM data WHERE key = ?", key).one()?.v;
72
+
73
+ if (version !== newVersion) throw new Error("Concurrent modification");
74
+ this.ctx.storage.sql.exec("UPDATE data SET value = ?, version = version + 1 WHERE key = ?", await externalData.text(), key);
75
+ }
76
+ ```
77
+
78
+ ## SQLite Storage
79
+
80
+ ```typescript
81
+ // Query
82
+ const cursor = this.ctx.storage.sql.exec("SELECT * FROM users WHERE age > ?", 18);
83
+ cursor.toArray() // All rows
84
+ cursor.one() // 1 row or throw
85
+ cursor.raw().toArray() // [[1, 'Alice']]
86
+ cursor.rowsRead, cursor.rowsWritten, cursor.columnNames
87
+ this.ctx.storage.sql.databaseSize
88
+
89
+ // Schema
90
+ this.ctx.storage.sql.exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)");
91
+ ```
92
+
93
+ ## KV Storage
94
+
95
+ ```typescript
96
+ // Sync (SQLite only)
97
+ this.ctx.storage.kv.get/put/delete("key", value)
98
+ this.ctx.storage.kv.list({ prefix: "user:" })
99
+
100
+ // Async
101
+ await this.ctx.storage.get/put/delete("key", value)
102
+ await this.ctx.storage.put({ k1: "a", k2: "b" }) // Batch 128 max
103
+ await this.ctx.storage.list({ prefix: "user:", start: "user:100", limit: 50 })
104
+ await this.ctx.storage.deleteAll()
105
+ ```
106
+
107
+ ## Transactions
108
+
109
+ ```typescript
110
+ // Sync
111
+ this.ctx.storage.transactionSync(() => { /* SQL ops */ });
112
+
113
+ // Async
114
+ await this.ctx.storage.transaction(async (txn) => {
115
+ await txn.get/put/delete("key", value); // Throw to rollback
116
+ });
117
+ ```
118
+
119
+ ## Point-in-Time Recovery
120
+
121
+ ```typescript
122
+ await this.ctx.storage.getCurrentBookmark()
123
+ await this.ctx.storage.getBookmarkForTime(Date.now() - 86400000)
124
+ await this.ctx.storage.onNextSessionRestoreBookmark(bookmark) // Call ctx.abort() after
125
+ ```
126
+
127
+ ## Alarms
128
+
129
+ ```typescript
130
+ await this.ctx.storage.setAlarm(Date.now() + 3600000)
131
+ await this.ctx.storage.getAlarm()
132
+ await this.ctx.storage.deleteAlarm()
133
+ async alarm() { /* runs when fires */ }
134
+ ```
135
+
136
+ ## WebSockets
137
+
138
+ ```typescript
139
+ async fetch(req: Request): Promise<Response> {
140
+ const [client, server] = Object.values(new WebSocketPair());
141
+ this.ctx.acceptWebSocket(server, ["room:123"]);
142
+ server.serializeAttachment({ userId: "abc" });
143
+ return new Response(null, { status: 101, webSocket: client });
144
+ }
145
+
146
+ async webSocketMessage(ws: WebSocket, msg: string | ArrayBuffer) {
147
+ const data = ws.deserializeAttachment();
148
+ for (const c of this.ctx.getWebSockets()) c.send(msg);
149
+ }
150
+
151
+ // Management: getWebSockets(), getTags(ws), ws.send/close()
152
+ ```
@@ -0,0 +1,148 @@
1
+ # Durable Objects Configuration
2
+
3
+ ## Basic Setup
4
+
5
+ ```jsonc
6
+ {
7
+ "name": "my-worker",
8
+ "main": "src/index.ts",
9
+ "compatibility_date": "2024-04-03",
10
+ "durable_objects": {
11
+ "bindings": [
12
+ { "name": "MY_DO", "class_name": "MyDO" },
13
+ { "name": "EXTERNAL", "class_name": "ExternalDO", "script_name": "other-worker" }
14
+ ]
15
+ },
16
+ "migrations": [
17
+ { "tag": "v1", "new_sqlite_classes": ["MyDO"] }
18
+ ]
19
+ }
20
+ ```
21
+
22
+ ## Migrations
23
+
24
+ ```jsonc
25
+ {
26
+ "migrations": [
27
+ // Create new SQLite-backed class (recommended for new classes)
28
+ { "tag": "v1", "new_sqlite_classes": ["MyDO"] },
29
+
30
+ // Create new KV-backed class (legacy, paid only)
31
+ // { "tag": "v1", "new_classes": ["MyDO"] },
32
+
33
+ // Rename class - preserves all data and object IDs
34
+ { "tag": "v2", "renamed_classes": [{ "from": "OldName", "to": "NewName" }] },
35
+
36
+ // Transfer between scripts - requires coordination
37
+ { "tag": "v3", "transferred_classes": [{ "from": "Src", "from_script": "old-worker", "to": "Dest" }] },
38
+
39
+ // DELETE - DESTROYS ALL DATA PERMANENTLY, NO RECOVERY
40
+ { "tag": "v4", "deleted_classes": ["Obsolete"] }
41
+ ]
42
+ }
43
+ ```
44
+
45
+ **Migration rules:**
46
+ - Tags must be unique and sequential
47
+ - No rollback mechanism—test with `--dry-run` first
48
+ - Auto-applied on deploy
49
+ - `renamed_classes` preserves data and IDs
50
+ - `deleted_classes` is irreversible—all storage gone
51
+ - Transfers between scripts require both scripts deployed with coordinated migrations
52
+
53
+ ## Advanced
54
+
55
+ ```jsonc
56
+ {
57
+ "limits": { "cpu_ms": 300000 }, // Default 30s, max 300s
58
+ "env": {
59
+ "production": {
60
+ "durable_objects": {
61
+ "bindings": [{ "name": "MY_DO", "class_name": "MyDO", "environment": "production" }]
62
+ }
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ## Types
69
+
70
+ ```typescript
71
+ import { DurableObject } from "cloudflare:workers";
72
+
73
+ interface Env {
74
+ MY_DO: DurableObjectNamespace<MyDO>;
75
+ }
76
+
77
+ export class MyDO extends DurableObject<Env> {}
78
+
79
+ type DurableObjectNamespace<T> = {
80
+ newUniqueId(options?: { jurisdiction?: string }): DurableObjectId;
81
+ idFromName(name: string): DurableObjectId;
82
+ idFromString(id: string): DurableObjectId;
83
+ get(id: DurableObjectId): DurableObjectStub<T>;
84
+ };
85
+ ```
86
+
87
+ ## Testing with Vitest
88
+
89
+ ```typescript
90
+ // vitest.config.ts
91
+ import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
92
+
93
+ export default defineWorkersConfig({
94
+ test: {
95
+ poolOptions: {
96
+ workers: { wrangler: { configPath: "./wrangler.toml" } },
97
+ },
98
+ },
99
+ });
100
+ ```
101
+
102
+ ```typescript
103
+ // test/my-do.test.ts
104
+ import { env, runInDurableObject, runDurableObjectAlarm } from "cloudflare:test";
105
+ import { describe, it, expect } from "vitest";
106
+
107
+ describe("MyDO", () => {
108
+ it("handles RPC methods", async () => {
109
+ const id = env.MY_DO.idFromName("test");
110
+ const stub = env.MY_DO.get(id);
111
+
112
+ const result = await stub.myMethod("test-arg");
113
+ expect(result).toBe("test-arg");
114
+ });
115
+
116
+ it("can access storage directly", async () => {
117
+ const id = env.MY_DO.idFromName("test");
118
+ const stub = env.MY_DO.get(id);
119
+
120
+ await runInDurableObject(stub, async (instance, state) => {
121
+ const count = state.storage.sql
122
+ .exec<{ count: number }>("SELECT COUNT(*) as count FROM data")
123
+ .one();
124
+ expect(count.count).toBe(0);
125
+ });
126
+ });
127
+
128
+ it("can trigger alarms", async () => {
129
+ const id = env.MY_DO.idFromName("test");
130
+ const stub = env.MY_DO.get(id);
131
+
132
+ const alarmRan = await runDurableObjectAlarm(stub);
133
+ expect(alarmRan).toBe(false); // No alarm scheduled
134
+ });
135
+ });
136
+ ```
137
+
138
+ ## Commands
139
+
140
+ ```bash
141
+ npx wrangler dev # Local dev
142
+ npx wrangler dev --remote # Test prod DOs
143
+ npx wrangler deploy # Deploy + migrations
144
+ npx wrangler deploy --dry-run # Validate only
145
+ npx wrangler durable-objects list # List namespaces
146
+ npx wrangler durable-objects info <namespace> <id> # Object info
147
+ npx wrangler durable-objects delete <namespace> <id> # Delete object
148
+ ```
@@ -0,0 +1,158 @@
1
+ # Durable Objects Gotchas
2
+
3
+ ## Limits
4
+
5
+ | Resource | Free | Paid |
6
+ |----------|------|------|
7
+ | Storage per DO | 10GB (SQLite) | 10GB (SQLite) |
8
+ | Total storage | 5GB | Unlimited |
9
+ | DO classes | 100 | 500 |
10
+ | Requests/sec/DO | ~1000 | ~1000 |
11
+ | CPU time | 30s default, 300s max | 30s default, 300s max |
12
+ | WebSocket message | 32MiB | 32MiB |
13
+ | SQL columns | 100 | 100 |
14
+ | SQL statement | 100KB | 100KB |
15
+ | Key+value size | 2MB | 2MB |
16
+
17
+ ## Billing Gotchas
18
+
19
+ ### Duration Billing Trap
20
+ DOs bill for **wall-clock time** while active, not CPU time. WebSocket open 8 hours = 8 hours duration billing, even if DO processed 50 small messages.
21
+
22
+ **Fix**: Use Hibernatable WebSockets API. DO sleeps while maintaining connections, only wakes (and bills) when messages arrive.
23
+
24
+ ### storage.list() on Every Request
25
+ Storage reads are cheap but not free. Calling `storage.list()` or multiple `storage.get()` on every request adds up.
26
+
27
+ **Fix**: Profile actual usage. Options:
28
+ - `storage.get(['key1', 'key2', 'key3'])` - cheapest if only need specific keys
29
+ - `storage.list()` once on wake, cache in memory - cheapest if serving many requests per wake cycle
30
+ - Single `storage.get('allData')` with combined object - cheapest if often need multiple keys together
31
+
32
+ ### Alarm Recursion
33
+ Scheduling `setAlarm()` every 5 minutes = 288 wake-ups/day × minimum billable duration. Across thousands of DOs, you're waking them all whether work exists or not.
34
+
35
+ **Fix**: Only schedule alarms when actual work is pending. Check if alarm is needed before setting.
36
+
37
+ ### WebSocket Never Closes
38
+ If users close browser tabs without proper disconnect and you don't handle it, connection stays "open" from DO's perspective, preventing hibernation.
39
+
40
+ **Fix**:
41
+ 1. Handle `webSocketClose` and `webSocketError` events
42
+ 2. Implement heartbeat/ping-pong to detect dead connections
43
+ 3. Use Hibernatable WebSockets API properly
44
+
45
+ ### Singleton vs Sharding
46
+ Global singleton DO handling all traffic = bottleneck + continuous duration billing (never hibernates).
47
+
48
+ | Design | Cost Pattern |
49
+ |--------|--------------|
50
+ | One global DO | Never hibernates, continuous billing |
51
+ | Per-user DO | Each only wakes for their requests, most hibernate |
52
+ | Per-user-per-hour | Many cold starts, many minimum durations |
53
+
54
+ **Fix**: Use per-entity DOs (per-user, per-room, per-document). They hibernate between activity.
55
+
56
+ ### Batching Reads
57
+ Five separate `storage.get()` calls > one `storage.get(['k1','k2','k3','k4','k5'])`. Each operation has overhead.
58
+
59
+ **Fix**: Batch reads/writes. Writes without intervening `await` are automatically coalesced into single atomic transaction.
60
+
61
+ ### Hibernation State Loss
62
+ In-memory state is **lost** when DO hibernates or evicts. Waking DO reconstructs from storage.
63
+
64
+ **Fix**:
65
+ 1. Store all important state in SQLite storage
66
+ 2. Use `blockConcurrencyWhile()` in constructor to load state on wake
67
+ 3. Cache in memory for current wake cycle only
68
+ 4. Accept every wake is potentially "cold"
69
+
70
+ ### Fan-Out Tax
71
+ Event notifying 1,000 DOs = 1,000 DO invocations billed immediately. Queue pattern doesn't reduce invocations but provides retries and batching.
72
+
73
+ **Fix**: For time-sensitive, accept cost. For deferrable, use Queues for retry/dead-letter handling.
74
+
75
+ ### Idempotency Key Explosion
76
+ Creating one DO per idempotency key (used once) = millions of single-use DOs that persist until deleted.
77
+
78
+ **Fix**:
79
+ 1. Hash idempotency keys into N sharded buckets
80
+ 2. Store records as rows in single DO's SQLite table
81
+ 3. Implement TTL cleanup via alarms
82
+ 4. Consider if KV is sufficient (if strong consistency not needed)
83
+
84
+ ### Storage Compaction
85
+ Individual writes billed per-operation. Writing 100 events individually = 100× the write operations vs batching.
86
+
87
+ **Fix**: Batch writes. Multiple `INSERT` statements without intervening `await` coalesce into single transaction.
88
+
89
+ ### waitUntil() Behavior
90
+ `ctx.waitUntil()` keeps DO alive (billed) until promises resolve. Waiting for slow external calls = paying for wait time.
91
+
92
+ **Fix**: For true background work, use alarms or Queues instead of `waitUntil()`.
93
+
94
+ ### KV vs DO Storage
95
+ For read-heavy, write-rare, eventually-consistent-OK data: **KV is cheaper**.
96
+
97
+ | | KV | DO Storage |
98
+ |-|----|----|
99
+ | Reads | Global edge cache, cheap | Every read hits DO compute |
100
+ | Writes | ~60s propagation | Immediate consistency |
101
+ | Use case | Config, sessions, cache | Read-modify-write, coordination |
102
+
103
+ ## Common Issues
104
+
105
+ | Issue | Cause | Fix |
106
+ |-------|-------|-----|
107
+ | DO overloaded (503) | Single DO bottleneck | Shard across DOs with random/deterministic IDs |
108
+ | Storage quota exceeded | Write failures | Upgrade plan or cleanup via alarms |
109
+ | CPU exceeded | Terminated mid-request | Increase `limits.cpu_ms` or chunk work |
110
+ | WebSockets disconnect | Eviction | Use hibernation + reconnection logic |
111
+ | Migration failed | Deploy error | Check tag uniqueness, class names, use `--dry-run` |
112
+ | RPC not found | Old compatibility_date | Update to >= 2024-04-03 or use fetch |
113
+ | One alarm limit | Need multiple timers | Use event queue pattern (store events, single alarm) |
114
+ | Constructor expensive | Slow cold starts | Lazy load in methods, cache after first load |
115
+
116
+ ## RPC vs Fetch
117
+
118
+ | | RPC | Fetch |
119
+ |-|-----|-------|
120
+ | Type safety | Full TypeScript support | Manual parsing |
121
+ | Simplicity | Direct method calls | HTTP request/response |
122
+ | Performance | Slightly faster | HTTP overhead |
123
+ | Requirement | compatibility_date >= 2024-04-03 | Always works |
124
+ | Use case | **Default choice** | Legacy, proxying |
125
+
126
+ ```typescript
127
+ // RPC (recommended)
128
+ const result = await stub.myMethod(arg);
129
+
130
+ // Fetch (legacy)
131
+ const response = await stub.fetch(new Request("http://do/endpoint"));
132
+ ```
133
+
134
+ ## Migration Gotchas
135
+
136
+ - Tags must be unique and sequential
137
+ - No rollback mechanism
138
+ - `deleted_classes` **destroys ALL data** permanently
139
+ - Test with `--dry-run` before production deploy
140
+ - Transfers between scripts need coordination
141
+ - Renames preserve data and IDs
142
+
143
+ ## Debugging
144
+
145
+ ```bash
146
+ npx wrangler dev # Local development
147
+ npx wrangler dev --remote # Test against production DOs
148
+ npx wrangler tail # Stream logs
149
+ npx wrangler durable-objects list
150
+ npx wrangler durable-objects info <namespace> <id>
151
+ ```
152
+
153
+ ```typescript
154
+ // Storage diagnostics
155
+ this.ctx.storage.sql.databaseSize // Current storage usage
156
+ cursor.rowsRead // Rows scanned
157
+ cursor.rowsWritten // Rows modified
158
+ ```