denchclaw 2.3.6 → 2.3.7

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 (400) hide show
  1. package/apps/web/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  2. package/apps/web/.next/standalone/apps/web/.next/app-build-manifest.json +140 -105
  3. package/apps/web/.next/standalone/apps/web/.next/app-path-routes-manifest.json +34 -29
  4. package/apps/web/.next/standalone/apps/web/.next/build-manifest.json +2 -2
  5. package/apps/web/.next/standalone/apps/web/.next/required-server-files.json +1 -1
  6. package/apps/web/.next/standalone/apps/web/.next/routes-manifest.json +8 -0
  7. package/apps/web/.next/standalone/apps/web/.next/server/app/_not-found/page.js +1 -1
  8. package/apps/web/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/cron/route.js +1 -0
  10. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/cron/route.js.nft.json +1 -0
  11. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/cron/route_client-reference-manifest.js +1 -0
  12. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/proxy/route.js +1 -0
  13. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/proxy/route.js.nft.json +1 -0
  14. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/proxy/route_client-reference-manifest.js +1 -0
  15. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/route.js +197 -9
  16. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/route_client-reference-manifest.js +1 -1
  17. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/serve/[...path]/route.js +197 -9
  18. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/serve/[...path]/route_client-reference-manifest.js +1 -1
  19. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/store/route.js +1 -0
  20. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/store/route.js.nft.json +1 -0
  21. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/store/route_client-reference-manifest.js +1 -0
  22. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/webhooks/[...path]/route.js +1 -0
  23. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/webhooks/[...path]/route.js.nft.json +1 -0
  24. package/apps/web/.next/standalone/apps/web/.next/server/app/api/apps/webhooks/[...path]/route_client-reference-manifest.js +1 -0
  25. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/active/route.js +1 -1
  26. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/active/route.js.nft.json +1 -1
  27. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/active/route_client-reference-manifest.js +1 -1
  28. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route.js +1 -1
  29. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route.js.nft.json +1 -1
  30. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/route_client-reference-manifest.js +1 -1
  31. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/runs/route.js +1 -1
  32. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/runs/route.js.nft.json +1 -1
  33. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/runs/route_client-reference-manifest.js +1 -1
  34. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route.js +1 -1
  35. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route.js.nft.json +1 -1
  36. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stop/route_client-reference-manifest.js +1 -1
  37. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stream/route.js +1 -1
  38. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stream/route.js.nft.json +1 -1
  39. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/stream/route_client-reference-manifest.js +1 -1
  40. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/subagents/route.js +1 -1
  41. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/subagents/route.js.nft.json +1 -1
  42. package/apps/web/.next/standalone/apps/web/.next/server/app/api/chat/subagents/route_client-reference-manifest.js +1 -1
  43. package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/jobs/[jobId]/runs/route_client-reference-manifest.js +1 -1
  44. package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/jobs/route_client-reference-manifest.js +1 -1
  45. package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/runs/[sessionId]/route_client-reference-manifest.js +1 -1
  46. package/apps/web/.next/standalone/apps/web/.next/server/app/api/cron/runs/search-transcript/route_client-reference-manifest.js +1 -1
  47. package/apps/web/.next/standalone/apps/web/.next/server/app/api/feedback/route.js +1 -1
  48. package/apps/web/.next/standalone/apps/web/.next/server/app/api/feedback/route_client-reference-manifest.js +1 -1
  49. package/apps/web/.next/standalone/apps/web/.next/server/app/api/memories/route_client-reference-manifest.js +1 -1
  50. package/apps/web/.next/standalone/apps/web/.next/server/app/api/profiles/route_client-reference-manifest.js +1 -1
  51. package/apps/web/.next/standalone/apps/web/.next/server/app/api/profiles/switch/route_client-reference-manifest.js +1 -1
  52. package/apps/web/.next/standalone/apps/web/.next/server/app/api/sessions/[sessionId]/route_client-reference-manifest.js +1 -1
  53. package/apps/web/.next/standalone/apps/web/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
  54. package/apps/web/.next/standalone/apps/web/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  55. package/apps/web/.next/standalone/apps/web/.next/server/app/api/terminal/port/route_client-reference-manifest.js +1 -1
  56. package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/messages/route_client-reference-manifest.js +1 -1
  57. package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/route.js +1 -1
  58. package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/route.js.nft.json +1 -1
  59. package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/[id]/route_client-reference-manifest.js +1 -1
  60. package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/route.js +1 -1
  61. package/apps/web/.next/standalone/apps/web/.next/server/app/api/web-sessions/route_client-reference-manifest.js +1 -1
  62. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/assets/[...path]/route_client-reference-manifest.js +1 -1
  63. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/browse/route_client-reference-manifest.js +1 -1
  64. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/browse-file/route_client-reference-manifest.js +1 -1
  65. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/context/route_client-reference-manifest.js +1 -1
  66. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/copy/route_client-reference-manifest.js +1 -1
  67. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/db/introspect/route_client-reference-manifest.js +1 -1
  68. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/db/query/route_client-reference-manifest.js +1 -1
  69. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/delete/route.js +1 -1
  70. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/delete/route_client-reference-manifest.js +1 -1
  71. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/execute/route.js +1 -0
  72. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/execute/route.js.nft.json +1 -0
  73. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/execute/route_client-reference-manifest.js +1 -0
  74. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/file/route_client-reference-manifest.js +1 -1
  75. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/init/route.js +1 -1
  76. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/init/route_client-reference-manifest.js +1 -1
  77. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/list/route_client-reference-manifest.js +1 -1
  78. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/mkdir/route_client-reference-manifest.js +1 -1
  79. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/move/route_client-reference-manifest.js +1 -1
  80. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/display-field/route_client-reference-manifest.js +1 -1
  81. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/[id]/route_client-reference-manifest.js +1 -1
  82. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/bulk-delete/route_client-reference-manifest.js +1 -1
  83. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/options/route_client-reference-manifest.js +1 -1
  84. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/route.js +1 -1
  85. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/entries/route_client-reference-manifest.js +1 -1
  86. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route_client-reference-manifest.js +1 -1
  87. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/[fieldId]/route_client-reference-manifest.js +1 -1
  88. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/fields/reorder/route_client-reference-manifest.js +1 -1
  89. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/route_client-reference-manifest.js +1 -1
  90. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/objects/[name]/views/route_client-reference-manifest.js +1 -1
  91. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/open-file/route_client-reference-manifest.js +1 -1
  92. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/path-info/route_client-reference-manifest.js +1 -1
  93. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/query/route_client-reference-manifest.js +1 -1
  94. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/raw-file/route_client-reference-manifest.js +1 -1
  95. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/rename/route_client-reference-manifest.js +1 -1
  96. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/reports/execute/route.js +1 -1
  97. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/reports/execute/route_client-reference-manifest.js +1 -1
  98. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/search-index/route_client-reference-manifest.js +1 -1
  99. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/suggest-files/route_client-reference-manifest.js +1 -1
  100. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/switch/route.js +1 -1
  101. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/switch/route_client-reference-manifest.js +1 -1
  102. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/thumbnail/route_client-reference-manifest.js +1 -1
  103. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/tree/route.js +1 -1
  104. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/tree/route_client-reference-manifest.js +1 -1
  105. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/upload/route.js +1 -1
  106. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/upload/route_client-reference-manifest.js +1 -1
  107. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/virtual-file/route_client-reference-manifest.js +1 -1
  108. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/watch/route_client-reference-manifest.js +1 -1
  109. package/apps/web/.next/standalone/apps/web/.next/server/app/api/workspace/write-binary/route_client-reference-manifest.js +1 -1
  110. package/apps/web/.next/standalone/apps/web/.next/server/app/page.js +5 -5
  111. package/apps/web/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  112. package/apps/web/.next/standalone/apps/web/.next/server/app/workspace/page_client-reference-manifest.js +1 -1
  113. package/apps/web/.next/standalone/apps/web/.next/server/app-paths-manifest.json +34 -29
  114. package/apps/web/.next/standalone/apps/web/.next/server/chunks/6426.js +1 -7
  115. package/apps/web/.next/standalone/apps/web/.next/server/chunks/687.js +7 -0
  116. package/apps/web/.next/standalone/apps/web/.next/server/chunks/7173.js +1 -1
  117. package/apps/web/.next/standalone/apps/web/.next/server/functions-config-manifest.json +26 -21
  118. package/apps/web/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  119. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/cron/route-5f5d429b1700dd0e.js +1 -0
  120. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/proxy/route-5f5d429b1700dd0e.js +1 -0
  121. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/route-5f5d429b1700dd0e.js +1 -0
  122. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/serve/[...path]/route-5f5d429b1700dd0e.js +1 -0
  123. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/store/route-5f5d429b1700dd0e.js +1 -0
  124. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/webhooks/[...path]/route-5f5d429b1700dd0e.js +1 -0
  125. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/active/route-5f5d429b1700dd0e.js +1 -0
  126. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/route-5f5d429b1700dd0e.js +1 -0
  127. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/runs/route-5f5d429b1700dd0e.js +1 -0
  128. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/stop/route-5f5d429b1700dd0e.js +1 -0
  129. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/stream/route-5f5d429b1700dd0e.js +1 -0
  130. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/subagents/route-5f5d429b1700dd0e.js +1 -0
  131. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/jobs/[jobId]/runs/route-5f5d429b1700dd0e.js +1 -0
  132. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/jobs/route-5f5d429b1700dd0e.js +1 -0
  133. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/runs/[sessionId]/route-5f5d429b1700dd0e.js +1 -0
  134. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/runs/search-transcript/route-5f5d429b1700dd0e.js +1 -0
  135. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/feedback/route-5f5d429b1700dd0e.js +1 -0
  136. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/memories/route-5f5d429b1700dd0e.js +1 -0
  137. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/profiles/route-5f5d429b1700dd0e.js +1 -0
  138. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/profiles/switch/route-5f5d429b1700dd0e.js +1 -0
  139. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/sessions/[sessionId]/route-5f5d429b1700dd0e.js +1 -0
  140. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/sessions/route-5f5d429b1700dd0e.js +1 -0
  141. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/skills/route-5f5d429b1700dd0e.js +1 -0
  142. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/terminal/port/route-5f5d429b1700dd0e.js +1 -0
  143. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/web-sessions/[id]/messages/route-5f5d429b1700dd0e.js +1 -0
  144. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/web-sessions/[id]/route-5f5d429b1700dd0e.js +1 -0
  145. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/web-sessions/route-5f5d429b1700dd0e.js +1 -0
  146. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/assets/[...path]/route-5f5d429b1700dd0e.js +1 -0
  147. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/browse/route-5f5d429b1700dd0e.js +1 -0
  148. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/browse-file/route-5f5d429b1700dd0e.js +1 -0
  149. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/context/route-5f5d429b1700dd0e.js +1 -0
  150. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/copy/route-5f5d429b1700dd0e.js +1 -0
  151. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/db/introspect/route-5f5d429b1700dd0e.js +1 -0
  152. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/db/query/route-5f5d429b1700dd0e.js +1 -0
  153. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/delete/route-5f5d429b1700dd0e.js +1 -0
  154. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/execute/route-5f5d429b1700dd0e.js +1 -0
  155. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/file/route-5f5d429b1700dd0e.js +1 -0
  156. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/init/route-5f5d429b1700dd0e.js +1 -0
  157. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/list/route-5f5d429b1700dd0e.js +1 -0
  158. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/mkdir/route-5f5d429b1700dd0e.js +1 -0
  159. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/move/route-5f5d429b1700dd0e.js +1 -0
  160. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/display-field/route-5f5d429b1700dd0e.js +1 -0
  161. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/[id]/route-5f5d429b1700dd0e.js +1 -0
  162. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/bulk-delete/route-5f5d429b1700dd0e.js +1 -0
  163. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/options/route-5f5d429b1700dd0e.js +1 -0
  164. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/route-5f5d429b1700dd0e.js +1 -0
  165. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route-5f5d429b1700dd0e.js +1 -0
  166. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/route-5f5d429b1700dd0e.js +1 -0
  167. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/reorder/route-5f5d429b1700dd0e.js +1 -0
  168. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/route-5f5d429b1700dd0e.js +1 -0
  169. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/views/route-5f5d429b1700dd0e.js +1 -0
  170. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/open-file/route-5f5d429b1700dd0e.js +1 -0
  171. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/path-info/route-5f5d429b1700dd0e.js +1 -0
  172. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/query/route-5f5d429b1700dd0e.js +1 -0
  173. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/raw-file/route-5f5d429b1700dd0e.js +1 -0
  174. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/rename/route-5f5d429b1700dd0e.js +1 -0
  175. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/reports/execute/route-5f5d429b1700dd0e.js +1 -0
  176. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/search-index/route-5f5d429b1700dd0e.js +1 -0
  177. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/suggest-files/route-5f5d429b1700dd0e.js +1 -0
  178. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/switch/route-5f5d429b1700dd0e.js +1 -0
  179. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/thumbnail/route-5f5d429b1700dd0e.js +1 -0
  180. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/tree/route-5f5d429b1700dd0e.js +1 -0
  181. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/upload/route-5f5d429b1700dd0e.js +1 -0
  182. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/virtual-file/route-5f5d429b1700dd0e.js +1 -0
  183. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/watch/route-5f5d429b1700dd0e.js +1 -0
  184. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/write-binary/route-5f5d429b1700dd0e.js +1 -0
  185. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/{layout-27bf5ccd9324b2af.js → layout-a0f54c498e78b06e.js} +1 -1
  186. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/page-441fc26d2fd5ddf4.js +1 -0
  187. package/apps/web/.next/standalone/apps/web/.next/static/css/eb7b54c9778eb5c7.css +1 -0
  188. package/apps/web/.next/standalone/apps/web/.next/static/mOcRFLcuuyC7J3QuiCUwf/_buildManifest.js +1 -0
  189. package/apps/web/.next/standalone/apps/web/server.js +1 -1
  190. package/apps/web/.next/standalone/package.json +1 -1
  191. package/apps/web/.next/static/chunks/app/api/apps/cron/route-5f5d429b1700dd0e.js +1 -0
  192. package/apps/web/.next/static/chunks/app/api/apps/proxy/route-5f5d429b1700dd0e.js +1 -0
  193. package/apps/web/.next/static/chunks/app/api/apps/route-5f5d429b1700dd0e.js +1 -0
  194. package/apps/web/.next/static/chunks/app/api/apps/serve/[...path]/route-5f5d429b1700dd0e.js +1 -0
  195. package/apps/web/.next/static/chunks/app/api/apps/store/route-5f5d429b1700dd0e.js +1 -0
  196. package/apps/web/.next/static/chunks/app/api/apps/webhooks/[...path]/route-5f5d429b1700dd0e.js +1 -0
  197. package/apps/web/.next/static/chunks/app/api/chat/active/route-5f5d429b1700dd0e.js +1 -0
  198. package/apps/web/.next/static/chunks/app/api/chat/route-5f5d429b1700dd0e.js +1 -0
  199. package/apps/web/.next/static/chunks/app/api/chat/runs/route-5f5d429b1700dd0e.js +1 -0
  200. package/apps/web/.next/static/chunks/app/api/chat/stop/route-5f5d429b1700dd0e.js +1 -0
  201. package/apps/web/.next/static/chunks/app/api/chat/stream/route-5f5d429b1700dd0e.js +1 -0
  202. package/apps/web/.next/static/chunks/app/api/chat/subagents/route-5f5d429b1700dd0e.js +1 -0
  203. package/apps/web/.next/static/chunks/app/api/cron/jobs/[jobId]/runs/route-5f5d429b1700dd0e.js +1 -0
  204. package/apps/web/.next/static/chunks/app/api/cron/jobs/route-5f5d429b1700dd0e.js +1 -0
  205. package/apps/web/.next/static/chunks/app/api/cron/runs/[sessionId]/route-5f5d429b1700dd0e.js +1 -0
  206. package/apps/web/.next/static/chunks/app/api/cron/runs/search-transcript/route-5f5d429b1700dd0e.js +1 -0
  207. package/apps/web/.next/static/chunks/app/api/feedback/route-5f5d429b1700dd0e.js +1 -0
  208. package/apps/web/.next/static/chunks/app/api/memories/route-5f5d429b1700dd0e.js +1 -0
  209. package/apps/web/.next/static/chunks/app/api/profiles/route-5f5d429b1700dd0e.js +1 -0
  210. package/apps/web/.next/static/chunks/app/api/profiles/switch/route-5f5d429b1700dd0e.js +1 -0
  211. package/apps/web/.next/static/chunks/app/api/sessions/[sessionId]/route-5f5d429b1700dd0e.js +1 -0
  212. package/apps/web/.next/static/chunks/app/api/sessions/route-5f5d429b1700dd0e.js +1 -0
  213. package/apps/web/.next/static/chunks/app/api/skills/route-5f5d429b1700dd0e.js +1 -0
  214. package/apps/web/.next/static/chunks/app/api/terminal/port/route-5f5d429b1700dd0e.js +1 -0
  215. package/apps/web/.next/static/chunks/app/api/web-sessions/[id]/messages/route-5f5d429b1700dd0e.js +1 -0
  216. package/apps/web/.next/static/chunks/app/api/web-sessions/[id]/route-5f5d429b1700dd0e.js +1 -0
  217. package/apps/web/.next/static/chunks/app/api/web-sessions/route-5f5d429b1700dd0e.js +1 -0
  218. package/apps/web/.next/static/chunks/app/api/workspace/assets/[...path]/route-5f5d429b1700dd0e.js +1 -0
  219. package/apps/web/.next/static/chunks/app/api/workspace/browse/route-5f5d429b1700dd0e.js +1 -0
  220. package/apps/web/.next/static/chunks/app/api/workspace/browse-file/route-5f5d429b1700dd0e.js +1 -0
  221. package/apps/web/.next/static/chunks/app/api/workspace/context/route-5f5d429b1700dd0e.js +1 -0
  222. package/apps/web/.next/static/chunks/app/api/workspace/copy/route-5f5d429b1700dd0e.js +1 -0
  223. package/apps/web/.next/static/chunks/app/api/workspace/db/introspect/route-5f5d429b1700dd0e.js +1 -0
  224. package/apps/web/.next/static/chunks/app/api/workspace/db/query/route-5f5d429b1700dd0e.js +1 -0
  225. package/apps/web/.next/static/chunks/app/api/workspace/delete/route-5f5d429b1700dd0e.js +1 -0
  226. package/apps/web/.next/static/chunks/app/api/workspace/execute/route-5f5d429b1700dd0e.js +1 -0
  227. package/apps/web/.next/static/chunks/app/api/workspace/file/route-5f5d429b1700dd0e.js +1 -0
  228. package/apps/web/.next/static/chunks/app/api/workspace/init/route-5f5d429b1700dd0e.js +1 -0
  229. package/apps/web/.next/static/chunks/app/api/workspace/list/route-5f5d429b1700dd0e.js +1 -0
  230. package/apps/web/.next/static/chunks/app/api/workspace/mkdir/route-5f5d429b1700dd0e.js +1 -0
  231. package/apps/web/.next/static/chunks/app/api/workspace/move/route-5f5d429b1700dd0e.js +1 -0
  232. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/display-field/route-5f5d429b1700dd0e.js +1 -0
  233. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/[id]/route-5f5d429b1700dd0e.js +1 -0
  234. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/bulk-delete/route-5f5d429b1700dd0e.js +1 -0
  235. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/options/route-5f5d429b1700dd0e.js +1 -0
  236. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/route-5f5d429b1700dd0e.js +1 -0
  237. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route-5f5d429b1700dd0e.js +1 -0
  238. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/route-5f5d429b1700dd0e.js +1 -0
  239. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/reorder/route-5f5d429b1700dd0e.js +1 -0
  240. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/route-5f5d429b1700dd0e.js +1 -0
  241. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/views/route-5f5d429b1700dd0e.js +1 -0
  242. package/apps/web/.next/static/chunks/app/api/workspace/open-file/route-5f5d429b1700dd0e.js +1 -0
  243. package/apps/web/.next/static/chunks/app/api/workspace/path-info/route-5f5d429b1700dd0e.js +1 -0
  244. package/apps/web/.next/static/chunks/app/api/workspace/query/route-5f5d429b1700dd0e.js +1 -0
  245. package/apps/web/.next/static/chunks/app/api/workspace/raw-file/route-5f5d429b1700dd0e.js +1 -0
  246. package/apps/web/.next/static/chunks/app/api/workspace/rename/route-5f5d429b1700dd0e.js +1 -0
  247. package/apps/web/.next/static/chunks/app/api/workspace/reports/execute/route-5f5d429b1700dd0e.js +1 -0
  248. package/apps/web/.next/static/chunks/app/api/workspace/search-index/route-5f5d429b1700dd0e.js +1 -0
  249. package/apps/web/.next/static/chunks/app/api/workspace/suggest-files/route-5f5d429b1700dd0e.js +1 -0
  250. package/apps/web/.next/static/chunks/app/api/workspace/switch/route-5f5d429b1700dd0e.js +1 -0
  251. package/apps/web/.next/static/chunks/app/api/workspace/thumbnail/route-5f5d429b1700dd0e.js +1 -0
  252. package/apps/web/.next/static/chunks/app/api/workspace/tree/route-5f5d429b1700dd0e.js +1 -0
  253. package/apps/web/.next/static/chunks/app/api/workspace/upload/route-5f5d429b1700dd0e.js +1 -0
  254. package/apps/web/.next/static/chunks/app/api/workspace/virtual-file/route-5f5d429b1700dd0e.js +1 -0
  255. package/apps/web/.next/static/chunks/app/api/workspace/watch/route-5f5d429b1700dd0e.js +1 -0
  256. package/apps/web/.next/static/chunks/app/api/workspace/write-binary/route-5f5d429b1700dd0e.js +1 -0
  257. package/apps/web/.next/static/chunks/app/{layout-27bf5ccd9324b2af.js → layout-a0f54c498e78b06e.js} +1 -1
  258. package/apps/web/.next/static/chunks/app/page-441fc26d2fd5ddf4.js +1 -0
  259. package/apps/web/.next/static/css/eb7b54c9778eb5c7.css +1 -0
  260. package/apps/web/.next/static/mOcRFLcuuyC7J3QuiCUwf/_buildManifest.js +1 -0
  261. package/dist/entry.js +1 -1
  262. package/dist/{program-C_fKvUXP.js → program-BDssgdL4.js} +95 -10
  263. package/dist/{run-main-B9xMLY9j.js → run-main-CiJ0dwZR.js} +1 -1
  264. package/extensions/posthog-analytics/lib/build-env.js +1 -1
  265. package/package.json +1 -1
  266. package/skills/app-builder/SKILL.md +122 -1789
  267. package/skills/app-builder/agent-builder/SKILL.md +277 -0
  268. package/skills/app-builder/data-builder/SKILL.md +993 -0
  269. package/skills/app-builder/game-builder/SKILL.md +1379 -0
  270. package/skills/app-builder/platform-api/SKILL.md +338 -0
  271. package/apps/web/.next/standalone/apps/web/.next/static/8JJPnGXX0UABv387IrLpB/_buildManifest.js +0 -1
  272. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/route-0a8ccfe24ebd650b.js +0 -1
  273. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/apps/serve/[...path]/route-0a8ccfe24ebd650b.js +0 -1
  274. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/active/route-0a8ccfe24ebd650b.js +0 -1
  275. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/route-0a8ccfe24ebd650b.js +0 -1
  276. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/runs/route-0a8ccfe24ebd650b.js +0 -1
  277. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/stop/route-0a8ccfe24ebd650b.js +0 -1
  278. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/stream/route-0a8ccfe24ebd650b.js +0 -1
  279. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/chat/subagents/route-0a8ccfe24ebd650b.js +0 -1
  280. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/jobs/[jobId]/runs/route-0a8ccfe24ebd650b.js +0 -1
  281. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/jobs/route-0a8ccfe24ebd650b.js +0 -1
  282. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/runs/[sessionId]/route-0a8ccfe24ebd650b.js +0 -1
  283. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/cron/runs/search-transcript/route-0a8ccfe24ebd650b.js +0 -1
  284. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/feedback/route-0a8ccfe24ebd650b.js +0 -1
  285. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/memories/route-0a8ccfe24ebd650b.js +0 -1
  286. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/profiles/route-0a8ccfe24ebd650b.js +0 -1
  287. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/profiles/switch/route-0a8ccfe24ebd650b.js +0 -1
  288. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/sessions/[sessionId]/route-0a8ccfe24ebd650b.js +0 -1
  289. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/sessions/route-0a8ccfe24ebd650b.js +0 -1
  290. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/skills/route-0a8ccfe24ebd650b.js +0 -1
  291. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/terminal/port/route-0a8ccfe24ebd650b.js +0 -1
  292. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/web-sessions/[id]/messages/route-0a8ccfe24ebd650b.js +0 -1
  293. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/web-sessions/[id]/route-0a8ccfe24ebd650b.js +0 -1
  294. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/web-sessions/route-0a8ccfe24ebd650b.js +0 -1
  295. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/assets/[...path]/route-0a8ccfe24ebd650b.js +0 -1
  296. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/browse/route-0a8ccfe24ebd650b.js +0 -1
  297. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/browse-file/route-0a8ccfe24ebd650b.js +0 -1
  298. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/context/route-0a8ccfe24ebd650b.js +0 -1
  299. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/copy/route-0a8ccfe24ebd650b.js +0 -1
  300. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/db/introspect/route-0a8ccfe24ebd650b.js +0 -1
  301. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/db/query/route-0a8ccfe24ebd650b.js +0 -1
  302. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/delete/route-0a8ccfe24ebd650b.js +0 -1
  303. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/file/route-0a8ccfe24ebd650b.js +0 -1
  304. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/init/route-0a8ccfe24ebd650b.js +0 -1
  305. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/list/route-0a8ccfe24ebd650b.js +0 -1
  306. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/mkdir/route-0a8ccfe24ebd650b.js +0 -1
  307. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/move/route-0a8ccfe24ebd650b.js +0 -1
  308. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/display-field/route-0a8ccfe24ebd650b.js +0 -1
  309. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/[id]/route-0a8ccfe24ebd650b.js +0 -1
  310. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/bulk-delete/route-0a8ccfe24ebd650b.js +0 -1
  311. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/options/route-0a8ccfe24ebd650b.js +0 -1
  312. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/route-0a8ccfe24ebd650b.js +0 -1
  313. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route-0a8ccfe24ebd650b.js +0 -1
  314. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/route-0a8ccfe24ebd650b.js +0 -1
  315. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/reorder/route-0a8ccfe24ebd650b.js +0 -1
  316. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/route-0a8ccfe24ebd650b.js +0 -1
  317. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/views/route-0a8ccfe24ebd650b.js +0 -1
  318. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/open-file/route-0a8ccfe24ebd650b.js +0 -1
  319. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/path-info/route-0a8ccfe24ebd650b.js +0 -1
  320. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/query/route-0a8ccfe24ebd650b.js +0 -1
  321. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/raw-file/route-0a8ccfe24ebd650b.js +0 -1
  322. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/rename/route-0a8ccfe24ebd650b.js +0 -1
  323. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/reports/execute/route-0a8ccfe24ebd650b.js +0 -1
  324. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/search-index/route-0a8ccfe24ebd650b.js +0 -1
  325. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/suggest-files/route-0a8ccfe24ebd650b.js +0 -1
  326. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/switch/route-0a8ccfe24ebd650b.js +0 -1
  327. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/thumbnail/route-0a8ccfe24ebd650b.js +0 -1
  328. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/tree/route-0a8ccfe24ebd650b.js +0 -1
  329. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/upload/route-0a8ccfe24ebd650b.js +0 -1
  330. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/virtual-file/route-0a8ccfe24ebd650b.js +0 -1
  331. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/watch/route-0a8ccfe24ebd650b.js +0 -1
  332. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/api/workspace/write-binary/route-0a8ccfe24ebd650b.js +0 -1
  333. package/apps/web/.next/standalone/apps/web/.next/static/chunks/app/page-a42d210666478706.js +0 -1
  334. package/apps/web/.next/standalone/apps/web/.next/static/css/877366416eab5665.css +0 -1
  335. package/apps/web/.next/static/8JJPnGXX0UABv387IrLpB/_buildManifest.js +0 -1
  336. package/apps/web/.next/static/chunks/app/api/apps/route-0a8ccfe24ebd650b.js +0 -1
  337. package/apps/web/.next/static/chunks/app/api/apps/serve/[...path]/route-0a8ccfe24ebd650b.js +0 -1
  338. package/apps/web/.next/static/chunks/app/api/chat/active/route-0a8ccfe24ebd650b.js +0 -1
  339. package/apps/web/.next/static/chunks/app/api/chat/route-0a8ccfe24ebd650b.js +0 -1
  340. package/apps/web/.next/static/chunks/app/api/chat/runs/route-0a8ccfe24ebd650b.js +0 -1
  341. package/apps/web/.next/static/chunks/app/api/chat/stop/route-0a8ccfe24ebd650b.js +0 -1
  342. package/apps/web/.next/static/chunks/app/api/chat/stream/route-0a8ccfe24ebd650b.js +0 -1
  343. package/apps/web/.next/static/chunks/app/api/chat/subagents/route-0a8ccfe24ebd650b.js +0 -1
  344. package/apps/web/.next/static/chunks/app/api/cron/jobs/[jobId]/runs/route-0a8ccfe24ebd650b.js +0 -1
  345. package/apps/web/.next/static/chunks/app/api/cron/jobs/route-0a8ccfe24ebd650b.js +0 -1
  346. package/apps/web/.next/static/chunks/app/api/cron/runs/[sessionId]/route-0a8ccfe24ebd650b.js +0 -1
  347. package/apps/web/.next/static/chunks/app/api/cron/runs/search-transcript/route-0a8ccfe24ebd650b.js +0 -1
  348. package/apps/web/.next/static/chunks/app/api/feedback/route-0a8ccfe24ebd650b.js +0 -1
  349. package/apps/web/.next/static/chunks/app/api/memories/route-0a8ccfe24ebd650b.js +0 -1
  350. package/apps/web/.next/static/chunks/app/api/profiles/route-0a8ccfe24ebd650b.js +0 -1
  351. package/apps/web/.next/static/chunks/app/api/profiles/switch/route-0a8ccfe24ebd650b.js +0 -1
  352. package/apps/web/.next/static/chunks/app/api/sessions/[sessionId]/route-0a8ccfe24ebd650b.js +0 -1
  353. package/apps/web/.next/static/chunks/app/api/sessions/route-0a8ccfe24ebd650b.js +0 -1
  354. package/apps/web/.next/static/chunks/app/api/skills/route-0a8ccfe24ebd650b.js +0 -1
  355. package/apps/web/.next/static/chunks/app/api/terminal/port/route-0a8ccfe24ebd650b.js +0 -1
  356. package/apps/web/.next/static/chunks/app/api/web-sessions/[id]/messages/route-0a8ccfe24ebd650b.js +0 -1
  357. package/apps/web/.next/static/chunks/app/api/web-sessions/[id]/route-0a8ccfe24ebd650b.js +0 -1
  358. package/apps/web/.next/static/chunks/app/api/web-sessions/route-0a8ccfe24ebd650b.js +0 -1
  359. package/apps/web/.next/static/chunks/app/api/workspace/assets/[...path]/route-0a8ccfe24ebd650b.js +0 -1
  360. package/apps/web/.next/static/chunks/app/api/workspace/browse/route-0a8ccfe24ebd650b.js +0 -1
  361. package/apps/web/.next/static/chunks/app/api/workspace/browse-file/route-0a8ccfe24ebd650b.js +0 -1
  362. package/apps/web/.next/static/chunks/app/api/workspace/context/route-0a8ccfe24ebd650b.js +0 -1
  363. package/apps/web/.next/static/chunks/app/api/workspace/copy/route-0a8ccfe24ebd650b.js +0 -1
  364. package/apps/web/.next/static/chunks/app/api/workspace/db/introspect/route-0a8ccfe24ebd650b.js +0 -1
  365. package/apps/web/.next/static/chunks/app/api/workspace/db/query/route-0a8ccfe24ebd650b.js +0 -1
  366. package/apps/web/.next/static/chunks/app/api/workspace/delete/route-0a8ccfe24ebd650b.js +0 -1
  367. package/apps/web/.next/static/chunks/app/api/workspace/file/route-0a8ccfe24ebd650b.js +0 -1
  368. package/apps/web/.next/static/chunks/app/api/workspace/init/route-0a8ccfe24ebd650b.js +0 -1
  369. package/apps/web/.next/static/chunks/app/api/workspace/list/route-0a8ccfe24ebd650b.js +0 -1
  370. package/apps/web/.next/static/chunks/app/api/workspace/mkdir/route-0a8ccfe24ebd650b.js +0 -1
  371. package/apps/web/.next/static/chunks/app/api/workspace/move/route-0a8ccfe24ebd650b.js +0 -1
  372. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/display-field/route-0a8ccfe24ebd650b.js +0 -1
  373. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/[id]/route-0a8ccfe24ebd650b.js +0 -1
  374. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/bulk-delete/route-0a8ccfe24ebd650b.js +0 -1
  375. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/options/route-0a8ccfe24ebd650b.js +0 -1
  376. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/entries/route-0a8ccfe24ebd650b.js +0 -1
  377. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/enum-rename/route-0a8ccfe24ebd650b.js +0 -1
  378. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/[fieldId]/route-0a8ccfe24ebd650b.js +0 -1
  379. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/fields/reorder/route-0a8ccfe24ebd650b.js +0 -1
  380. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/route-0a8ccfe24ebd650b.js +0 -1
  381. package/apps/web/.next/static/chunks/app/api/workspace/objects/[name]/views/route-0a8ccfe24ebd650b.js +0 -1
  382. package/apps/web/.next/static/chunks/app/api/workspace/open-file/route-0a8ccfe24ebd650b.js +0 -1
  383. package/apps/web/.next/static/chunks/app/api/workspace/path-info/route-0a8ccfe24ebd650b.js +0 -1
  384. package/apps/web/.next/static/chunks/app/api/workspace/query/route-0a8ccfe24ebd650b.js +0 -1
  385. package/apps/web/.next/static/chunks/app/api/workspace/raw-file/route-0a8ccfe24ebd650b.js +0 -1
  386. package/apps/web/.next/static/chunks/app/api/workspace/rename/route-0a8ccfe24ebd650b.js +0 -1
  387. package/apps/web/.next/static/chunks/app/api/workspace/reports/execute/route-0a8ccfe24ebd650b.js +0 -1
  388. package/apps/web/.next/static/chunks/app/api/workspace/search-index/route-0a8ccfe24ebd650b.js +0 -1
  389. package/apps/web/.next/static/chunks/app/api/workspace/suggest-files/route-0a8ccfe24ebd650b.js +0 -1
  390. package/apps/web/.next/static/chunks/app/api/workspace/switch/route-0a8ccfe24ebd650b.js +0 -1
  391. package/apps/web/.next/static/chunks/app/api/workspace/thumbnail/route-0a8ccfe24ebd650b.js +0 -1
  392. package/apps/web/.next/static/chunks/app/api/workspace/tree/route-0a8ccfe24ebd650b.js +0 -1
  393. package/apps/web/.next/static/chunks/app/api/workspace/upload/route-0a8ccfe24ebd650b.js +0 -1
  394. package/apps/web/.next/static/chunks/app/api/workspace/virtual-file/route-0a8ccfe24ebd650b.js +0 -1
  395. package/apps/web/.next/static/chunks/app/api/workspace/watch/route-0a8ccfe24ebd650b.js +0 -1
  396. package/apps/web/.next/static/chunks/app/api/workspace/write-binary/route-0a8ccfe24ebd650b.js +0 -1
  397. package/apps/web/.next/static/chunks/app/page-a42d210666478706.js +0 -1
  398. package/apps/web/.next/static/css/877366416eab5665.css +0 -1
  399. /package/apps/web/.next/standalone/apps/web/.next/static/{8JJPnGXX0UABv387IrLpB → mOcRFLcuuyC7J3QuiCUwf}/_ssgManifest.js +0 -0
  400. /package/apps/web/.next/static/{8JJPnGXX0UABv387IrLpB → mOcRFLcuuyC7J3QuiCUwf}/_ssgManifest.js +0 -0
