@cloudgrid-io/mcp 0.13.0 → 0.15.0

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 (364) hide show
  1. package/package.json +1 -1
  2. package/src/corpus/capability-map.md +81 -7
  3. package/src/corpus/templates/_cloudgrid.yaml.reference +228 -0
  4. package/src/corpus/templates/admin-dashboard/cloudgrid.yaml +226 -8
  5. package/src/corpus/templates/admin-dashboard/index.md +3 -0
  6. package/src/corpus/templates/ai-app/cloudgrid.yaml +225 -11
  7. package/src/corpus/templates/ai-app/index.md +3 -11
  8. package/src/corpus/templates/ai-knowledge-base/AGENTS.md +254 -0
  9. package/src/corpus/templates/ai-knowledge-base/README.md +28 -0
  10. package/src/corpus/templates/ai-knowledge-base/cloudgrid.yaml +238 -0
  11. package/src/corpus/templates/ai-knowledge-base/index.md +81 -0
  12. package/src/corpus/templates/analytics-dashboard/README.md +85 -0
  13. package/src/corpus/templates/analytics-dashboard/cloudgrid.yaml +232 -0
  14. package/src/corpus/templates/analytics-dashboard/index.md +316 -0
  15. package/src/corpus/templates/analytics-dashboard/services/web/app/api/events/route.js +60 -0
  16. package/src/corpus/templates/analytics-dashboard/services/web/app/event-form.js +100 -0
  17. package/src/corpus/templates/analytics-dashboard/services/web/app/layout.js +41 -0
  18. package/src/corpus/templates/analytics-dashboard/services/web/app/page.js +54 -0
  19. package/src/corpus/templates/analytics-dashboard/services/web/lib/db.js +32 -0
  20. package/src/corpus/templates/analytics-dashboard/services/web/package.json +16 -0
  21. package/src/corpus/templates/api-dashboard/README.md +84 -0
  22. package/src/corpus/templates/api-dashboard/cloudgrid.yaml +233 -0
  23. package/src/corpus/templates/api-dashboard/index.md +310 -0
  24. package/src/corpus/templates/api-dashboard/services/web/app/api/requests/route.js +62 -0
  25. package/src/corpus/templates/api-dashboard/services/web/app/dashboard.js +156 -0
  26. package/src/corpus/templates/api-dashboard/services/web/app/layout.js +42 -0
  27. package/src/corpus/templates/api-dashboard/services/web/app/page.js +39 -0
  28. package/src/corpus/templates/api-dashboard/services/web/lib/db.js +32 -0
  29. package/src/corpus/templates/api-dashboard/services/web/package.json +16 -0
  30. package/src/corpus/templates/api-docs/cloudgrid.yaml +222 -4
  31. package/src/corpus/templates/api-docs/index.md +3 -5
  32. package/src/corpus/templates/api-service/cloudgrid.yaml +224 -9
  33. package/src/corpus/templates/api-service/index.md +3 -11
  34. package/src/corpus/templates/app-with-data/cloudgrid.yaml +226 -8
  35. package/src/corpus/templates/app-with-data/index.md +3 -8
  36. package/src/corpus/templates/appointment-booking/AGENTS.md +223 -0
  37. package/src/corpus/templates/appointment-booking/README.md +16 -0
  38. package/src/corpus/templates/appointment-booking/cloudgrid.yaml +250 -0
  39. package/src/corpus/templates/appointment-booking/index.md +72 -0
  40. package/src/corpus/templates/approval-workflow/AGENTS.md +170 -0
  41. package/src/corpus/templates/approval-workflow/README.md +12 -0
  42. package/src/corpus/templates/approval-workflow/cloudgrid.yaml +237 -0
  43. package/src/corpus/templates/approval-workflow/index.md +58 -0
  44. package/src/corpus/templates/billing-dashboard/AGENTS.md +199 -0
  45. package/src/corpus/templates/billing-dashboard/README.md +18 -0
  46. package/src/corpus/templates/billing-dashboard/cloudgrid.yaml +235 -0
  47. package/src/corpus/templates/billing-dashboard/index.md +87 -0
  48. package/src/corpus/templates/blog-cms/README.md +94 -0
  49. package/src/corpus/templates/blog-cms/cloudgrid.yaml +233 -0
  50. package/src/corpus/templates/blog-cms/index.md +358 -0
  51. package/src/corpus/templates/blog-cms/services/web/app/admin/admin-editor.js +133 -0
  52. package/src/corpus/templates/blog-cms/services/web/app/admin/page.js +33 -0
  53. package/src/corpus/templates/blog-cms/services/web/app/api/posts/route.js +84 -0
  54. package/src/corpus/templates/blog-cms/services/web/app/layout.js +47 -0
  55. package/src/corpus/templates/blog-cms/services/web/app/page.js +56 -0
  56. package/src/corpus/templates/blog-cms/services/web/app/posts/[slug]/page.js +45 -0
  57. package/src/corpus/templates/blog-cms/services/web/lib/db.js +32 -0
  58. package/src/corpus/templates/blog-cms/services/web/package.json +16 -0
  59. package/src/corpus/templates/booking-system/AGENTS.md +189 -0
  60. package/src/corpus/templates/booking-system/README.md +17 -0
  61. package/src/corpus/templates/booking-system/cloudgrid.yaml +248 -0
  62. package/src/corpus/templates/booking-system/index.md +86 -0
  63. package/src/corpus/templates/calendar-scheduler/AGENTS.md +226 -0
  64. package/src/corpus/templates/calendar-scheduler/README.md +25 -0
  65. package/src/corpus/templates/calendar-scheduler/cloudgrid.yaml +259 -0
  66. package/src/corpus/templates/calendar-scheduler/index.md +85 -0
  67. package/src/corpus/templates/changelog/cloudgrid.yaml +222 -4
  68. package/src/corpus/templates/changelog/index.md +3 -5
  69. package/src/corpus/templates/company-website/README.md +54 -0
  70. package/src/corpus/templates/company-website/cloudgrid.yaml +233 -0
  71. package/src/corpus/templates/company-website/index.html +309 -0
  72. package/src/corpus/templates/company-website/index.md +29 -0
  73. package/src/corpus/templates/course-platform/AGENTS.md +161 -0
  74. package/src/corpus/templates/course-platform/README.md +26 -0
  75. package/src/corpus/templates/course-platform/cloudgrid.yaml +237 -0
  76. package/src/corpus/templates/course-platform/index.md +70 -0
  77. package/src/corpus/templates/crm/cloudgrid.yaml +226 -8
  78. package/src/corpus/templates/crm/index.md +3 -0
  79. package/src/corpus/templates/dashboard/cloudgrid.yaml +228 -4
  80. package/src/corpus/templates/dashboard/index.md +3 -5
  81. package/src/corpus/templates/deck/cloudgrid.yaml +228 -4
  82. package/src/corpus/templates/deck/index.md +3 -5
  83. package/src/corpus/templates/directory/README.md +75 -0
  84. package/src/corpus/templates/directory/cloudgrid.yaml +233 -0
  85. package/src/corpus/templates/directory/index.md +334 -0
  86. package/src/corpus/templates/directory/services/web/app/api/entries/route.js +63 -0
  87. package/src/corpus/templates/directory/services/web/app/directory-list.js +146 -0
  88. package/src/corpus/templates/directory/services/web/app/layout.js +44 -0
  89. package/src/corpus/templates/directory/services/web/app/page.js +38 -0
  90. package/src/corpus/templates/directory/services/web/lib/db.js +32 -0
  91. package/src/corpus/templates/directory/services/web/package.json +16 -0
  92. package/src/corpus/templates/docs-site/cloudgrid.yaml +222 -4
  93. package/src/corpus/templates/docs-site/index.md +3 -5
  94. package/src/corpus/templates/erp/AGENTS.md +116 -0
  95. package/src/corpus/templates/erp/README.md +17 -0
  96. package/src/corpus/templates/erp/cloudgrid.yaml +235 -0
  97. package/src/corpus/templates/erp/index.md +81 -0
  98. package/src/corpus/templates/event-board/README.md +74 -0
  99. package/src/corpus/templates/event-board/cloudgrid.yaml +233 -0
  100. package/src/corpus/templates/event-board/index.md +299 -0
  101. package/src/corpus/templates/event-board/services/web/app/api/events/route.js +61 -0
  102. package/src/corpus/templates/event-board/services/web/app/event-form.js +118 -0
  103. package/src/corpus/templates/event-board/services/web/app/layout.js +39 -0
  104. package/src/corpus/templates/event-board/services/web/app/page.js +34 -0
  105. package/src/corpus/templates/event-board/services/web/lib/db.js +32 -0
  106. package/src/corpus/templates/event-board/services/web/package.json +16 -0
  107. package/src/corpus/templates/expense-tracker/README.md +76 -0
  108. package/src/corpus/templates/expense-tracker/cloudgrid.yaml +233 -0
  109. package/src/corpus/templates/expense-tracker/index.md +305 -0
  110. package/src/corpus/templates/expense-tracker/services/web/app/api/expenses/route.js +61 -0
  111. package/src/corpus/templates/expense-tracker/services/web/app/expense-form.js +145 -0
  112. package/src/corpus/templates/expense-tracker/services/web/app/layout.js +42 -0
  113. package/src/corpus/templates/expense-tracker/services/web/app/page.js +34 -0
  114. package/src/corpus/templates/expense-tracker/services/web/lib/db.js +32 -0
  115. package/src/corpus/templates/expense-tracker/services/web/package.json +16 -0
  116. package/src/corpus/templates/feature-request-board/README.md +87 -0
  117. package/src/corpus/templates/feature-request-board/cloudgrid.yaml +233 -0
  118. package/src/corpus/templates/feature-request-board/index.md +317 -0
  119. package/src/corpus/templates/feature-request-board/services/web/app/api/requests/route.js +92 -0
  120. package/src/corpus/templates/feature-request-board/services/web/app/board.js +91 -0
  121. package/src/corpus/templates/feature-request-board/services/web/app/layout.js +43 -0
  122. package/src/corpus/templates/feature-request-board/services/web/app/page.js +35 -0
  123. package/src/corpus/templates/feature-request-board/services/web/lib/db.js +32 -0
  124. package/src/corpus/templates/feature-request-board/services/web/package.json +16 -0
  125. package/src/corpus/templates/financial-dashboard/README.md +80 -0
  126. package/src/corpus/templates/financial-dashboard/cloudgrid.yaml +233 -0
  127. package/src/corpus/templates/financial-dashboard/index.md +326 -0
  128. package/src/corpus/templates/financial-dashboard/services/web/app/api/entries/route.js +63 -0
  129. package/src/corpus/templates/financial-dashboard/services/web/app/entry-board.js +130 -0
  130. package/src/corpus/templates/financial-dashboard/services/web/app/layout.js +46 -0
  131. package/src/corpus/templates/financial-dashboard/services/web/app/page.js +31 -0
  132. package/src/corpus/templates/financial-dashboard/services/web/lib/db.js +32 -0
  133. package/src/corpus/templates/financial-dashboard/services/web/package.json +16 -0
  134. package/src/corpus/templates/forum/AGENTS.md +196 -0
  135. package/src/corpus/templates/forum/README.md +12 -0
  136. package/src/corpus/templates/forum/cloudgrid.yaml +237 -0
  137. package/src/corpus/templates/forum/index.md +66 -0
  138. package/src/corpus/templates/hr-portal/AGENTS.md +174 -0
  139. package/src/corpus/templates/hr-portal/README.md +14 -0
  140. package/src/corpus/templates/hr-portal/cloudgrid.yaml +237 -0
  141. package/src/corpus/templates/hr-portal/index.md +56 -0
  142. package/src/corpus/templates/internal-tools-portal/AGENTS.md +201 -0
  143. package/src/corpus/templates/internal-tools-portal/README.md +17 -0
  144. package/src/corpus/templates/internal-tools-portal/cloudgrid.yaml +237 -0
  145. package/src/corpus/templates/internal-tools-portal/index.md +62 -0
  146. package/src/corpus/templates/inventory/README.md +71 -0
  147. package/src/corpus/templates/inventory/cloudgrid.yaml +233 -0
  148. package/src/corpus/templates/inventory/index.md +68 -0
  149. package/src/corpus/templates/inventory/services/web/app/api/items/route.js +88 -0
  150. package/src/corpus/templates/inventory/services/web/app/inventory-manager.js +101 -0
  151. package/src/corpus/templates/inventory/services/web/app/layout.js +36 -0
  152. package/src/corpus/templates/inventory/services/web/app/page.js +37 -0
  153. package/src/corpus/templates/inventory/services/web/lib/db.js +32 -0
  154. package/src/corpus/templates/inventory/services/web/package.json +16 -0
  155. package/src/corpus/templates/invoice/README.md +71 -0
  156. package/src/corpus/templates/invoice/cloudgrid.yaml +233 -0
  157. package/src/corpus/templates/invoice/index.md +68 -0
  158. package/src/corpus/templates/invoice/services/web/app/api/invoices/route.js +82 -0
  159. package/src/corpus/templates/invoice/services/web/app/invoice-manager.js +101 -0
  160. package/src/corpus/templates/invoice/services/web/app/layout.js +35 -0
  161. package/src/corpus/templates/invoice/services/web/app/page.js +34 -0
  162. package/src/corpus/templates/invoice/services/web/lib/db.js +32 -0
  163. package/src/corpus/templates/invoice/services/web/package.json +16 -0
  164. package/src/corpus/templates/job-board/README.md +71 -0
  165. package/src/corpus/templates/job-board/cloudgrid.yaml +233 -0
  166. package/src/corpus/templates/job-board/index.md +68 -0
  167. package/src/corpus/templates/job-board/services/web/app/api/jobs/route.js +66 -0
  168. package/src/corpus/templates/job-board/services/web/app/job-board.js +73 -0
  169. package/src/corpus/templates/job-board/services/web/app/layout.js +35 -0
  170. package/src/corpus/templates/job-board/services/web/app/page.js +32 -0
  171. package/src/corpus/templates/job-board/services/web/lib/db.js +32 -0
  172. package/src/corpus/templates/job-board/services/web/package.json +16 -0
  173. package/src/corpus/templates/kanban/cloudgrid.yaml +226 -8
  174. package/src/corpus/templates/kanban/index.md +3 -0
  175. package/src/corpus/templates/landing-page/cloudgrid.yaml +228 -4
  176. package/src/corpus/templates/landing-page/index.md +3 -5
  177. package/src/corpus/templates/lms/AGENTS.md +193 -0
  178. package/src/corpus/templates/lms/README.md +27 -0
  179. package/src/corpus/templates/lms/cloudgrid.yaml +237 -0
  180. package/src/corpus/templates/lms/index.md +79 -0
  181. package/src/corpus/templates/marketplace/AGENTS.md +208 -0
  182. package/src/corpus/templates/marketplace/README.md +22 -0
  183. package/src/corpus/templates/marketplace/cloudgrid.yaml +233 -0
  184. package/src/corpus/templates/marketplace/index.md +76 -0
  185. package/src/corpus/templates/membership-site/AGENTS.md +160 -0
  186. package/src/corpus/templates/membership-site/README.md +18 -0
  187. package/src/corpus/templates/membership-site/cloudgrid.yaml +236 -0
  188. package/src/corpus/templates/membership-site/index.md +66 -0
  189. package/src/corpus/templates/monitoring-dashboard/README.md +84 -0
  190. package/src/corpus/templates/monitoring-dashboard/cloudgrid.yaml +233 -0
  191. package/src/corpus/templates/monitoring-dashboard/index.md +328 -0
  192. package/src/corpus/templates/monitoring-dashboard/services/web/app/api/checks/route.js +76 -0
  193. package/src/corpus/templates/monitoring-dashboard/services/web/app/check-form.js +124 -0
  194. package/src/corpus/templates/monitoring-dashboard/services/web/app/layout.js +44 -0
  195. package/src/corpus/templates/monitoring-dashboard/services/web/app/page.js +49 -0
  196. package/src/corpus/templates/monitoring-dashboard/services/web/lib/db.js +32 -0
  197. package/src/corpus/templates/monitoring-dashboard/services/web/package.json +16 -0
  198. package/src/corpus/templates/online-store/AGENTS.md +153 -0
  199. package/src/corpus/templates/online-store/README.md +16 -0
  200. package/src/corpus/templates/online-store/cloudgrid.yaml +234 -0
  201. package/src/corpus/templates/online-store/index.md +81 -0
  202. package/src/corpus/templates/portfolio/cloudgrid.yaml +222 -4
  203. package/src/corpus/templates/portfolio/index.md +3 -5
  204. package/src/corpus/templates/product-catalog/README.md +74 -0
  205. package/src/corpus/templates/product-catalog/cloudgrid.yaml +232 -0
  206. package/src/corpus/templates/product-catalog/index.md +330 -0
  207. package/src/corpus/templates/product-catalog/services/web/app/api/products/route.js +69 -0
  208. package/src/corpus/templates/product-catalog/services/web/app/catalog.js +153 -0
  209. package/src/corpus/templates/product-catalog/services/web/app/layout.js +49 -0
  210. package/src/corpus/templates/product-catalog/services/web/app/page.js +36 -0
  211. package/src/corpus/templates/product-catalog/services/web/lib/db.js +32 -0
  212. package/src/corpus/templates/product-catalog/services/web/package.json +16 -0
  213. package/src/corpus/templates/product-launch/README.md +46 -0
  214. package/src/corpus/templates/product-launch/cloudgrid.yaml +234 -0
  215. package/src/corpus/templates/product-launch/index.html +320 -0
  216. package/src/corpus/templates/product-launch/index.md +34 -0
  217. package/src/corpus/templates/project-management/README.md +83 -0
  218. package/src/corpus/templates/project-management/cloudgrid.yaml +233 -0
  219. package/src/corpus/templates/project-management/index.md +346 -0
  220. package/src/corpus/templates/project-management/services/web/app/api/projects/route.js +48 -0
  221. package/src/corpus/templates/project-management/services/web/app/api/tasks/route.js +85 -0
  222. package/src/corpus/templates/project-management/services/web/app/board.js +182 -0
  223. package/src/corpus/templates/project-management/services/web/app/layout.js +45 -0
  224. package/src/corpus/templates/project-management/services/web/app/page.js +49 -0
  225. package/src/corpus/templates/project-management/services/web/lib/db.js +32 -0
  226. package/src/corpus/templates/project-management/services/web/package.json +16 -0
  227. package/src/corpus/templates/property-listings/README.md +76 -0
  228. package/src/corpus/templates/property-listings/cloudgrid.yaml +233 -0
  229. package/src/corpus/templates/property-listings/index.md +335 -0
  230. package/src/corpus/templates/property-listings/services/web/app/api/properties/route.js +73 -0
  231. package/src/corpus/templates/property-listings/services/web/app/layout.js +45 -0
  232. package/src/corpus/templates/property-listings/services/web/app/listings.js +152 -0
  233. package/src/corpus/templates/property-listings/services/web/app/page.js +53 -0
  234. package/src/corpus/templates/property-listings/services/web/lib/db.js +32 -0
  235. package/src/corpus/templates/property-listings/services/web/package.json +16 -0
  236. package/src/corpus/templates/quiz-platform/README.md +84 -0
  237. package/src/corpus/templates/quiz-platform/cloudgrid.yaml +233 -0
  238. package/src/corpus/templates/quiz-platform/index.md +313 -0
  239. package/src/corpus/templates/quiz-platform/services/web/app/api/questions/route.js +69 -0
  240. package/src/corpus/templates/quiz-platform/services/web/app/layout.js +47 -0
  241. package/src/corpus/templates/quiz-platform/services/web/app/page.js +37 -0
  242. package/src/corpus/templates/quiz-platform/services/web/app/quiz.js +188 -0
  243. package/src/corpus/templates/quiz-platform/services/web/lib/db.js +32 -0
  244. package/src/corpus/templates/quiz-platform/services/web/package.json +16 -0
  245. package/src/corpus/templates/report/cloudgrid.yaml +228 -4
  246. package/src/corpus/templates/report/index.md +3 -5
  247. package/src/corpus/templates/restaurant-reservations/AGENTS.md +258 -0
  248. package/src/corpus/templates/restaurant-reservations/README.md +17 -0
  249. package/src/corpus/templates/restaurant-reservations/cloudgrid.yaml +258 -0
  250. package/src/corpus/templates/restaurant-reservations/index.md +62 -0
  251. package/src/corpus/templates/revenue-dashboard/README.md +75 -0
  252. package/src/corpus/templates/revenue-dashboard/cloudgrid.yaml +233 -0
  253. package/src/corpus/templates/revenue-dashboard/index.md +307 -0
  254. package/src/corpus/templates/revenue-dashboard/services/web/app/api/sales/route.js +60 -0
  255. package/src/corpus/templates/revenue-dashboard/services/web/app/layout.js +40 -0
  256. package/src/corpus/templates/revenue-dashboard/services/web/app/page.js +87 -0
  257. package/src/corpus/templates/revenue-dashboard/services/web/app/sale-form.js +63 -0
  258. package/src/corpus/templates/revenue-dashboard/services/web/lib/db.js +32 -0
  259. package/src/corpus/templates/revenue-dashboard/services/web/package.json +16 -0
  260. package/src/corpus/templates/saas-marketing/cloudgrid.yaml +222 -4
  261. package/src/corpus/templates/saas-marketing/index.md +3 -5
  262. package/src/corpus/templates/semantic-search/AGENTS.md +192 -0
  263. package/src/corpus/templates/semantic-search/README.md +74 -0
  264. package/src/corpus/templates/semantic-search/cloudgrid.yaml +217 -0
  265. package/src/corpus/templates/semantic-search/index.md +97 -0
  266. package/src/corpus/templates/semantic-search/services/backend/requirements.txt +7 -0
  267. package/src/corpus/templates/semantic-search/services/backend/src/app/__init__.py +0 -0
  268. package/src/corpus/templates/semantic-search/services/backend/src/app/answer.py +90 -0
  269. package/src/corpus/templates/semantic-search/services/backend/src/app/auth.py +65 -0
  270. package/src/corpus/templates/semantic-search/services/backend/src/app/config.py +110 -0
  271. package/src/corpus/templates/semantic-search/services/backend/src/app/db.py +89 -0
  272. package/src/corpus/templates/semantic-search/services/backend/src/app/embeddings.py +44 -0
  273. package/src/corpus/templates/semantic-search/services/backend/src/app/indexing.py +222 -0
  274. package/src/corpus/templates/semantic-search/services/backend/src/app/main.py +259 -0
  275. package/src/corpus/templates/semantic-search/services/backend/src/app/search.py +222 -0
  276. package/src/corpus/templates/semantic-search/services/backend/src/app/source.py +259 -0
  277. package/src/corpus/templates/semantic-search/services/backend/src/main.py +12 -0
  278. package/src/corpus/templates/semantic-search/services/web/index.html +12 -0
  279. package/src/corpus/templates/semantic-search/services/web/package-lock.json +1680 -0
  280. package/src/corpus/templates/semantic-search/services/web/package.json +19 -0
  281. package/src/corpus/templates/semantic-search/services/web/src/App.jsx +55 -0
  282. package/src/corpus/templates/semantic-search/services/web/src/api.js +125 -0
  283. package/src/corpus/templates/semantic-search/services/web/src/components/Dashboard.jsx +61 -0
  284. package/src/corpus/templates/semantic-search/services/web/src/components/ManagerLogin.jsx +39 -0
  285. package/src/corpus/templates/semantic-search/services/web/src/components/SearchView.jsx +166 -0
  286. package/src/corpus/templates/semantic-search/services/web/src/components/Settings.jsx +148 -0
  287. package/src/corpus/templates/semantic-search/services/web/src/main.jsx +10 -0
  288. package/src/corpus/templates/semantic-search/services/web/src/styles.css +78 -0
  289. package/src/corpus/templates/semantic-search/services/web/vite.config.js +10 -0
  290. package/src/corpus/templates/status-page/cloudgrid.yaml +222 -4
  291. package/src/corpus/templates/status-page/index.md +3 -5
  292. package/src/corpus/templates/subscription-management/AGENTS.md +191 -0
  293. package/src/corpus/templates/subscription-management/README.md +21 -0
  294. package/src/corpus/templates/subscription-management/cloudgrid.yaml +236 -0
  295. package/src/corpus/templates/subscription-management/index.md +73 -0
  296. package/src/corpus/templates/task-manager/cloudgrid.yaml +226 -8
  297. package/src/corpus/templates/task-manager/index.md +3 -0
  298. package/src/corpus/templates/ticket-system/README.md +71 -0
  299. package/src/corpus/templates/ticket-system/cloudgrid.yaml +233 -0
  300. package/src/corpus/templates/ticket-system/index.md +68 -0
  301. package/src/corpus/templates/ticket-system/services/web/app/api/tickets/route.js +81 -0
  302. package/src/corpus/templates/ticket-system/services/web/app/layout.js +36 -0
  303. package/src/corpus/templates/ticket-system/services/web/app/page.js +35 -0
  304. package/src/corpus/templates/ticket-system/services/web/app/ticket-queue.js +112 -0
  305. package/src/corpus/templates/ticket-system/services/web/lib/db.js +32 -0
  306. package/src/corpus/templates/ticket-system/services/web/package.json +16 -0
  307. package/src/corpus/templates/time-tracking/README.md +81 -0
  308. package/src/corpus/templates/time-tracking/cloudgrid.yaml +233 -0
  309. package/src/corpus/templates/time-tracking/index.md +298 -0
  310. package/src/corpus/templates/time-tracking/services/web/app/api/entries/route.js +66 -0
  311. package/src/corpus/templates/time-tracking/services/web/app/entry-form.js +106 -0
  312. package/src/corpus/templates/time-tracking/services/web/app/layout.js +39 -0
  313. package/src/corpus/templates/time-tracking/services/web/app/page.js +30 -0
  314. package/src/corpus/templates/time-tracking/services/web/lib/db.js +32 -0
  315. package/src/corpus/templates/time-tracking/services/web/package.json +16 -0
  316. package/src/corpus/templates/travel-booking/AGENTS.md +207 -0
  317. package/src/corpus/templates/travel-booking/README.md +17 -0
  318. package/src/corpus/templates/travel-booking/cloudgrid.yaml +249 -0
  319. package/src/corpus/templates/travel-booking/index.md +88 -0
  320. package/src/corpus/templates/waitlist/cloudgrid.yaml +222 -4
  321. package/src/corpus/templates/waitlist/index.md +3 -5
  322. package/src/corpus/templates/web-app/cloudgrid.yaml +228 -4
  323. package/src/corpus/templates/web-app/index.md +3 -5
  324. package/src/corpus/workflows/ai-knowledge-base.md +137 -0
  325. package/src/corpus/workflows/analytics-dashboard.md +104 -0
  326. package/src/corpus/workflows/api-dashboard.md +102 -0
  327. package/src/corpus/workflows/appointment-booking.md +143 -0
  328. package/src/corpus/workflows/approval-workflow.md +124 -0
  329. package/src/corpus/workflows/billing-dashboard.md +120 -0
  330. package/src/corpus/workflows/blog-cms.md +104 -0
  331. package/src/corpus/workflows/booking-system.md +116 -0
  332. package/src/corpus/workflows/calendar-scheduler.md +134 -0
  333. package/src/corpus/workflows/company-website.md +46 -0
  334. package/src/corpus/workflows/course-platform.md +126 -0
  335. package/src/corpus/workflows/directory.md +101 -0
  336. package/src/corpus/workflows/erp.md +125 -0
  337. package/src/corpus/workflows/event-board.md +102 -0
  338. package/src/corpus/workflows/expense-tracker.md +102 -0
  339. package/src/corpus/workflows/feature-request-board.md +105 -0
  340. package/src/corpus/workflows/financial-dashboard.md +103 -0
  341. package/src/corpus/workflows/forum.md +128 -0
  342. package/src/corpus/workflows/hr-portal.md +115 -0
  343. package/src/corpus/workflows/internal-tools-portal.md +125 -0
  344. package/src/corpus/workflows/inventory.md +101 -0
  345. package/src/corpus/workflows/invoice.md +101 -0
  346. package/src/corpus/workflows/job-board.md +101 -0
  347. package/src/corpus/workflows/lms.md +113 -0
  348. package/src/corpus/workflows/marketplace.md +123 -0
  349. package/src/corpus/workflows/membership-site.md +128 -0
  350. package/src/corpus/workflows/monitoring-dashboard.md +104 -0
  351. package/src/corpus/workflows/online-store.md +114 -0
  352. package/src/corpus/workflows/product-catalog.md +105 -0
  353. package/src/corpus/workflows/product-launch.md +43 -0
  354. package/src/corpus/workflows/project-management.md +106 -0
  355. package/src/corpus/workflows/property-listings.md +101 -0
  356. package/src/corpus/workflows/quiz-platform.md +105 -0
  357. package/src/corpus/workflows/restaurant-reservations.md +123 -0
  358. package/src/corpus/workflows/revenue-dashboard.md +102 -0
  359. package/src/corpus/workflows/semantic-search.md +133 -0
  360. package/src/corpus/workflows/subscription-management.md +141 -0
  361. package/src/corpus/workflows/ticket-system.md +101 -0
  362. package/src/corpus/workflows/time-tracking.md +104 -0
  363. package/src/corpus/workflows/travel-booking.md +115 -0
  364. package/src/tools.js +73 -12
@@ -1,10 +1,228 @@
1
- # static — deploys as an inspiration (instant, works on hosted) via gridctl_drop;
2
- # this yaml is only for plugging it as an OWNED static runtime (async, local
3
- # edition only). To publish the page, prefer gridctl_drop, not grid plug.
1
+ # ============================================================================
2
+ # cloudgrid.yaml — Complete Example
3
+ # ============================================================================
4
4
  #
5
- # needs: {} # none — static, no infrastructure
5
+ # This file shows EVERY field the platform supports, with comments explaining
6
+ # each one. It is a reference — no real project would use all of these at once.
7
+ #
8
+ # STANDARD: every CloudGrid template ships its cloudgrid.yaml in THIS full form.
9
+ # Uncomment ONLY the fields the archetype needs (always: name + services; plus
10
+ # needs: for runtime apps). Leave everything else commented. Comments are
11
+ # ignored by the parser, so the file deploys to exactly the active fields.
12
+ #
13
+ # Only two fields are required: name and services. Everything else is optional.
14
+ # Full docs: docs/cloudgrid-yaml-reference.md
15
+ # ============================================================================
16
+
17
+
18
+ # ─── IDENTITY ───────────────────────────────────────────────────────────────
19
+
20
+ # Entity slug (REQUIRED). 2-42 chars, lowercase alphanumeric + hyphens.
21
+ # Must start and end with a letter or digit.
22
+ # Becomes part of your public URL: <name>-<4hex>.<org>.cloudgrid.io
6
23
  name: saas-marketing