@@ -0,0 +1,1379 @@
1
+ ---
2
+ name: game-builder
3
+ description: Build 2D and 3D games as DenchClaw apps using p5.js, Three.js, Matter.js, and other game libraries. Covers game architecture, sprites, physics, particles, audio, tilemaps, and complete game examples.
4
+ metadata: { "openclaw": { "inject": true, "always": true, "emoji": "🎮" } }
5
+ ---
6
+
7
+ # App Game Builder
8
+
9
+ This skill covers building 2D and 3D games as DenchClaw apps. For core app structure, manifest reference, and bridge API basics, see the parent **app-builder** skill (`app-builder/SKILL.md`).
10
+
11
+ ---
12
+
13
+ ## 2D Games with p5.js
14
+
15
+ **Always use p5.js for 2D games, simulations, generative art, and interactive 2D experiences.** p5.js is the default choice for anything 2D unless the user specifically requests something else.
16
+
17
+ ### When to Use p5.js
18
+
19
+ - 2D games (platformer, puzzle, arcade, card games, board games)
20
+ - Generative art and creative coding
21
+ - Physics simulations and particle systems
22
+ - Interactive data visualizations with animation
23
+ - Educational simulations and demonstrations
24
+ - Drawing and painting tools
25
+ - Any 2D canvas-based interactive experience
26
+
27
+ ### p5.js App Template
28
+
29
+ ```
30
+ apps/my-game.dench.app/
31
+ .dench.yaml
32
+ index.html
33
+ sketch.js
34
+ assets/ # sprites, sounds, fonts
35
+ ```
36
+
37
+ **`.dench.yaml`:**
38
+ ```yaml
39
+ name: "My Game"
40
+ description: "A fun 2D game built with p5.js"
41
+ icon: "gamepad-2"
42
+ version: "1.0.0"
43
+ entry: "index.html"
44
+ runtime: "static"
45
+ ```
46
+
47
+ No permissions needed unless the game reads/writes workspace data.
48
+
49
+ **`index.html`:**
50
+ ```html
51
+ <!DOCTYPE html>
52
+ <html lang="en">
53
+ <head>
54
+ <meta charset="UTF-8">
55
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
56
+ <title>My Game</title>
57
+ <script src="https://unpkg.com/p5@1/lib/p5.min.js"></script>
58
+ <style>
59
+ * { margin: 0; padding: 0; }
60
+ html, body { width: 100%; height: 100%; overflow: hidden; }
61
+ body { display: flex; align-items: center; justify-content: center; background: #0f0f1a; }
62
+ canvas { display: block; }
63
+ </style>
64
+ </head>
65
+ <body>
66
+ <script src="sketch.js"></script>
67
+ </body>
68
+ </html>
69
+ ```
70
+
71
+ **`sketch.js` (game loop skeleton):**
72
+ ```javascript
73
+ let isDark = true;
74
+
75
+ function setup() {
76
+ createCanvas(windowWidth, windowHeight);
77
+
78
+ // Detect theme from DenchClaw
79
+ if (window.dench) {
80
+ window.dench.app.getTheme().then(theme => {
81
+ isDark = theme === 'dark';
82
+ }).catch(() => {});
83
+ }
84
+ }
85
+
86
+ function draw() {
87
+ background(isDark ? 15 : 245);
88
+
89
+ // Game rendering goes here
90
+ }
91
+
92
+ function windowResized() {
93
+ resizeCanvas(windowWidth, windowHeight);
94
+ }
95
+ ```
96
+
97
+ ### p5.js Instance Mode (Recommended for Complex Apps)
98
+
99
+ Use instance mode to avoid global namespace pollution. This is especially important for multi-file apps:
100
+
101
+ ```javascript
102
+ const sketch = (p) => {
103
+ let isDark = true;
104
+ let player;
105
+
106
+ p.setup = () => {
107
+ p.createCanvas(p.windowWidth, p.windowHeight);
108
+ player = { x: p.width / 2, y: p.height / 2, size: 30, speed: 4 };
109
+
110
+ if (window.dench) {
111
+ window.dench.app.getTheme().then(theme => { isDark = theme === 'dark'; }).catch(() => {});
112
+ }
113
+ };
114
+
115
+ p.draw = () => {
116
+ p.background(isDark ? 15 : 245);
117
+
118
+ // Input handling
119
+ if (p.keyIsDown(p.LEFT_ARROW) || p.keyIsDown(65)) player.x -= player.speed;
120
+ if (p.keyIsDown(p.RIGHT_ARROW) || p.keyIsDown(68)) player.x += player.speed;
121
+ if (p.keyIsDown(p.UP_ARROW) || p.keyIsDown(87)) player.y -= player.speed;
122
+ if (p.keyIsDown(p.DOWN_ARROW) || p.keyIsDown(83)) player.y += player.speed;
123
+
124
+ // Keep in bounds
125
+ player.x = p.constrain(player.x, 0, p.width);
126
+ player.y = p.constrain(player.y, 0, p.height);
127
+
128
+ // Draw player
129
+ p.fill(isDark ? '#6366f1' : '#4f46e5');
130
+ p.noStroke();
131
+ p.ellipse(player.x, player.y, player.size);
132
+ };
133
+
134
+ p.windowResized = () => {
135
+ p.resizeCanvas(p.windowWidth, p.windowHeight);
136
+ };
137
+ };
138
+
139
+ new p5(sketch);
140
+ ```
141
+
142
+ ### p5.js Game Architecture Patterns
143
+
144
+ #### Game State Machine
145
+
146
+ ```javascript
147
+ const GameState = { MENU: 'menu', PLAYING: 'playing', PAUSED: 'paused', GAME_OVER: 'gameover' };
148
+ let state = GameState.MENU;
149
+ let score = 0;
150
+ let highScore = 0;
151
+
152
+ function draw() {
153
+ switch (state) {
154
+ case GameState.MENU: drawMenu(); break;
155
+ case GameState.PLAYING: drawGame(); break;
156
+ case GameState.PAUSED: drawPause(); break;
157
+ case GameState.GAME_OVER: drawGameOver(); break;
158
+ }
159
+ }
160
+
161
+ function keyPressed() {
162
+ if (state === GameState.MENU && (key === ' ' || key === 'Enter')) {
163
+ state = GameState.PLAYING;
164
+ resetGame();
165
+ } else if (state === GameState.PLAYING && key === 'Escape') {
166
+ state = GameState.PAUSED;
167
+ } else if (state === GameState.PAUSED && key === 'Escape') {
168
+ state = GameState.PLAYING;
169
+ } else if (state === GameState.GAME_OVER && (key === ' ' || key === 'Enter')) {
170
+ state = GameState.PLAYING;
171
+ resetGame();
172
+ }
173
+ }
174
+
175
+ function drawMenu() {
176
+ background(15);
177
+ fill(255);
178
+ textAlign(CENTER, CENTER);
179
+ textSize(48);
180
+ text('MY GAME', width / 2, height / 2 - 60);
181
+ textSize(18);
182
+ fill(150);
183
+ text('Press SPACE or ENTER to start', width / 2, height / 2 + 20);
184
+ if (highScore > 0) {
185
+ textSize(14);
186
+ text('High Score: ' + highScore, width / 2, height / 2 + 60);
187
+ }
188
+ }
189
+
190
+ function drawGameOver() {
191
+ background(15);
192
+ fill('#ef4444');
193
+ textAlign(CENTER, CENTER);
194
+ textSize(48);
195
+ text('GAME OVER', width / 2, height / 2 - 60);
196
+ fill(255);
197
+ textSize(24);
198
+ text('Score: ' + score, width / 2, height / 2);
199
+ textSize(16);
200
+ fill(150);
201
+ text('Press SPACE to play again', width / 2, height / 2 + 50);
202
+ }
203
+ ```
204
+
205
+ #### Sprite Management
206
+
207
+ ```javascript
208
+ class Sprite {
209
+ constructor(x, y, w, h) {
210
+ this.pos = createVector(x, y);
211
+ this.vel = createVector(0, 0);
212
+ this.w = w;
213
+ this.h = h;
214
+ this.alive = true;
215
+ }
216
+
217
+ update() {
218
+ this.pos.add(this.vel);
219
+ }
220
+
221
+ draw() {
222
+ rectMode(CENTER);
223
+ rect(this.pos.x, this.pos.y, this.w, this.h);
224
+ }
225
+
226
+ collidesWith(other) {
227
+ return (
228
+ this.pos.x - this.w / 2 < other.pos.x + other.w / 2 &&
229
+ this.pos.x + this.w / 2 > other.pos.x - other.w / 2 &&
230
+ this.pos.y - this.h / 2 < other.pos.y + other.h / 2 &&
231
+ this.pos.y + this.h / 2 > other.pos.y - other.h / 2
232
+ );
233
+ }
234
+
235
+ isOffscreen() {
236
+ return (
237
+ this.pos.x < -this.w || this.pos.x > width + this.w ||
238
+ this.pos.y < -this.h || this.pos.y > height + this.h
239
+ );
240
+ }
241
+ }
242
+ ```
243
+
244
+ #### Particle System
245
+
246
+ ```javascript
247
+ class Particle {
248
+ constructor(x, y, color) {
249
+ this.pos = createVector(x, y);
250
+ this.vel = p5.Vector.random2D().mult(random(1, 5));
251
+ this.acc = createVector(0, 0.1);
252
+ this.color = color;
253
+ this.alpha = 255;
254
+ this.size = random(3, 8);
255
+ this.life = 1.0;
256
+ this.decay = random(0.01, 0.04);
257
+ }
258
+
259
+ update() {
260
+ this.vel.add(this.acc);
261
+ this.pos.add(this.vel);
262
+ this.life -= this.decay;
263
+ this.alpha = this.life * 255;
264
+ }
265
+
266
+ draw() {
267
+ noStroke();
268
+ fill(red(this.color), green(this.color), blue(this.color), this.alpha);
269
+ ellipse(this.pos.x, this.pos.y, this.size);
270
+ }
271
+
272
+ isDead() {
273
+ return this.life <= 0;
274
+ }
275
+ }
276
+
277
+ let particles = [];
278
+
279
+ function spawnExplosion(x, y, col, count = 30) {
280
+ for (let i = 0; i < count; i++) {
281
+ particles.push(new Particle(x, y, col));
282
+ }
283
+ }
284
+
285
+ function updateParticles() {
286
+ for (let i = particles.length - 1; i >= 0; i--) {
287
+ particles[i].update();
288
+ particles[i].draw();
289
+ if (particles[i].isDead()) particles.splice(i, 1);
290
+ }
291
+ }
292
+ ```
293
+
294
+ #### Camera / Scrolling
295
+
296
+ ```javascript
297
+ let camera = { x: 0, y: 0 };
298
+
299
+ function draw() {
300
+ background(15);
301
+
302
+ // Follow player
303
+ camera.x = lerp(camera.x, player.x - width / 2, 0.1);
304
+ camera.y = lerp(camera.y, player.y - height / 2, 0.1);
305
+
306
+ push();
307
+ translate(-camera.x, -camera.y);
308
+
309
+ // Draw world (in world coordinates)
310
+ drawWorld();
311
+ drawPlayer();
312
+ drawEnemies();
313
+
314
+ pop();
315
+
316
+ // Draw HUD (in screen coordinates)
317
+ drawHUD();
318
+ }
319
+ ```
320
+
321
+ #### Tilemap Rendering
322
+
323
+ ```javascript
324
+ const TILE_SIZE = 32;
325
+ const tilemap = [
326
+ [1, 1, 1, 1, 1, 1, 1, 1],
327
+ [1, 0, 0, 0, 0, 0, 0, 1],
328
+ [1, 0, 0, 2, 0, 0, 0, 1],
329
+ [1, 0, 0, 0, 0, 3, 0, 1],
330
+ [1, 1, 1, 1, 1, 1, 1, 1],
331
+ ];
332
+
333
+ const TILE_COLORS = {
334
+ 0: null, // empty
335
+ 1: '#4a4a6a', // wall
336
+ 2: '#22c55e', // item
337
+ 3: '#ef4444', // enemy
338
+ };
339
+
340
+ function drawTilemap() {
341
+ for (let row = 0; row < tilemap.length; row++) {
342
+ for (let col = 0; col < tilemap[row].length; col++) {
343
+ const tile = tilemap[row][col];
344
+ if (TILE_COLORS[tile]) {
345
+ fill(TILE_COLORS[tile]);
346
+ noStroke();
347
+ rect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE);
348
+ }
349
+ }
350
+ }
351
+ }
352
+ ```
353
+
354
+ #### Sound Effects (using p5.sound or Howler.js)
355
+
356
+ For sound, prefer Howler.js since p5.sound adds significant bundle size:
357
+
358
+ ```html
359
+ <script src="https://unpkg.com/howler@2/dist/howler.min.js"></script>
360
+ ```
361
+
362
+ ```javascript
363
+ const sounds = {
364
+ jump: new Howl({ src: ['assets/jump.wav'], volume: 0.5 }),
365
+ hit: new Howl({ src: ['assets/hit.wav'], volume: 0.7 }),
366
+ coin: new Howl({ src: ['assets/coin.wav'], volume: 0.4 }),
367
+ music: new Howl({ src: ['assets/music.mp3'], loop: true, volume: 0.3 }),
368
+ };
369
+ ```
370
+
371
+ If no sound assets are available, generate simple audio with Tone.js or the Web Audio API:
372
+
373
+ ```javascript
374
+ function playBeep(freq = 440, duration = 0.1) {
375
+ const ctx = new (window.AudioContext || window.webkitAudioContext)();
376
+ const osc = ctx.createOscillator();
377
+ const gain = ctx.createGain();
378
+ osc.connect(gain);
379
+ gain.connect(ctx.destination);
380
+ osc.frequency.value = freq;
381
+ gain.gain.setValueAtTime(0.3, ctx.currentTime);
382
+ gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + duration);
383
+ osc.start();
384
+ osc.stop(ctx.currentTime + duration);
385
+ }
386
+ ```
387
+
388
+ ### p5.js with Physics (Matter.js)
389
+
390
+ For games needing realistic 2D physics (platformers, ragdoll, pinball):
391
+
392
+ ```html
393
+ <script src="https://unpkg.com/p5@1/lib/p5.min.js"></script>
394
+ <script src="https://unpkg.com/matter-js@0.20/build/matter.min.js"></script>
395
+ ```
396
+
397
+ ```javascript
398
+ const { Engine, World, Bodies, Body, Events } = Matter;
399
+
400
+ let engine, world;
401
+ let ground, player;
402
+
403
+ function setup() {
404
+ createCanvas(windowWidth, windowHeight);
405
+ engine = Engine.create();
406
+ world = engine.world;
407
+
408
+ ground = Bodies.rectangle(width / 2, height - 20, width, 40, { isStatic: true });
409
+ player = Bodies.circle(width / 2, height / 2, 20, { restitution: 0.5 });
410
+
411
+ World.add(world, [ground, player]);
412
+ }
413
+
414
+ function draw() {
415
+ Engine.update(engine);
416
+ background(15);
417
+
418
+ // Draw ground
419
+ fill('#4a4a6a');
420
+ rectMode(CENTER);
421
+ rect(ground.position.x, ground.position.y, width, 40);
422
+
423
+ // Draw player
424
+ fill('#6366f1');
425
+ ellipse(player.position.x, player.position.y, 40);
426
+ }
427
+
428
+ function keyPressed() {
429
+ if (key === ' ') {
430
+ Body.applyForce(player, player.position, { x: 0, y: -0.05 });
431
+ }
432
+ }
433
+ ```
434
+
435
+ ### p5.js Responsive Canvas
436
+
437
+ Always handle window resizing and use the full viewport:
438
+
439
+ ```javascript
440
+ function setup() {
441
+ createCanvas(windowWidth, windowHeight);
442
+ }
443
+
444
+ function windowResized() {
445
+ resizeCanvas(windowWidth, windowHeight);
446
+ }
447
+ ```
448
+
449
+ For fixed-aspect-ratio games (e.g., retro pixel games), scale the canvas:
450
+
451
+ ```javascript
452
+ const GAME_W = 320;
453
+ const GAME_H = 240;
454
+ let scaleFactor;
455
+
456
+ function setup() {
457
+ createCanvas(windowWidth, windowHeight);
458
+ pixelDensity(1);
459
+ noSmooth();
460
+ calcScale();
461
+ }
462
+
463
+ function calcScale() {
464
+ scaleFactor = min(windowWidth / GAME_W, windowHeight / GAME_H);
465
+ }
466
+
467
+ function draw() {
468
+ background(0);
469
+ push();
470
+ translate((width - GAME_W * scaleFactor) / 2, (height - GAME_H * scaleFactor) / 2);
471
+ scale(scaleFactor);
472
+
473
+ // All game drawing at GAME_W x GAME_H logical resolution
474
+ drawGameWorld();
475
+
476
+ pop();
477
+ }
478
+
479
+ function windowResized() {
480
+ resizeCanvas(windowWidth, windowHeight);
481
+ calcScale();
482
+ }
483
+ ```
484
+
485
+ ### Touch / Mobile Input for p5.js Games
486
+
487
+ ```javascript
488
+ let touchActive = false;
489
+ let touchX = 0, touchY = 0;
490
+
491
+ function touchStarted() {
492
+ touchActive = true;
493
+ touchX = mouseX;
494
+ touchY = mouseY;
495
+ return false; // prevent default
496
+ }
497
+
498
+ function touchMoved() {
499
+ touchX = mouseX;
500
+ touchY = mouseY;
501
+ return false;
502
+ }
503
+
504
+ function touchEnded() {
505
+ touchActive = false;
506
+ return false;
507
+ }
508
+
509
+ // Unified input: works for both mouse and touch
510
+ function getInputX() { return mouseX; }
511
+ function getInputY() { return mouseY; }
512
+ function isInputActive() { return mouseIsPressed || touchActive; }
513
+ ```
514
+
515
+ ### p5.js High Score Persistence with DuckDB
516
+
517
+ If the game has a `database` permission, persist high scores:
518
+
519
+ ```javascript
520
+ async function loadHighScore() {
521
+ try {
522
+ await window.dench.db.execute(`
523
+ CREATE TABLE IF NOT EXISTS game_scores (
524
+ game TEXT, score INTEGER, played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
525
+ )
526
+ `);
527
+ const result = await window.dench.db.query(
528
+ `SELECT MAX(score) as high_score FROM game_scores WHERE game = 'my-game'`
529
+ );
530
+ return result.rows?.[0]?.high_score || 0;
531
+ } catch { return 0; }
532
+ }
533
+
534
+ async function saveScore(score) {
535
+ try {
536
+ await window.dench.db.execute(
537
+ `INSERT INTO game_scores (game, score) VALUES ('my-game', ${score})`
538
+ );
539
+ } catch {}
540
+ }
541
+ ```
542
+
543
+ ---
544
+
545
+ ## 3D Games & Experiences with Three.js
546
+
547
+ **Always use Three.js for 3D games, visualizations, and interactive 3D experiences.** Three.js is the default choice for anything 3D.
548
+
549
+ ### When to Use Three.js
550
+
551
+ - 3D games (first-person, third-person, flying, racing)
552
+ - 3D product viewers and configurators
553
+ - Terrain and world visualization
554
+ - 3D data visualization (3D scatter plots, network graphs)
555
+ - Architectural walkthroughs
556
+ - Generative 3D art
557
+ - Physics-based 3D simulations
558
+
559
+ ### Three.js App Template
560
+
561
+ ```
562
+ apps/my-3d-app.dench.app/
563
+ .dench.yaml
564
+ index.html
565
+ app.js # Main Three.js module
566
+ assets/
567
+ model.glb # 3D models (optional)
568
+ texture.jpg # Textures (optional)
569
+ ```
570
+
571
+ **`.dench.yaml`:**
572
+ ```yaml
573
+ name: "3D World"
574
+ description: "An interactive 3D experience"
575
+ icon: "box"
576
+ version: "1.0.0"
577
+ entry: "index.html"
578
+ runtime: "static"
579
+ ```
580
+
581
+ **`index.html`:**
582
+ ```html
583
+ <!DOCTYPE html>
584
+ <html lang="en">
585
+ <head>
586
+ <meta charset="UTF-8">
587
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
588
+ <title>3D World</title>
589
+ <script type="importmap">
590
+ {
591
+ "imports": {
592
+ "three": "https://unpkg.com/three@0.170/build/three.module.js",
593
+ "three/addons/": "https://unpkg.com/three@0.170/examples/jsm/"
594
+ }
595
+ }
596
+ </script>
597
+ <style>
598
+ * { margin: 0; padding: 0; }
599
+ html, body { width: 100%; height: 100%; overflow: hidden; }
600
+ canvas { display: block; }
601
+ #loading {
602
+ position: fixed; inset: 0; display: flex;
603
+ align-items: center; justify-content: center;
604
+ background: #0f0f1a; color: #e8e8f0;
605
+ font-family: -apple-system, BlinkMacSystemFont, sans-serif;
606
+ font-size: 18px; z-index: 10;
607
+ transition: opacity 0.5s;
608
+ }
609
+ #loading.hidden { opacity: 0; pointer-events: none; }
610
+ </style>
611
+ </head>
612
+ <body>
613
+ <div id="loading">Loading...</div>
614
+ <script type="module" src="app.js"></script>
615
+ </body>
616
+ </html>
617
+ ```
618
+
619
+ **`app.js` (Three.js module skeleton):**
620
+ ```javascript
621
+ import * as THREE from 'three';
622
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
623
+
624
+ // --- Scene setup ---
625
+ const scene = new THREE.Scene();
626
+ scene.background = new THREE.Color(0x0f0f1a);
627
+ scene.fog = new THREE.Fog(0x0f0f1a, 50, 200);
628
+
629
+ const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
630
+ camera.position.set(0, 5, 10);
631
+
632
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
633
+ renderer.setSize(window.innerWidth, window.innerHeight);
634
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
635
+ renderer.shadowMap.enabled = true;
636
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
637
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
638
+ renderer.toneMappingExposure = 1.0;
639
+ document.body.appendChild(renderer.domElement);
640
+
641
+ // --- Controls ---
642
+ const controls = new OrbitControls(camera, renderer.domElement);
643
+ controls.enableDamping = true;
644
+ controls.dampingFactor = 0.05;
645
+ controls.maxPolarAngle = Math.PI / 2;
646
+
647
+ // --- Lighting ---
648
+ const ambientLight = new THREE.AmbientLight(0x404060, 0.5);
649
+ scene.add(ambientLight);
650
+
651
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
652
+ directionalLight.position.set(10, 20, 10);
653
+ directionalLight.castShadow = true;
654
+ directionalLight.shadow.mapSize.set(2048, 2048);
655
+ directionalLight.shadow.camera.near = 0.5;
656
+ directionalLight.shadow.camera.far = 100;
657
+ directionalLight.shadow.camera.left = -30;
658
+ directionalLight.shadow.camera.right = 30;
659
+ directionalLight.shadow.camera.top = 30;
660
+ directionalLight.shadow.camera.bottom = -30;
661
+ scene.add(directionalLight);
662
+
663
+ // --- Ground ---
664
+ const groundGeo = new THREE.PlaneGeometry(200, 200);
665
+ const groundMat = new THREE.MeshStandardMaterial({ color: 0x1a1a2e, roughness: 0.8 });
666
+ const ground = new THREE.Mesh(groundGeo, groundMat);
667
+ ground.rotation.x = -Math.PI / 2;
668
+ ground.receiveShadow = true;
669
+ scene.add(ground);
670
+
671
+ // --- Objects ---
672
+ const geometry = new THREE.BoxGeometry(2, 2, 2);
673
+ const material = new THREE.MeshStandardMaterial({
674
+ color: 0x6366f1,
675
+ roughness: 0.3,
676
+ metalness: 0.5,
677
+ });
678
+ const cube = new THREE.Mesh(geometry, material);
679
+ cube.position.y = 1;
680
+ cube.castShadow = true;
681
+ scene.add(cube);
682
+
683
+ // --- Theme ---
684
+ if (window.dench) {
685
+ window.dench.app.getTheme().then(theme => {
686
+ if (theme === 'light') {
687
+ scene.background = new THREE.Color(0xf0f0f5);
688
+ scene.fog = new THREE.Fog(0xf0f0f5, 50, 200);
689
+ groundMat.color.set(0xe8e8f0);
690
+ }
691
+ }).catch(() => {});
692
+ }
693
+
694
+ // --- Hide loading screen ---
695
+ document.getElementById('loading')?.classList.add('hidden');
696
+
697
+ // --- Animation loop ---
698
+ const clock = new THREE.Clock();
699
+
700
+ function animate() {
701
+ requestAnimationFrame(animate);
702
+ const dt = clock.getDelta();
703
+ const elapsed = clock.getElapsedTime();
704
+
705
+ cube.rotation.y = elapsed * 0.5;
706
+ cube.position.y = 1 + Math.sin(elapsed) * 0.5;
707
+
708
+ controls.update();
709
+ renderer.render(scene, camera);
710
+ }
711
+
712
+ animate();
713
+
714
+ // --- Resize ---
715
+ window.addEventListener('resize', () => {
716
+ camera.aspect = window.innerWidth / window.innerHeight;
717
+ camera.updateProjectionMatrix();
718
+ renderer.setSize(window.innerWidth, window.innerHeight);
719
+ });
720
+ ```
721
+
722
+ ### Three.js Common Addons
723
+
724
+ Load additional Three.js modules as needed via the import map:
725
+
726
+ ```javascript
727
+ // First-person controls
728
+ import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
729
+
730
+ // GLTF model loading
731
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
732
+
733
+ // Post-processing
734
+ import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
735
+ import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
736
+ import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
737
+
738
+ // Environment maps
739
+ import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
740
+
741
+ // Text
742
+ import { FontLoader } from 'three/addons/loaders/FontLoader.js';
743
+ import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
744
+
745
+ // Sky
746
+ import { Sky } from 'three/addons/objects/Sky.js';
747
+
748
+ // Water
749
+ import { Water } from 'three/addons/objects/Water.js';
750
+
751
+ // Physics integration (use cannon-es via CDN)
752
+ // Add to importmap: "cannon-es": "https://unpkg.com/cannon-es@0.20/dist/cannon-es.js"
753
+ import * as CANNON from 'cannon-es';
754
+ ```
755
+
756
+ ### Three.js First-Person Game Pattern
757
+
758
+ ```javascript
759
+ import * as THREE from 'three';
760
+ import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
761
+
762
+ const scene = new THREE.Scene();
763
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
764
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
765
+ renderer.setSize(window.innerWidth, window.innerHeight);
766
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
767
+ document.body.appendChild(renderer.domElement);
768
+
769
+ const controls = new PointerLockControls(camera, document.body);
770
+
771
+ // Click to enter pointer lock
772
+ document.addEventListener('click', () => {
773
+ if (!controls.isLocked) controls.lock();
774
+ });
775
+
776
+ // Movement state
777
+ const velocity = new THREE.Vector3();
778
+ const direction = new THREE.Vector3();
779
+ const keys = { forward: false, backward: false, left: false, right: false, jump: false };
780
+
781
+ document.addEventListener('keydown', (e) => {
782
+ switch (e.code) {
783
+ case 'KeyW': case 'ArrowUp': keys.forward = true; break;
784
+ case 'KeyS': case 'ArrowDown': keys.backward = true; break;
785
+ case 'KeyA': case 'ArrowLeft': keys.left = true; break;
786
+ case 'KeyD': case 'ArrowRight': keys.right = true; break;
787
+ case 'Space': keys.jump = true; break;
788
+ }
789
+ });
790
+
791
+ document.addEventListener('keyup', (e) => {
792
+ switch (e.code) {
793
+ case 'KeyW': case 'ArrowUp': keys.forward = false; break;
794
+ case 'KeyS': case 'ArrowDown': keys.backward = false; break;
795
+ case 'KeyA': case 'ArrowLeft': keys.left = false; break;
796
+ case 'KeyD': case 'ArrowRight': keys.right = false; break;
797
+ case 'Space': keys.jump = false; break;
798
+ }
799
+ });
800
+
801
+ let onGround = true;
802
+ const MOVE_SPEED = 50;
803
+ const JUMP_FORCE = 12;
804
+ const GRAVITY = 30;
805
+
806
+ const clock = new THREE.Clock();
807
+
808
+ function animate() {
809
+ requestAnimationFrame(animate);
810
+ const dt = Math.min(clock.getDelta(), 0.1);
811
+
812
+ if (controls.isLocked) {
813
+ // Apply friction
814
+ velocity.x -= velocity.x * 10.0 * dt;
815
+ velocity.z -= velocity.z * 10.0 * dt;
816
+ velocity.y -= GRAVITY * dt;
817
+
818
+ direction.z = Number(keys.forward) - Number(keys.backward);
819
+ direction.x = Number(keys.right) - Number(keys.left);
820
+ direction.normalize();
821
+
822
+ if (keys.forward || keys.backward) velocity.z -= direction.z * MOVE_SPEED * dt;
823
+ if (keys.left || keys.right) velocity.x -= direction.x * MOVE_SPEED * dt;
824
+ if (keys.jump && onGround) { velocity.y = JUMP_FORCE; onGround = false; }
825
+
826
+ controls.moveRight(-velocity.x * dt);
827
+ controls.moveForward(-velocity.z * dt);
828
+ camera.position.y += velocity.y * dt;
829
+
830
+ if (camera.position.y < 1.7) {
831
+ velocity.y = 0;
832
+ camera.position.y = 1.7;
833
+ onGround = true;
834
+ }
835
+ }
836
+
837
+ renderer.render(scene, camera);
838
+ }
839
+
840
+ animate();
841
+ ```
842
+
843
+ ### Three.js GLTF Model Loading
844
+
845
+ ```javascript
846
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
847
+ import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
848
+
849
+ const loader = new GLTFLoader();
850
+ const dracoLoader = new DRACOLoader();
851
+ dracoLoader.setDecoderPath('https://unpkg.com/three@0.170/examples/jsm/libs/draco/');
852
+ loader.setDRACOLoader(dracoLoader);
853
+
854
+ // Load a model from the app's assets folder
855
+ loader.load('assets/model.glb', (gltf) => {
856
+ const model = gltf.scene;
857
+ model.traverse((child) => {
858
+ if (child.isMesh) {
859
+ child.castShadow = true;
860
+ child.receiveShadow = true;
861
+ }
862
+ });
863
+ model.scale.setScalar(1);
864
+ scene.add(model);
865
+
866
+ // If the model has animations
867
+ if (gltf.animations.length > 0) {
868
+ const mixer = new THREE.AnimationMixer(model);
869
+ const action = mixer.clipAction(gltf.animations[0]);
870
+ action.play();
871
+ // In animate loop: mixer.update(dt);
872
+ }
873
+ }, undefined, (error) => {
874
+ console.error('Model load error:', error);
875
+ });
876
+ ```
877
+
878
+ ### Three.js Post-Processing (Bloom, etc.)
879
+
880
+ ```javascript
881
+ import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
882
+ import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
883
+ import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
884
+
885
+ const composer = new EffectComposer(renderer);
886
+ composer.addPass(new RenderPass(scene, camera));
887
+
888
+ const bloomPass = new UnrealBloomPass(
889
+ new THREE.Vector2(window.innerWidth, window.innerHeight),
890
+ 0.5, // strength
891
+ 0.4, // radius
892
+ 0.85 // threshold
893
+ );
894
+ composer.addPass(bloomPass);
895
+
896
+ // In animate loop, replace renderer.render(scene, camera) with:
897
+ // composer.render();
898
+
899
+ // On resize, also update:
900
+ // composer.setSize(window.innerWidth, window.innerHeight);
901
+ ```
902
+
903
+ ### Three.js Procedural Terrain
904
+
905
+ ```javascript
906
+ function createTerrain(width, depth, resolution) {
907
+ const geometry = new THREE.PlaneGeometry(width, depth, resolution, resolution);
908
+ const vertices = geometry.attributes.position.array;
909
+
910
+ for (let i = 0; i < vertices.length; i += 3) {
911
+ const x = vertices[i];
912
+ const z = vertices[i + 1];
913
+ vertices[i + 2] = noise(x * 0.02, z * 0.02) * 15;
914
+ }
915
+
916
+ geometry.computeVertexNormals();
917
+
918
+ const material = new THREE.MeshStandardMaterial({
919
+ color: 0x3a7d44,
920
+ roughness: 0.9,
921
+ flatShading: true,
922
+ });
923
+
924
+ const mesh = new THREE.Mesh(geometry, material);
925
+ mesh.rotation.x = -Math.PI / 2;
926
+ mesh.receiveShadow = true;
927
+ return mesh;
928
+ }
929
+
930
+ // Simple noise function (for procedural generation without dependencies)
931
+ function noise(x, y) {
932
+ const n = Math.sin(x * 12.9898 + y * 78.233) * 43758.5453;
933
+ return n - Math.floor(n);
934
+ }
935
+ ```
936
+
937
+ ### Three.js HUD / UI Overlay
938
+
939
+ Since Three.js renders to a canvas, use HTML overlays for UI:
940
+
941
+ ```html
942
+ <div id="hud" style="
943
+ position: fixed; top: 0; left: 0; right: 0;
944
+ padding: 16px; pointer-events: none;
945
+ font-family: -apple-system, BlinkMacSystemFont, sans-serif;
946
+ color: white; z-index: 5;
947
+ ">
948
+ <div id="score" style="font-size: 24px; font-weight: 700;"></div>
949
+ <div id="health-bar" style="
950
+ width: 200px; height: 8px; border-radius: 4px;
951
+ background: rgba(255,255,255,0.2); margin-top: 8px;
952
+ ">
953
+ <div id="health-fill" style="
954
+ width: 100%; height: 100%; border-radius: 4px;
955
+ background: #22c55e; transition: width 0.3s;
956
+ "></div>
957
+ </div>
958
+ </div>
959
+ ```
960
+
961
+ ```javascript
962
+ function updateHUD(score, health) {
963
+ document.getElementById('score').textContent = `Score: ${score}`;
964
+ document.getElementById('health-fill').style.width = `${health}%`;
965
+ document.getElementById('health-fill').style.background =
966
+ health > 50 ? '#22c55e' : health > 25 ? '#f59e0b' : '#ef4444';
967
+ }
968
+ ```
969
+
970
+ ---
971
+
972
+ ## Full Game Examples
973
+
974
+ ### Example 1: Arcade Game (p5.js)
975
+
976
+ A complete asteroid-dodge game with scoring, particles, and game states.
977
+
978
+ **`.dench.yaml`:**
979
+ ```yaml
980
+ name: "Asteroid Dodge"
981
+ description: "Dodge the falling asteroids! Arrow keys or WASD to move."
982
+ icon: "rocket"
983
+ version: "1.0.0"
984
+ entry: "index.html"
985
+ runtime: "static"
986
+ ```
987
+
988
+ **`index.html`:**
989
+ ```html
990
+ <!DOCTYPE html>
991
+ <html lang="en">
992
+ <head>
993
+ <meta charset="UTF-8">
994
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
995
+ <title>Asteroid Dodge</title>
996
+ <script src="https://unpkg.com/p5@1/lib/p5.min.js"></script>
997
+ <style>
998
+ * { margin: 0; padding: 0; }
999
+ html, body { width: 100%; height: 100%; overflow: hidden; background: #0a0a1a; }
1000
+ canvas { display: block; }
1001
+ </style>
1002
+ </head>
1003
+ <body>
1004
+ <script src="game.js"></script>
1005
+ </body>
1006
+ </html>
1007
+ ```
1008
+
1009
+ **`game.js`:**
1010
+ ```javascript
1011
+ const State = { MENU: 0, PLAY: 1, OVER: 2 };
1012
+ let state = State.MENU;
1013
+ let player, asteroids, particles, stars;
1014
+ let score, highScore = 0, spawnTimer, difficulty;
1015
+
1016
+ function setup() {
1017
+ createCanvas(windowWidth, windowHeight);
1018
+ textFont('system-ui');
1019
+
1020
+ stars = Array.from({ length: 100 }, () => ({
1021
+ x: random(width), y: random(height), s: random(1, 3), b: random(100, 255)
1022
+ }));
1023
+
1024
+ if (window.dench) {
1025
+ window.dench.app.getTheme().catch(() => {});
1026
+ }
1027
+ }
1028
+
1029
+ function resetGame() {
1030
+ player = { x: width / 2, y: height - 80, size: 24, speed: 5, lives: 3, invincible: 0 };
1031
+ asteroids = [];
1032
+ particles = [];
1033
+ score = 0;
1034
+ spawnTimer = 0;
1035
+ difficulty = 1;
1036
+ }
1037
+
1038
+ function draw() {
1039
+ background(10, 10, 26);
1040
+ drawStars();
1041
+
1042
+ switch (state) {
1043
+ case State.MENU: drawMenu(); break;
1044
+ case State.PLAY: updateGame(); drawGame(); drawHUD(); break;
1045
+ case State.OVER: drawGame(); drawHUD(); drawGameOver(); break;
1046
+ }
1047
+ }
1048
+
1049
+ function drawStars() {
1050
+ noStroke();
1051
+ for (const s of stars) {
1052
+ fill(255, s.b);
1053
+ ellipse(s.x, s.y, s.s);
1054
+ s.y += s.s * 0.3;
1055
+ if (s.y > height) { s.y = 0; s.x = random(width); }
1056
+ }
1057
+ }
1058
+
1059
+ function drawMenu() {
1060
+ fill(255);
1061
+ textAlign(CENTER, CENTER);
1062
+ textSize(min(width * 0.08, 56));
1063
+ textStyle(BOLD);
1064
+ text('ASTEROID DODGE', width / 2, height / 2 - 60);
1065
+ textSize(min(width * 0.03, 18));
1066
+ textStyle(NORMAL);
1067
+ fill(180);
1068
+ text('Arrow keys or WASD to move', width / 2, height / 2 + 10);
1069
+ fill(99, 102, 241);
1070
+ text('Press SPACE or ENTER to start', width / 2, height / 2 + 50);
1071
+ if (highScore > 0) {
1072
+ fill(120);
1073
+ textSize(14);
1074
+ text('High Score: ' + highScore, width / 2, height / 2 + 90);
1075
+ }
1076
+ }
1077
+
1078
+ function updateGame() {
1079
+ // Player movement
1080
+ if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) player.x -= player.speed;
1081
+ if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) player.x += player.speed;
1082
+ if (keyIsDown(UP_ARROW) || keyIsDown(87)) player.y -= player.speed;
1083
+ if (keyIsDown(DOWN_ARROW) || keyIsDown(83)) player.y += player.speed;
1084
+ player.x = constrain(player.x, player.size, width - player.size);
1085
+ player.y = constrain(player.y, player.size, height - player.size);
1086
+ if (player.invincible > 0) player.invincible--;
1087
+
1088
+ // Spawn asteroids
1089
+ difficulty = 1 + score / 500;
1090
+ spawnTimer++;
1091
+ if (spawnTimer > max(15, 45 - difficulty * 3)) {
1092
+ asteroids.push({
1093
+ x: random(width), y: -30,
1094
+ size: random(15, 35),
1095
+ vy: random(2, 4) * difficulty,
1096
+ vx: random(-1, 1),
1097
+ rot: random(TWO_PI),
1098
+ rotSpeed: random(-0.05, 0.05),
1099
+ });
1100
+ spawnTimer = 0;
1101
+ }
1102
+
1103
+ // Update asteroids
1104
+ for (let i = asteroids.length - 1; i >= 0; i--) {
1105
+ const a = asteroids[i];
1106
+ a.y += a.vy;
1107
+ a.x += a.vx;
1108
+ a.rot += a.rotSpeed;
1109
+
1110
+ if (a.y > height + 50) {
1111
+ asteroids.splice(i, 1);
1112
+ score += 10;
1113
+ continue;
1114
+ }
1115
+
1116
+ // Collision
1117
+ if (player.invincible <= 0 && dist(player.x, player.y, a.x, a.y) < player.size + a.size / 2) {
1118
+ spawnParticles(a.x, a.y, color(239, 68, 68), 20);
1119
+ asteroids.splice(i, 1);
1120
+ player.lives--;
1121
+ player.invincible = 90;
1122
+ if (player.lives <= 0) {
1123
+ highScore = max(highScore, score);
1124
+ state = State.OVER;
1125
+ }
1126
+ }
1127
+ }
1128
+
1129
+ // Update particles
1130
+ for (let i = particles.length - 1; i >= 0; i--) {
1131
+ const p = particles[i];
1132
+ p.x += p.vx; p.y += p.vy; p.vy += 0.05; p.life -= 0.02;
1133
+ if (p.life <= 0) particles.splice(i, 1);
1134
+ }
1135
+
1136
+ score++;
1137
+ }
1138
+
1139
+ function drawGame() {
1140
+ // Draw asteroids
1141
+ for (const a of asteroids) {
1142
+ push();
1143
+ translate(a.x, a.y);
1144
+ rotate(a.rot);
1145
+ fill(120, 120, 140);
1146
+ stroke(80, 80, 100);
1147
+ strokeWeight(1);
1148
+ beginShape();
1149
+ for (let i = 0; i < 7; i++) {
1150
+ const angle = map(i, 0, 7, 0, TWO_PI);
1151
+ const r = a.size / 2 * (0.7 + 0.3 * sin(i * 2.5));
1152
+ vertex(cos(angle) * r, sin(angle) * r);
1153
+ }
1154
+ endShape(CLOSE);
1155
+ pop();
1156
+ }
1157
+
1158
+ // Draw particles
1159
+ noStroke();
1160
+ for (const p of particles) {
1161
+ fill(red(p.col), green(p.col), blue(p.col), p.life * 255);
1162
+ ellipse(p.x, p.y, p.size * p.life);
1163
+ }
1164
+
1165
+ // Draw player
1166
+ if (state === State.PLAY) {
1167
+ if (player.invincible <= 0 || frameCount % 6 < 3) {
1168
+ push();
1169
+ translate(player.x, player.y);
1170
+ fill(99, 102, 241);
1171
+ noStroke();
1172
+ triangle(0, -player.size, -player.size * 0.6, player.size * 0.6, player.size * 0.6, player.size * 0.6);
1173
+ fill(129, 140, 248);
1174
+ triangle(0, -player.size * 0.5, -player.size * 0.3, player.size * 0.3, player.size * 0.3, player.size * 0.3);
1175
+ pop();
1176
+ }
1177
+ }
1178
+ }
1179
+
1180
+ function drawHUD() {
1181
+ fill(255);
1182
+ noStroke();
1183
+ textAlign(LEFT, TOP);
1184
+ textSize(20);
1185
+ textStyle(BOLD);
1186
+ text('Score: ' + score, 20, 20);
1187
+ textStyle(NORMAL);
1188
+ textSize(14);
1189
+ fill(200);
1190
+ for (let i = 0; i < player.lives; i++) {
1191
+ fill(239, 68, 68);
1192
+ ellipse(20 + i * 22, 55, 14);
1193
+ }
1194
+ }
1195
+
1196
+ function drawGameOver() {
1197
+ fill(0, 0, 0, 150);
1198
+ rect(0, 0, width, height);
1199
+ fill(239, 68, 68);
1200
+ textAlign(CENTER, CENTER);
1201
+ textSize(min(width * 0.07, 48));
1202
+ textStyle(BOLD);
1203
+ text('GAME OVER', width / 2, height / 2 - 40);
1204
+ fill(255);
1205
+ textSize(22);
1206
+ textStyle(NORMAL);
1207
+ text('Score: ' + score, width / 2, height / 2 + 10);
1208
+ fill(180);
1209
+ textSize(16);
1210
+ text('Press SPACE to play again', width / 2, height / 2 + 50);
1211
+ }
1212
+
1213
+ function spawnParticles(x, y, col, count) {
1214
+ for (let i = 0; i < count; i++) {
1215
+ const angle = random(TWO_PI);
1216
+ const speed = random(1, 5);
1217
+ particles.push({
1218
+ x, y, vx: cos(angle) * speed, vy: sin(angle) * speed,
1219
+ size: random(4, 10), col, life: 1.0,
1220
+ });
1221
+ }
1222
+ }
1223
+
1224
+ function keyPressed() {
1225
+ if (state === State.MENU && (key === ' ' || key === 'Enter')) {
1226
+ state = State.PLAY;
1227
+ resetGame();
1228
+ } else if (state === State.OVER && (key === ' ' || key === 'Enter')) {
1229
+ state = State.PLAY;
1230
+ resetGame();
1231
+ }
1232
+ }
1233
+
1234
+ function windowResized() {
1235
+ resizeCanvas(windowWidth, windowHeight);
1236
+ }
1237
+ ```
1238
+
1239
+ ### Example 2: 3D Scene Viewer (Three.js)
1240
+
1241
+ **`.dench.yaml`:**
1242
+ ```yaml
1243
+ name: "3D Playground"
1244
+ description: "Interactive 3D scene with orbit controls"
1245
+ icon: "box"
1246
+ version: "1.0.0"
1247
+ entry: "index.html"
1248
+ runtime: "static"
1249
+ ```
1250
+
1251
+ **`index.html`:**
1252
+ ```html
1253
+ <!DOCTYPE html>
1254
+ <html lang="en">
1255
+ <head>
1256
+ <meta charset="UTF-8">
1257
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1258
+ <title>3D Playground</title>
1259
+ <script type="importmap">
1260
+ {
1261
+ "imports": {
1262
+ "three": "https://unpkg.com/three@0.170/build/three.module.js",
1263
+ "three/addons/": "https://unpkg.com/three@0.170/examples/jsm/"
1264
+ }
1265
+ }
1266
+ </script>
1267
+ <style>
1268
+ * { margin: 0; padding: 0; }
1269
+ html, body { width: 100%; height: 100%; overflow: hidden; }
1270
+ canvas { display: block; }
1271
+ </style>
1272
+ </head>
1273
+ <body>
1274
+ <script type="module" src="scene.js"></script>
1275
+ </body>
1276
+ </html>
1277
+ ```
1278
+
1279
+ **`scene.js`:**
1280
+ ```javascript
1281
+ import * as THREE from 'three';
1282
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
1283
+
1284
+ const scene = new THREE.Scene();
1285
+ let bgColor = 0x0f0f1a;
1286
+
1287
+ if (window.dench) {
1288
+ window.dench.app.getTheme().then(t => {
1289
+ bgColor = t === 'light' ? 0xf0f0f5 : 0x0f0f1a;
1290
+ scene.background = new THREE.Color(bgColor);
1291
+ scene.fog = new THREE.Fog(bgColor, 30, 100);
1292
+ }).catch(() => {});
1293
+ }
1294
+
1295
+ scene.background = new THREE.Color(bgColor);
1296
+ scene.fog = new THREE.Fog(bgColor, 30, 100);
1297
+
1298
+ const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 500);
1299
+ camera.position.set(8, 6, 12);
1300
+
1301
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
1302
+ renderer.setSize(innerWidth, innerHeight);
1303
+ renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
1304
+ renderer.shadowMap.enabled = true;
1305
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
1306
+ document.body.appendChild(renderer.domElement);
1307
+
1308
+ const controls = new OrbitControls(camera, renderer.domElement);
1309
+ controls.enableDamping = true;
1310
+
1311
+ scene.add(new THREE.AmbientLight(0x404060, 0.6));
1312
+ const sun = new THREE.DirectionalLight(0xffffff, 1.5);
1313
+ sun.position.set(10, 20, 10);
1314
+ sun.castShadow = true;
1315
+ sun.shadow.mapSize.set(1024, 1024);
1316
+ scene.add(sun);
1317
+
1318
+ const ground = new THREE.Mesh(
1319
+ new THREE.PlaneGeometry(60, 60),
1320
+ new THREE.MeshStandardMaterial({ color: 0x1a1a2e, roughness: 0.8 })
1321
+ );
1322
+ ground.rotation.x = -Math.PI / 2;
1323
+ ground.receiveShadow = true;
1324
+ scene.add(ground);
1325
+
1326
+ const shapes = [];
1327
+ const colors = [0x6366f1, 0x22c55e, 0xf59e0b, 0xef4444, 0x06b6d4];
1328
+
1329
+ for (let i = 0; i < 12; i++) {
1330
+ const geos = [
1331
+ new THREE.BoxGeometry(1, 1, 1),
1332
+ new THREE.SphereGeometry(0.6, 32, 32),
1333
+ new THREE.ConeGeometry(0.5, 1.2, 6),
1334
+ new THREE.TorusGeometry(0.5, 0.2, 16, 32),
1335
+ new THREE.OctahedronGeometry(0.6),
1336
+ ];
1337
+ const geo = geos[Math.floor(Math.random() * geos.length)];
1338
+ const mat = new THREE.MeshStandardMaterial({
1339
+ color: colors[Math.floor(Math.random() * colors.length)],
1340
+ roughness: 0.3, metalness: 0.5,
1341
+ });
1342
+ const mesh = new THREE.Mesh(geo, mat);
1343
+ mesh.position.set(
1344
+ (Math.random() - 0.5) * 16,
1345
+ 0.5 + Math.random() * 3,
1346
+ (Math.random() - 0.5) * 16
1347
+ );
1348
+ mesh.castShadow = true;
1349
+ mesh.userData = {
1350
+ baseY: mesh.position.y,
1351
+ phase: Math.random() * Math.PI * 2,
1352
+ rotSpeed: (Math.random() - 0.5) * 0.02,
1353
+ };
1354
+ scene.add(mesh);
1355
+ shapes.push(mesh);
1356
+ }
1357
+
1358
+ const clock = new THREE.Clock();
1359
+
1360
+ function animate() {
1361
+ requestAnimationFrame(animate);
1362
+ const t = clock.getElapsedTime();
1363
+
1364
+ for (const s of shapes) {
1365
+ s.position.y = s.userData.baseY + Math.sin(t + s.userData.phase) * 0.4;
1366
+ s.rotation.y += s.userData.rotSpeed;
1367
+ }
1368
+
1369
+ controls.update();
1370
+ renderer.render(scene, camera);
1371
+ }
1372
+ animate();
1373
+
1374
+ addEventListener('resize', () => {
1375
+ camera.aspect = innerWidth / innerHeight;
1376
+ camera.updateProjectionMatrix();
1377
+ renderer.setSize(innerWidth, innerHeight);
1378
+ });
1379
+ ```