24
+
25
+ # One-line summary. Max 280 chars. If omitted, Grid Brain auto-generates one.
26
+ # description: Order processing API for the e-commerce platform
27
+
28
+ # Single emoji or short text shown as the entity icon. Max 64 chars.
29
+ # icon: "📦"
30
+
31
+ # Entity type: 'app' (default) or 'agent'. An agent is an app with an agent: block.
32
+ # kind: app
33
+
34
+
35
+ # ─── NETWORKING ─────────────────────────────────────────────────────────────
36
+
37
+ # Whether this entity serves public HTTP traffic.
38
+ # true = public URL + Ingress (default). false = internal only.
39
+ # expose: true
40
+
41
+ # Additional domain names this entity serves on (the platform URL is always active).
42
+ # custom_domains:
43
+ # - orders.example.com
44
+ # - shop.example.com
45
+
46
+
47
+ # ─── HEALTH PROBE (entity-level override) ──────────────────────────────────
48
+
49
+ # Override the default health check for the entire entity.
50
+ # probe:
51
+ # path: /healthz # HTTP path to probe (default: /).
52
+ # expected: "<500" # '<500' (default), '200', '2xx'.
53
+
54
+
55
+ # ─── DEPLOY NOTIFICATIONS ──────────────────────────────────────────────────
56
+
57
+ # Slack notification to the org's default channel on deploy failure.
58
+ # true = notify (default), false = silent.
59
+ # notify: true
60
+
61
+
62
+ # ─── SCALING ────────────────────────────────────────────────────────────────
63
+
64
+ # Replica scaling intent.
65
+ # 'auto' — platform decides from the grid tier (default).
66
+ # 'alert' — single-replica, emit a SPOF warning at plug time.
67
+ # 1-10 — explicit replica count, clamped to the grid max.
68
+ # scale: auto
69
+
70
+
71
+ # ─── INFRASTRUCTURE NEEDS ──────────────────────────────────────────────────
72
+ #
73
+ # Declare infrastructure; the platform provisions it and injects connection
74
+ # details as env vars. Nine needs: database, cache, kv, queue, pubsub, vector,
75
+ # object_storage, disk, ai. Simplest form is `true`.
76
+ #
77
+ # needs:
78
+ # # database — MongoDB. Injects DATABASE_MONGODB_URL (+ legacy MONGODB_URL).
79
+ # # true | pool | dedicated | { tier: external, secret: MY_DB }
80
+ # database: true
81
+ # # cache — Redis, LRU eviction (derived data). Injects CACHE_REDIS_URL (+ REDIS_URL).
82
+ # # true | redis | { engine: external, secret: MY_REDIS_URL }
83
+ # cache: true
84
+ # # kv — Redis, no eviction (durable: flags, idempotency). Injects KV_REDIS_URL.
85
+ # kv: true
86
+ # # queue — Redis job-queue substrate (BullMQ). Injects QUEUE_REDIS_URL.
87
+ # queue: true
88
+ # # pubsub — Redis broadcast pub/sub. Injects PUBSUB_REDIS_URL.
89
+ # pubsub: true
90
+ # # vector — pgvector on Postgres. Injects VECTOR_PGVECTOR_URL (+ PGVECTOR_URL).
91
+ # # true | pgvector | { engine: pgvector, dim: 1536 }
92
+ # vector: pgvector
93
+ # # object_storage — GCS bucket. Injects OBJECT_STORAGE_GCS_BUCKET, _GCS_REGION.
94
+ # # true | { size: 10Gi }
95
+ # object_storage: true
96
+ # # disk — persistent FS mount (PVC). Injects DISK_PATH. Pins to 1 replica.
97
+ # # true | { size: 1Gi, mount: /var/data } (forbidden: /proc /sys /dev)
98
+ # disk: true
99
+ # # ai — AI Gateway via @cloudgrid-io/ai. Injects AI_GATEWAY_URL. true | false.
100
+ # ai: true
101
+
102
+
103
+ # ─── INTER-ENTITY COMMUNICATION ────────────────────────────────────────────
104
+
105
+ # Entities this app calls (outbound). Service-account token injected per pair.
106
+ # calls:
107
+ # - org:atomic/billing-api
108
+
109
+ # Inbound caller policy — who can call YOUR entity.
110
+ # callers:
111
+ # policy: auto # 'auto' | 'manual' (default).
112
+ # scope: org # 'org' (default) | 'space' | 'explicit'.
113
+ # fallback: deny # 'deny' (default) | 'warn'.
114
+ # # allowed_apps: # required only when scope: explicit
115
+ # # - org:atomic/frontend
116
+
117
+
118
+ # ─── VAULT ──────────────────────────────────────────────────────────────────
119
+
120
+ # Map org vault items to env vars. Keys UPPER_SNAKE_CASE; values = vault item keys.
121
+ # vault:
122
+ # STRIPE_KEY: stripe-live-key
123
+ # SENDGRID_API_KEY: sendgrid-key
124
+
125
+
126
+ # ─── CONNECTORS AND HOOKS ──────────────────────────────────────────────────
127
+
128
+ # connectors:
129
+ # - id: team-slack
130
+ # target: org # 'system' | 'org'.
131
+ # channel: "#deploys"
132
+ # hooks:
133
+ # - on: deploy.failed # release.published | deploy.failed | feedback.received | entity.created
134
+ # via: team-slack
135
+ # template: "Deploy failed for {entity_name}: {error}"
136
+ # channel: "#alerts"
137
+ # triggers:
138
+ # - from: team-slack
139
+ # event: message
140
+ # channel: "#support"
141
+ # route: /webhooks/slack
142
+
143
+
144
+ # ─── LOCAL DEVELOPMENT ──────────────────────────────────────────────────────
145
+
146
+ # Config for `grid dev`. Redact fields in dev data snapshots.
147
+ # dev:
148
+ # snapshot:
149
+ # mask:
150
+ # - users.email
151
+ # - users.phone
152
+
153
+
154
+ # ─── AGENT METADATA ────────────────────────────────────────────────────────
155
+
156
+ # An agent is an app with kind: agent (above) and an agent: block.
157
+ # agent:
158
+ # purpose: Sync customer data from external CRM every night
159
+ # schedule: "0 2 * * *"
160
+ # trigger: webhook
161
+
162
+
163
+ # ─── PRIVATE RESOURCE AUTO-DEPENDENCIES ────────────────────────────────────
164
+
165
+ # When true (default), private resources are auto-injected as depends_on.
166
+ # auto_depends_on_private_requires: true
167
+
168
+
169
+ # ─── SERVICES (REQUIRED) ───────────────────────────────────────────────────
170
+ #
171
+ # At least one service is required. Key = service name (slug rules).
172
+ # Types: node, nextjs, python, static, cron.
173
+ #
7
174
  services:
8
175
  web:
176
+ # type (REQUIRED): node | nextjs | python | static | cron
9
177
  type: static
178
+ # HTTP route: '/' | '/api' | false (internal) | omitted (=false + warning).
179
+ # Only one service per entity can claim '/'.
10
180
  path: /
181
+ # Container port (default 8080; read process.env.PORT). Not for cron.
182
+ # port: 3000
183
+ # nextjs only: base_image: distroless (default) | alpine
184
+ # base_image: distroless
185
+ # node only: lang: javascript (default) | typescript
186
+ # lang: typescript
187
+ # Custom source location (default services/<name>/). '.' = project root.
188
+ # source:
189
+ # path: src/worker
190
+ # Health probe: false/omitted (TCP) | true (/health) | "/path" | {path,expected}
191
+ # health:
192
+ # path: /api/health
193
+ # expected: "200"
194
+ # Static runtime env vars (strings). Reserved: PORT, APP_NAME, SERVICE_NAME,
195
+ # NODE_ENV, MONGODB_URL, REDIS_URL, AI_GATEWAY_URL, N8N_WEBHOOK_URL, CLOUDGRID_*.
196
+ # env:
197
+ # LOG_LEVEL: info
198
+ # Sibling services/private resources that must be Ready first (no cron, no cycles).
199
+ # depends_on:
200
+ # - worker
201
+ # Per-service needs override (merges with app-level needs).
202
+ # needs:
203
+ # queue: true
204
+ # Static-only build step:
205
+ # build:
206
+ # command: npm run build
207
+ # output: dist
208
+ # env:
209
+ # VITE_API_URL: https://api.example.com
210
+ # node_version: "22" # static build step: '18'|'20'|'22'|'24' (quoted)
211
+ # Cron-only: schedule (REQUIRED), timezone (UTC|EST|PST), run (job | https URL)
212
+ # schedule: "0 9 * * 1"
213
+ # timezone: UTC
214
+ # run: job
215
+ # Verbose per-service persistence (prefer needs.disk):
216
+ # persist:
217
+ # - name: scratch
218
+ # path: /tmp/scratch
219
+ # size: 500Mi
220
+
221
+
222
+ # ============================================================================
223
+ # NOTES
224
+ # - NOT here: org:/entity_id: (→ .cloudgrid/link.json), secrets (→ grid secrets set),
225
+ # Dockerfile (platform generates from services.*.type).
226
+ # - Deploy: grid plug | Local with grid resources: grid dev
227
+ # - Full reference: docs/cloudgrid-yaml-reference.md | CLI: docs/cli-reference.md
228
+ # ============================================================================
@@ -17,11 +17,9 @@ The fillable HTML is the real template — fetch it with
17
17
  ## cloudgrid.yaml (reference only)
18
18
 
19
19
  ```yaml
20
- # static — deploys as an inspiration (instant, works on hosted) via gridctl_drop;
21
- # this yaml is only for plugging it as an OWNED static runtime (async, local
22
- # edition only). To publish the page, prefer gridctl_drop, not grid plug.
23
- #
24
- # needs: {} # none — static, no infrastructure
20
+ # On disk this file is the full-annotated reference (templates/_cloudgrid.yaml.reference) with EVERY
21
+ # field present as a comment; only the fields below are uncommented, so it
22
+ # deploys to exactly these active fields.
25
23
  name: saas-marketing
26
24
  services:
27
25
  web:
@@ -0,0 +1,192 @@
1
+ # AGENTS.md — semantic-search template (CloudGrid wiring guide)
2
+
3
+ This template is a **runnable app**, not a blueprint — it ships real FastAPI +
4
+ React code. Read this guide, adapt the naming/metadata to the user's domain, wire
5
+ the secrets, and deploy. The four "baked-in learnings" (health-without-secrets,
6
+ startup index, `$text` guard, no vector/no cron) are already in the code — do not
7
+ regress them.
8
+
9
+ ---
10
+
11
+ ## 1. File tree
12
+
13
+ Every service's code lives under `services/<name>/` — `path:` in `cloudgrid.yaml`
14
+ is the URL mount, NOT the filesystem path. Files at the repo root fail with
15
+ `Error: Service directory not found: …/services/<name>`.
16
+
17
+ ```
18
+ cloudgrid.yaml # name + services(web,backend) + needs:{database:true}
19
+ services/web/ # React + Vite static frontend, served at /
20
+ package.json vite.config.js index.html
21
+ src/main.jsx App.jsx api.js styles.css
22
+ src/components/SearchView.jsx ManagerLogin.jsx Settings.jsx Dashboard.jsx
23
+ services/backend/ # FastAPI, mounted at /backend
24
+ requirements.txt
25
+ src/main.py # uvicorn app.main:app (reads PORT)
26
+ src/app/
27
+ main.py config.py db.py search.py indexing.py
28
+ source.py embeddings.py answer.py auth.py
29
+ ```
30
+
31
+ ---
32
+
33
+ ## 2. Mongo collections + fields
34
+
35
+ The grid provisions one MongoDB database (`needs: { database: true }`). Two
36
+ primary collections (`_id` is the Mongo ObjectId on every doc):
37
+
38
+ **`documents`** — one row per source document
39
+ - `title` (string), `collection` (string, free-form grouping tag, nullable),
40
+ `date` (ISO date string, nullable) — the metadata filters.
41
+ - `source_filename` (string, unique), `source_rev` (string — content hash / rev
42
+ for incremental sync), `file_path` (string, source-internal, never exposed).
43
+ - `has_media` (bool), `word_count` (int), `indexed_at` (Date).
44
+
45
+ **`chunks`** — one embeddable passage per document (the retrieval unit)
46
+ - `document_id` (ObjectId → documents), `chunk_index` (int),
47
+ - `content` (string — indexed by the `$text` index, returned as the passage),
48
+ - `embedding` (float[] — the semantic vector; `null` if embeddings unconfigured).
49
+
50
+ Support collections: `settings` (feature flags, synonyms, `catalog.last_refresh`),
51
+ `usage_events`, `index_reports`, `sessions`.
52
+
53
+ **Adapt the metadata to the domain:** rename/extend `collection` and `date` in
54
+ `indexing.py::_parse_metadata`, and mirror the field names in `search.py`,
55
+ `main.py`, and the web `SearchView`.
56
+
57
+ ---
58
+
59
+ ## 3. How CloudGrid injects the datastore
60
+
61
+ You never provision infra or set a connection string by hand. `needs:{database:
62
+ true}` provisions Mongo and injects it as an env var at `grid dev` (local) and at
63
+ runtime (after `grid plug`):
64
+
65
+ | What | Declared in cloudgrid.yaml | Injected env var(s) | Read in code |
66
+ |------|----------------------------|---------------------|--------------|
67
+ | MongoDB | `needs: { database: true }` | `DATABASE_MONGODB_URL` (+ legacy `MONGODB_URL`) | `app/db.py::get_client` (lazy) |
68
+
69
+ Read it LAZILY — `os.environ.get("DATABASE_MONGODB_URL") or
70
+ os.environ.get("MONGODB_URL")` inside `get_client()`, never at module top level.
71
+ `requires:` is the deprecated v1 alias; never author it and never set `needs:` and
72
+ `requires:` together (the validator rejects the combination).
73
+
74
+ **No `needs: vector`.** The ideal embedding store is pgvector
75
+ (`needs: { vector: pgvector }` → `VECTOR_PGVECTOR_URL`), but the runtime
76
+ role-grant is **blocked on platform issue #1545**. Until it lands, embeddings live
77
+ in the Mongo `chunks.embedding` float array and are cosine-ranked in-app
78
+ (`search.py::_cosine`). When #1545 ships, move the vectors to pgvector and replace
79
+ the in-app cosine block with an `ORDER BY embedding <=> $q LIMIT k` query — the
80
+ rest of the pipeline is unchanged.
81
+
82
+ ---
83
+
84
+ ## 4. Pluggable document source (SOURCE_TYPE)
85
+
86
+ The source is where raw documents live, not the query DB. `SOURCE_TYPE` selects
87
+ the adapter in `app/source.py`; all creds are gated in `app/config.py` and read
88
+ lazily:
89
+
90
+ - **`dropbox`** (default) — read-only, offline refresh-token flow. Secrets:
91
+ `DROPBOX_APP_KEY`, `DROPBOX_APP_SECRET`, `DROPBOX_REFRESH_TOKEN`,
92
+ `DROPBOX_FOLDER_PATH` (optional).
93
+ - **`local`** — a directory on the container filesystem. Set `LOCAL_SOURCE_PATH`
94
+ (or add `needs: { disk: true }` and it defaults to the injected `DISK_PATH`).
95
+ - **`url`** — a manifest of document URLs. Set `URL_SOURCE_MANIFEST` to a
96
+ newline- or comma-separated list.
97
+
98
+ **Add your own adapter:** subclass `Source` (implement `list_files()` returning
99
+ `SourceFile[]` and `download(path) -> bytes`), gate its config in
100
+ `config.py::source_configured`, and return it from `get_source()`. Text
101
+ extraction for txt/md/pdf/docx is shared in `source.extract_text`.
102
+
103
+ ---
104
+
105
+ ## 5. Embeddings (one config point)
106
+
107
+ `app/embeddings.py` is the single provider seam — OpenAI-compatible by default.
108
+ Secrets/config (all gated, read lazily):
109
+
110
+ - `EMBEDDINGS_API_KEY` — the key (semantic search + generated answers degrade
111
+ gracefully to lexical/extractive when unset).
112
+ - `EMBEDDINGS_MODEL` (default `text-embedding-3-small`) — changing it changes
113
+ vector dimensions and requires a full reindex.
114
+ - `EMBEDDINGS_BASE_URL` (default `https://api.openai.com/v1`) — point at any
115
+ OpenAI-compatible endpoint.
116
+ - `ANSWER_MODEL` (default `gpt-4o-mini`) — the grounded-answer chat model.
117
+
118
+ ---
119
+
120
+ ## 6. Secrets via `grid secrets set`
121
+
122
+ Store secrets with the CLI; never commit them, never read them at import time:
123
+
124
+ ```bash
125
+ grid secrets set EMBEDDINGS_API_KEY=sk-...
126
+ grid secrets set SOURCE_TYPE=dropbox
127
+ grid secrets set DROPBOX_APP_KEY=... DROPBOX_APP_SECRET=... DROPBOX_REFRESH_TOKEN=...
128
+ grid secrets set MANAGER_PASSWORD_HASH=$(printf '%s' 'your-password' | shasum -a 256 | cut -d' ' -f1)
129
+ ```
130
+
131
+ `MANAGER_PASSWORD_HASH` is the sha256 hex of the manager password, compared
132
+ server-side in `auth.py`. The in-app "Change password" screen returns a new hash
133
+ to store the same way. Non-secret public config can also go via `grid env`.
134
+
135
+ ---
136
+
137
+ ## 7. The baked-in learnings (do NOT regress)
138
+
139
+ 1. **Startup index.** `main.py` has `@app.on_event("startup")` →
140
+ `db.ensure_indexes()`, which creates the chunks `$text` index (plus the
141
+ documents metadata indexes) at boot. Without it, `$text` raises
142
+ `IndexNotFound` (a 500) on an empty catalog. `ensure_indexes()` is safe to call
143
+ repeatedly and never blocks startup if Mongo is briefly unavailable.
144
+ 2. **`$text` guard.** The lexical query in `search.py` is wrapped in
145
+ `except OperationFailure` so a missing index degrades to "lexical contributes
146
+ nothing", never a 500 — belt-and-suspenders on top of the startup index.
147
+ 3. **Health without secrets.** No secret is read at import time; every secret is
148
+ gated inside a function (`config.py`). `GET /backend/health` needs only Mongo.
149
+ Search/indexing degrade gracefully (empty results + a clear note) when the
150
+ source or embeddings are unconfigured. `GET /backend/status` reports capability
151
+ **booleans** (`source_configured`, `embeddings_configured`, …), never secret
152
+ values.
153
+ 4. **No `needs: vector` / no active cron.** `needs:` is `database` only (#1545).
154
+ The cron refresh service is commented out (#1585) — see §8.
155
+
156
+ ---
157
+
158
+ ## 8. Refresh: manager endpoint now, cron later
159
+
160
+ The supported refresh path today is the manager-only endpoint
161
+ `POST /backend/admin/refresh` (wired to the "Refresh now" button in Settings). It
162
+ runs the same incremental sync pipeline (`indexing.run_sync`) a cron would.
163
+
164
+ A scheduled `type: cron` refresh service is a **follow-up**: a Python cron entity
165
+ is currently blocked on **platform issue #1585**. The `cloudgrid.yaml` keeps a
166
+ `refresh:` cron service commented out with a `services/refresh` source pointing at
167
+ the same `indexing.run_sync`. When #1585 lands, uncomment it (`schedule`,
168
+ `timezone`, `run: job`) and add a thin `services/refresh/src/main.py` that calls
169
+ `app.indexing.run_sync(triggered_by="cron")`.
170
+
171
+ ---
172
+
173
+ ## 9. Deploy + edition note
174
+
175
+ This is a built + deployed multi-service app → the **local edition** (Claude
176
+ Desktop / Claude Code) or the CLI; the hosted edition cannot build a runtime
177
+ container.
178
+
179
+ 1. `grid init semantic-search` — creates the entity + `.cloudgrid/link.json`.
180
+ 2. Put the code under `services/web/` and `services/backend/`; set `cloudgrid.yaml`
181
+ to the active fields (web static+build, backend python, `needs:{database:true}`).
182
+ 3. `grid secrets set …` for embeddings + source + `MANAGER_PASSWORD_HASH` (§6).
183
+ 4. (Optional) `grid dev` to run locally against injected dev Mongo.
184
+ 5. **Build the frontend first:** `(cd services/web && npm install && npm run build)`.
185
+ CloudGrid validates that a `type: static` service carrying a `build:` block
186
+ already has `services/web/dist/index.html` on disk at plug time — plug fails
187
+ validation otherwise.
188
+ 6. `grid plug` — a runtime deploy is **ASYNC**: the first response is
189
+ `status: building`, not a live URL. Poll `grid status` (surface a liveness
190
+ signal, never a bare wait) until Ready.
191
+ 7. Sign in as manager, hit "Refresh now" to index the source, then search.
192
+ Re-plug the same entity to update the same URL.
@@ -0,0 +1,74 @@
1
+ # semantic-search template — CloudGrid-native document search
2
+
3
+ A deployable, domain-agnostic **document search** app: index a folder of
4
+ documents (PDF / DOCX / TXT / MD), then search them by keyword, by meaning, and
5
+ by metadata — with a grounded answer mode and a manager admin. Data lives in the
6
+ grid-shared MongoDB, so the catalog survives refresh and is shared across users.
7
+
8
+ **Hybrid search** = Mongo `$text` (lexical) + in-app NumPy cosine over chunk
9
+ embeddings (semantic) + metadata filters (date / collection), blended and
10
+ aggregated to the document level with a best-passage highlight.
11
+
12
+ ## Services
13
+
14
+ | Service | Type | Path | Entry |
15
+ |---|---|---|---|
16
+ | `web` | `static` (React, Vite) | `/` | build → `dist` |
17
+ | `backend` | `python` (FastAPI) | `/backend` | `services/backend/src/main.py` |
18
+
19
+ `needs: { database: true }` → CloudGrid injects `DATABASE_MONGODB_URL` (fallback
20
+ `MONGODB_URL`). **No `needs: vector`** — pgvector runtime role-grant is blocked
21
+ (platform #1545), so embeddings live in the Mongo `chunks` collection and are
22
+ cosine-ranked in-app. A scheduled (cron) refresh is a follow-up, blocked on
23
+ platform #1585 — ship the manager "Refresh now" endpoint for now (see AGENTS.md).
24
+
25
+ ## Pluggable document source
26
+
27
+ `SOURCE_TYPE` selects the adapter, all credentials from env secrets:
28
+
29
+ - `dropbox` (default) — read-only Dropbox via the offline refresh-token flow.
30
+ - `local` — a directory on the container filesystem (`LOCAL_SOURCE_PATH`, or a
31
+ `needs: disk` mount at `DISK_PATH`).
32
+ - `url` — a manifest of document URLs (`URL_SOURCE_MANIFEST`).
33
+
34
+ Add your own by subclassing `Source` in
35
+ `services/backend/src/app/source.py` and returning it from `get_source()`.
36
+
37
+ ## Embeddings
38
+
39
+ Behind one config point (`services/backend/src/app/embeddings.py`), OpenAI by
40
+ default. `EMBEDDINGS_API_KEY` from env; `EMBEDDINGS_MODEL` / `EMBEDDINGS_BASE_URL`
41
+ to point at any OpenAI-compatible provider.
42
+
43
+ ## Secrets (set with `grid secrets set KEY=VALUE`)
44
+
45
+ `EMBEDDINGS_API_KEY`, `SOURCE_TYPE`, and the source's own secrets
46
+ (`DROPBOX_APP_KEY` / `DROPBOX_APP_SECRET` / `DROPBOX_REFRESH_TOKEN` /
47
+ `DROPBOX_FOLDER_PATH`, or `LOCAL_SOURCE_PATH`, or `URL_SOURCE_MANIFEST`), and
48
+ `MANAGER_PASSWORD_HASH` (sha256 hex of the manager password).
49
+
50
+ The app starts and passes `GET /backend/health` with **none** of these set —
51
+ search / indexing degrade to a clear "not indexed / missing secret" state.
52
+
53
+ ## Health without secrets (baked-in)
54
+
55
+ - `@app.on_event("startup")` calls `db.ensure_indexes()` so the chunks `$text`
56
+ index exists at boot — `$text` returns `[]` on an empty catalog, never a 500.
57
+ - The `$text` query is additionally guarded in `except OperationFailure`.
58
+ - No secret is read at import time; every secret is gated inside a function.
59
+ - `/backend/status` reports capability booleans, never secret values.
60
+
61
+ ## Deploy (manager does this)
62
+
63
+ ```bash
64
+ grid init semantic-search # creates the entity + .cloudgrid/link.json
65
+ grid secrets set EMBEDDINGS_API_KEY=sk-... # + source secrets + MANAGER_PASSWORD_HASH
66
+
67
+ # Build the static frontend BEFORE plug — CloudGrid validates that a
68
+ # type:static service with a build: block already has services/web/dist/index.html.
69
+ (cd services/web && npm install && npm run build)
70
+
71
+ grid plug # async build + deploy; poll to a live URL
72
+ ```
73
+
74
+ See `AGENTS.md` for the full wiring guide.