@cloudgrid-io/mcp 0.13.0 → 0.14.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.
- package/package.json +1 -1
- package/src/corpus/capability-map.md +68 -7
- package/src/corpus/templates/_cloudgrid.yaml.reference +228 -0
- package/src/corpus/templates/admin-dashboard/cloudgrid.yaml +226 -8
- package/src/corpus/templates/admin-dashboard/index.md +3 -0
- package/src/corpus/templates/ai-app/cloudgrid.yaml +225 -11
- package/src/corpus/templates/ai-app/index.md +3 -11
- package/src/corpus/templates/ai-knowledge-base/AGENTS.md +254 -0
- package/src/corpus/templates/ai-knowledge-base/README.md +28 -0
- package/src/corpus/templates/ai-knowledge-base/cloudgrid.yaml +238 -0
- package/src/corpus/templates/ai-knowledge-base/index.md +81 -0
- package/src/corpus/templates/analytics-dashboard/README.md +85 -0
- package/src/corpus/templates/analytics-dashboard/cloudgrid.yaml +232 -0
- package/src/corpus/templates/analytics-dashboard/index.md +316 -0
- package/src/corpus/templates/analytics-dashboard/services/web/app/api/events/route.js +60 -0
- package/src/corpus/templates/analytics-dashboard/services/web/app/event-form.js +100 -0
- package/src/corpus/templates/analytics-dashboard/services/web/app/layout.js +41 -0
- package/src/corpus/templates/analytics-dashboard/services/web/app/page.js +54 -0
- package/src/corpus/templates/analytics-dashboard/services/web/lib/db.js +32 -0
- package/src/corpus/templates/analytics-dashboard/services/web/package.json +16 -0
- package/src/corpus/templates/api-dashboard/README.md +84 -0
- package/src/corpus/templates/api-dashboard/cloudgrid.yaml +233 -0
- package/src/corpus/templates/api-dashboard/index.md +310 -0
- package/src/corpus/templates/api-dashboard/services/web/app/api/requests/route.js +62 -0
- package/src/corpus/templates/api-dashboard/services/web/app/dashboard.js +156 -0
- package/src/corpus/templates/api-dashboard/services/web/app/layout.js +42 -0
- package/src/corpus/templates/api-dashboard/services/web/app/page.js +39 -0
- package/src/corpus/templates/api-dashboard/services/web/lib/db.js +32 -0
- package/src/corpus/templates/api-dashboard/services/web/package.json +16 -0
- package/src/corpus/templates/api-docs/cloudgrid.yaml +222 -4
- package/src/corpus/templates/api-docs/index.md +3 -5
- package/src/corpus/templates/api-service/cloudgrid.yaml +224 -9
- package/src/corpus/templates/api-service/index.md +3 -11
- package/src/corpus/templates/app-with-data/cloudgrid.yaml +226 -8
- package/src/corpus/templates/app-with-data/index.md +3 -8
- package/src/corpus/templates/appointment-booking/AGENTS.md +223 -0
- package/src/corpus/templates/appointment-booking/README.md +16 -0
- package/src/corpus/templates/appointment-booking/cloudgrid.yaml +250 -0
- package/src/corpus/templates/appointment-booking/index.md +72 -0
- package/src/corpus/templates/approval-workflow/AGENTS.md +170 -0
- package/src/corpus/templates/approval-workflow/README.md +12 -0
- package/src/corpus/templates/approval-workflow/cloudgrid.yaml +237 -0
- package/src/corpus/templates/approval-workflow/index.md +58 -0
- package/src/corpus/templates/billing-dashboard/AGENTS.md +199 -0
- package/src/corpus/templates/billing-dashboard/README.md +18 -0
- package/src/corpus/templates/billing-dashboard/cloudgrid.yaml +235 -0
- package/src/corpus/templates/billing-dashboard/index.md +87 -0
- package/src/corpus/templates/blog-cms/README.md +94 -0
- package/src/corpus/templates/blog-cms/cloudgrid.yaml +233 -0
- package/src/corpus/templates/blog-cms/index.md +358 -0
- package/src/corpus/templates/blog-cms/services/web/app/admin/admin-editor.js +133 -0
- package/src/corpus/templates/blog-cms/services/web/app/admin/page.js +33 -0
- package/src/corpus/templates/blog-cms/services/web/app/api/posts/route.js +84 -0
- package/src/corpus/templates/blog-cms/services/web/app/layout.js +47 -0
- package/src/corpus/templates/blog-cms/services/web/app/page.js +56 -0
- package/src/corpus/templates/blog-cms/services/web/app/posts/[slug]/page.js +45 -0
- package/src/corpus/templates/blog-cms/services/web/lib/db.js +32 -0
- package/src/corpus/templates/blog-cms/services/web/package.json +16 -0
- package/src/corpus/templates/booking-system/AGENTS.md +189 -0
- package/src/corpus/templates/booking-system/README.md +17 -0
- package/src/corpus/templates/booking-system/cloudgrid.yaml +248 -0
- package/src/corpus/templates/booking-system/index.md +86 -0
- package/src/corpus/templates/calendar-scheduler/AGENTS.md +226 -0
- package/src/corpus/templates/calendar-scheduler/README.md +25 -0
- package/src/corpus/templates/calendar-scheduler/cloudgrid.yaml +259 -0
- package/src/corpus/templates/calendar-scheduler/index.md +85 -0
- package/src/corpus/templates/changelog/cloudgrid.yaml +222 -4
- package/src/corpus/templates/changelog/index.md +3 -5
- package/src/corpus/templates/company-website/README.md +54 -0
- package/src/corpus/templates/company-website/cloudgrid.yaml +233 -0
- package/src/corpus/templates/company-website/index.html +309 -0
- package/src/corpus/templates/company-website/index.md +29 -0
- package/src/corpus/templates/course-platform/AGENTS.md +161 -0
- package/src/corpus/templates/course-platform/README.md +26 -0
- package/src/corpus/templates/course-platform/cloudgrid.yaml +237 -0
- package/src/corpus/templates/course-platform/index.md +70 -0
- package/src/corpus/templates/crm/cloudgrid.yaml +226 -8
- package/src/corpus/templates/crm/index.md +3 -0
- package/src/corpus/templates/dashboard/cloudgrid.yaml +228 -4
- package/src/corpus/templates/dashboard/index.md +3 -5
- package/src/corpus/templates/deck/cloudgrid.yaml +228 -4
- package/src/corpus/templates/deck/index.md +3 -5
- package/src/corpus/templates/directory/README.md +75 -0
- package/src/corpus/templates/directory/cloudgrid.yaml +233 -0
- package/src/corpus/templates/directory/index.md +334 -0
- package/src/corpus/templates/directory/services/web/app/api/entries/route.js +63 -0
- package/src/corpus/templates/directory/services/web/app/directory-list.js +146 -0
- package/src/corpus/templates/directory/services/web/app/layout.js +44 -0
- package/src/corpus/templates/directory/services/web/app/page.js +38 -0
- package/src/corpus/templates/directory/services/web/lib/db.js +32 -0
- package/src/corpus/templates/directory/services/web/package.json +16 -0
- package/src/corpus/templates/docs-site/cloudgrid.yaml +222 -4
- package/src/corpus/templates/docs-site/index.md +3 -5
- package/src/corpus/templates/erp/AGENTS.md +116 -0
- package/src/corpus/templates/erp/README.md +17 -0
- package/src/corpus/templates/erp/cloudgrid.yaml +235 -0
- package/src/corpus/templates/erp/index.md +81 -0
- package/src/corpus/templates/event-board/README.md +74 -0
- package/src/corpus/templates/event-board/cloudgrid.yaml +233 -0
- package/src/corpus/templates/event-board/index.md +299 -0
- package/src/corpus/templates/event-board/services/web/app/api/events/route.js +61 -0
- package/src/corpus/templates/event-board/services/web/app/event-form.js +118 -0
- package/src/corpus/templates/event-board/services/web/app/layout.js +39 -0
- package/src/corpus/templates/event-board/services/web/app/page.js +34 -0
- package/src/corpus/templates/event-board/services/web/lib/db.js +32 -0
- package/src/corpus/templates/event-board/services/web/package.json +16 -0
- package/src/corpus/templates/expense-tracker/README.md +76 -0
- package/src/corpus/templates/expense-tracker/cloudgrid.yaml +233 -0
- package/src/corpus/templates/expense-tracker/index.md +305 -0
- package/src/corpus/templates/expense-tracker/services/web/app/api/expenses/route.js +61 -0
- package/src/corpus/templates/expense-tracker/services/web/app/expense-form.js +145 -0
- package/src/corpus/templates/expense-tracker/services/web/app/layout.js +42 -0
- package/src/corpus/templates/expense-tracker/services/web/app/page.js +34 -0
- package/src/corpus/templates/expense-tracker/services/web/lib/db.js +32 -0
- package/src/corpus/templates/expense-tracker/services/web/package.json +16 -0
- package/src/corpus/templates/feature-request-board/README.md +87 -0
- package/src/corpus/templates/feature-request-board/cloudgrid.yaml +233 -0
- package/src/corpus/templates/feature-request-board/index.md +317 -0
- package/src/corpus/templates/feature-request-board/services/web/app/api/requests/route.js +92 -0
- package/src/corpus/templates/feature-request-board/services/web/app/board.js +91 -0
- package/src/corpus/templates/feature-request-board/services/web/app/layout.js +43 -0
- package/src/corpus/templates/feature-request-board/services/web/app/page.js +35 -0
- package/src/corpus/templates/feature-request-board/services/web/lib/db.js +32 -0
- package/src/corpus/templates/feature-request-board/services/web/package.json +16 -0
- package/src/corpus/templates/financial-dashboard/README.md +80 -0
- package/src/corpus/templates/financial-dashboard/cloudgrid.yaml +233 -0
- package/src/corpus/templates/financial-dashboard/index.md +326 -0
- package/src/corpus/templates/financial-dashboard/services/web/app/api/entries/route.js +63 -0
- package/src/corpus/templates/financial-dashboard/services/web/app/entry-board.js +130 -0
- package/src/corpus/templates/financial-dashboard/services/web/app/layout.js +46 -0
- package/src/corpus/templates/financial-dashboard/services/web/app/page.js +31 -0
- package/src/corpus/templates/financial-dashboard/services/web/lib/db.js +32 -0
- package/src/corpus/templates/financial-dashboard/services/web/package.json +16 -0
- package/src/corpus/templates/forum/AGENTS.md +196 -0
- package/src/corpus/templates/forum/README.md +12 -0
- package/src/corpus/templates/forum/cloudgrid.yaml +237 -0
- package/src/corpus/templates/forum/index.md +66 -0
- package/src/corpus/templates/hr-portal/AGENTS.md +174 -0
- package/src/corpus/templates/hr-portal/README.md +14 -0
- package/src/corpus/templates/hr-portal/cloudgrid.yaml +237 -0
- package/src/corpus/templates/hr-portal/index.md +56 -0
- package/src/corpus/templates/internal-tools-portal/AGENTS.md +201 -0
- package/src/corpus/templates/internal-tools-portal/README.md +17 -0
- package/src/corpus/templates/internal-tools-portal/cloudgrid.yaml +237 -0
- package/src/corpus/templates/internal-tools-portal/index.md +62 -0
- package/src/corpus/templates/inventory/README.md +71 -0
- package/src/corpus/templates/inventory/cloudgrid.yaml +233 -0
- package/src/corpus/templates/inventory/index.md +68 -0
- package/src/corpus/templates/inventory/services/web/app/api/items/route.js +88 -0
- package/src/corpus/templates/inventory/services/web/app/inventory-manager.js +101 -0
- package/src/corpus/templates/inventory/services/web/app/layout.js +36 -0
- package/src/corpus/templates/inventory/services/web/app/page.js +37 -0
- package/src/corpus/templates/inventory/services/web/lib/db.js +32 -0
- package/src/corpus/templates/inventory/services/web/package.json +16 -0
- package/src/corpus/templates/invoice/README.md +71 -0
- package/src/corpus/templates/invoice/cloudgrid.yaml +233 -0
- package/src/corpus/templates/invoice/index.md +68 -0
- package/src/corpus/templates/invoice/services/web/app/api/invoices/route.js +82 -0
- package/src/corpus/templates/invoice/services/web/app/invoice-manager.js +101 -0
- package/src/corpus/templates/invoice/services/web/app/layout.js +35 -0
- package/src/corpus/templates/invoice/services/web/app/page.js +34 -0
- package/src/corpus/templates/invoice/services/web/lib/db.js +32 -0
- package/src/corpus/templates/invoice/services/web/package.json +16 -0
- package/src/corpus/templates/job-board/README.md +71 -0
- package/src/corpus/templates/job-board/cloudgrid.yaml +233 -0
- package/src/corpus/templates/job-board/index.md +68 -0
- package/src/corpus/templates/job-board/services/web/app/api/jobs/route.js +66 -0
- package/src/corpus/templates/job-board/services/web/app/job-board.js +73 -0
- package/src/corpus/templates/job-board/services/web/app/layout.js +35 -0
- package/src/corpus/templates/job-board/services/web/app/page.js +32 -0
- package/src/corpus/templates/job-board/services/web/lib/db.js +32 -0
- package/src/corpus/templates/job-board/services/web/package.json +16 -0
- package/src/corpus/templates/kanban/cloudgrid.yaml +226 -8
- package/src/corpus/templates/kanban/index.md +3 -0
- package/src/corpus/templates/landing-page/cloudgrid.yaml +228 -4
- package/src/corpus/templates/landing-page/index.md +3 -5
- package/src/corpus/templates/lms/AGENTS.md +193 -0
- package/src/corpus/templates/lms/README.md +27 -0
- package/src/corpus/templates/lms/cloudgrid.yaml +237 -0
- package/src/corpus/templates/lms/index.md +79 -0
- package/src/corpus/templates/marketplace/AGENTS.md +208 -0
- package/src/corpus/templates/marketplace/README.md +22 -0
- package/src/corpus/templates/marketplace/cloudgrid.yaml +233 -0
- package/src/corpus/templates/marketplace/index.md +76 -0
- package/src/corpus/templates/membership-site/AGENTS.md +160 -0
- package/src/corpus/templates/membership-site/README.md +18 -0
- package/src/corpus/templates/membership-site/cloudgrid.yaml +236 -0
- package/src/corpus/templates/membership-site/index.md +66 -0
- package/src/corpus/templates/monitoring-dashboard/README.md +84 -0
- package/src/corpus/templates/monitoring-dashboard/cloudgrid.yaml +233 -0
- package/src/corpus/templates/monitoring-dashboard/index.md +328 -0
- package/src/corpus/templates/monitoring-dashboard/services/web/app/api/checks/route.js +76 -0
- package/src/corpus/templates/monitoring-dashboard/services/web/app/check-form.js +124 -0
- package/src/corpus/templates/monitoring-dashboard/services/web/app/layout.js +44 -0
- package/src/corpus/templates/monitoring-dashboard/services/web/app/page.js +49 -0
- package/src/corpus/templates/monitoring-dashboard/services/web/lib/db.js +32 -0
- package/src/corpus/templates/monitoring-dashboard/services/web/package.json +16 -0
- package/src/corpus/templates/online-store/AGENTS.md +153 -0
- package/src/corpus/templates/online-store/README.md +16 -0
- package/src/corpus/templates/online-store/cloudgrid.yaml +234 -0
- package/src/corpus/templates/online-store/index.md +81 -0
- package/src/corpus/templates/portfolio/cloudgrid.yaml +222 -4
- package/src/corpus/templates/portfolio/index.md +3 -5
- package/src/corpus/templates/product-catalog/README.md +74 -0
- package/src/corpus/templates/product-catalog/cloudgrid.yaml +232 -0
- package/src/corpus/templates/product-catalog/index.md +330 -0
- package/src/corpus/templates/product-catalog/services/web/app/api/products/route.js +69 -0
- package/src/corpus/templates/product-catalog/services/web/app/catalog.js +153 -0
- package/src/corpus/templates/product-catalog/services/web/app/layout.js +49 -0
- package/src/corpus/templates/product-catalog/services/web/app/page.js +36 -0
- package/src/corpus/templates/product-catalog/services/web/lib/db.js +32 -0
- package/src/corpus/templates/product-catalog/services/web/package.json +16 -0
- package/src/corpus/templates/product-launch/README.md +46 -0
- package/src/corpus/templates/product-launch/cloudgrid.yaml +234 -0
- package/src/corpus/templates/product-launch/index.html +320 -0
- package/src/corpus/templates/product-launch/index.md +34 -0
- package/src/corpus/templates/project-management/README.md +83 -0
- package/src/corpus/templates/project-management/cloudgrid.yaml +233 -0
- package/src/corpus/templates/project-management/index.md +346 -0
- package/src/corpus/templates/project-management/services/web/app/api/projects/route.js +48 -0
- package/src/corpus/templates/project-management/services/web/app/api/tasks/route.js +85 -0
- package/src/corpus/templates/project-management/services/web/app/board.js +182 -0
- package/src/corpus/templates/project-management/services/web/app/layout.js +45 -0
- package/src/corpus/templates/project-management/services/web/app/page.js +49 -0
- package/src/corpus/templates/project-management/services/web/lib/db.js +32 -0
- package/src/corpus/templates/project-management/services/web/package.json +16 -0
- package/src/corpus/templates/property-listings/README.md +76 -0
- package/src/corpus/templates/property-listings/cloudgrid.yaml +233 -0
- package/src/corpus/templates/property-listings/index.md +335 -0
- package/src/corpus/templates/property-listings/services/web/app/api/properties/route.js +73 -0
- package/src/corpus/templates/property-listings/services/web/app/layout.js +45 -0
- package/src/corpus/templates/property-listings/services/web/app/listings.js +152 -0
- package/src/corpus/templates/property-listings/services/web/app/page.js +53 -0
- package/src/corpus/templates/property-listings/services/web/lib/db.js +32 -0
- package/src/corpus/templates/property-listings/services/web/package.json +16 -0
- package/src/corpus/templates/quiz-platform/README.md +84 -0
- package/src/corpus/templates/quiz-platform/cloudgrid.yaml +233 -0
- package/src/corpus/templates/quiz-platform/index.md +313 -0
- package/src/corpus/templates/quiz-platform/services/web/app/api/questions/route.js +69 -0
- package/src/corpus/templates/quiz-platform/services/web/app/layout.js +47 -0
- package/src/corpus/templates/quiz-platform/services/web/app/page.js +37 -0
- package/src/corpus/templates/quiz-platform/services/web/app/quiz.js +188 -0
- package/src/corpus/templates/quiz-platform/services/web/lib/db.js +32 -0
- package/src/corpus/templates/quiz-platform/services/web/package.json +16 -0
- package/src/corpus/templates/report/cloudgrid.yaml +228 -4
- package/src/corpus/templates/report/index.md +3 -5
- package/src/corpus/templates/restaurant-reservations/AGENTS.md +258 -0
- package/src/corpus/templates/restaurant-reservations/README.md +17 -0
- package/src/corpus/templates/restaurant-reservations/cloudgrid.yaml +258 -0
- package/src/corpus/templates/restaurant-reservations/index.md +62 -0
- package/src/corpus/templates/revenue-dashboard/README.md +75 -0
- package/src/corpus/templates/revenue-dashboard/cloudgrid.yaml +233 -0
- package/src/corpus/templates/revenue-dashboard/index.md +307 -0
- package/src/corpus/templates/revenue-dashboard/services/web/app/api/sales/route.js +60 -0
- package/src/corpus/templates/revenue-dashboard/services/web/app/layout.js +40 -0
- package/src/corpus/templates/revenue-dashboard/services/web/app/page.js +87 -0
- package/src/corpus/templates/revenue-dashboard/services/web/app/sale-form.js +63 -0
- package/src/corpus/templates/revenue-dashboard/services/web/lib/db.js +32 -0
- package/src/corpus/templates/revenue-dashboard/services/web/package.json +16 -0
- package/src/corpus/templates/saas-marketing/cloudgrid.yaml +222 -4
- package/src/corpus/templates/saas-marketing/index.md +3 -5
- package/src/corpus/templates/status-page/cloudgrid.yaml +222 -4
- package/src/corpus/templates/status-page/index.md +3 -5
- package/src/corpus/templates/subscription-management/AGENTS.md +191 -0
- package/src/corpus/templates/subscription-management/README.md +21 -0
- package/src/corpus/templates/subscription-management/cloudgrid.yaml +236 -0
- package/src/corpus/templates/subscription-management/index.md +73 -0
- package/src/corpus/templates/task-manager/cloudgrid.yaml +226 -8
- package/src/corpus/templates/task-manager/index.md +3 -0
- package/src/corpus/templates/ticket-system/README.md +71 -0
- package/src/corpus/templates/ticket-system/cloudgrid.yaml +233 -0
- package/src/corpus/templates/ticket-system/index.md +68 -0
- package/src/corpus/templates/ticket-system/services/web/app/api/tickets/route.js +81 -0
- package/src/corpus/templates/ticket-system/services/web/app/layout.js +36 -0
- package/src/corpus/templates/ticket-system/services/web/app/page.js +35 -0
- package/src/corpus/templates/ticket-system/services/web/app/ticket-queue.js +112 -0
- package/src/corpus/templates/ticket-system/services/web/lib/db.js +32 -0
- package/src/corpus/templates/ticket-system/services/web/package.json +16 -0
- package/src/corpus/templates/time-tracking/README.md +81 -0
- package/src/corpus/templates/time-tracking/cloudgrid.yaml +233 -0
- package/src/corpus/templates/time-tracking/index.md +298 -0
- package/src/corpus/templates/time-tracking/services/web/app/api/entries/route.js +66 -0
- package/src/corpus/templates/time-tracking/services/web/app/entry-form.js +106 -0
- package/src/corpus/templates/time-tracking/services/web/app/layout.js +39 -0
- package/src/corpus/templates/time-tracking/services/web/app/page.js +30 -0
- package/src/corpus/templates/time-tracking/services/web/lib/db.js +32 -0
- package/src/corpus/templates/time-tracking/services/web/package.json +16 -0
- package/src/corpus/templates/travel-booking/AGENTS.md +207 -0
- package/src/corpus/templates/travel-booking/README.md +17 -0
- package/src/corpus/templates/travel-booking/cloudgrid.yaml +249 -0
- package/src/corpus/templates/travel-booking/index.md +88 -0
- package/src/corpus/templates/waitlist/cloudgrid.yaml +222 -4
- package/src/corpus/templates/waitlist/index.md +3 -5
- package/src/corpus/templates/web-app/cloudgrid.yaml +228 -4
- package/src/corpus/templates/web-app/index.md +3 -5
- package/src/corpus/workflows/ai-knowledge-base.md +137 -0
- package/src/corpus/workflows/analytics-dashboard.md +104 -0
- package/src/corpus/workflows/api-dashboard.md +102 -0
- package/src/corpus/workflows/appointment-booking.md +143 -0
- package/src/corpus/workflows/approval-workflow.md +124 -0
- package/src/corpus/workflows/billing-dashboard.md +120 -0
- package/src/corpus/workflows/blog-cms.md +104 -0
- package/src/corpus/workflows/booking-system.md +116 -0
- package/src/corpus/workflows/calendar-scheduler.md +134 -0
- package/src/corpus/workflows/company-website.md +46 -0
- package/src/corpus/workflows/course-platform.md +126 -0
- package/src/corpus/workflows/directory.md +101 -0
- package/src/corpus/workflows/erp.md +125 -0
- package/src/corpus/workflows/event-board.md +102 -0
- package/src/corpus/workflows/expense-tracker.md +102 -0
- package/src/corpus/workflows/feature-request-board.md +105 -0
- package/src/corpus/workflows/financial-dashboard.md +103 -0
- package/src/corpus/workflows/forum.md +128 -0
- package/src/corpus/workflows/hr-portal.md +115 -0
- package/src/corpus/workflows/internal-tools-portal.md +125 -0
- package/src/corpus/workflows/inventory.md +101 -0
- package/src/corpus/workflows/invoice.md +101 -0
- package/src/corpus/workflows/job-board.md +101 -0
- package/src/corpus/workflows/lms.md +113 -0
- package/src/corpus/workflows/marketplace.md +123 -0
- package/src/corpus/workflows/membership-site.md +128 -0
- package/src/corpus/workflows/monitoring-dashboard.md +104 -0
- package/src/corpus/workflows/online-store.md +114 -0
- package/src/corpus/workflows/product-catalog.md +105 -0
- package/src/corpus/workflows/product-launch.md +43 -0
- package/src/corpus/workflows/project-management.md +106 -0
- package/src/corpus/workflows/property-listings.md +101 -0
- package/src/corpus/workflows/quiz-platform.md +105 -0
- package/src/corpus/workflows/restaurant-reservations.md +123 -0
- package/src/corpus/workflows/revenue-dashboard.md +102 -0
- package/src/corpus/workflows/subscription-management.md +141 -0
- package/src/corpus/workflows/ticket-system.md +101 -0
- package/src/corpus/workflows/time-tracking.md +104 -0
- package/src/corpus/workflows/travel-booking.md +115 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# AGENTS.md — appointment-booking (BLUEPRINT)
|
|
2
|
+
|
|
3
|
+
This is a **blueprint**, not runnable code. It tells an agent how to build an
|
|
4
|
+
appointment / clinic / salon booking app correctly on CloudGrid: a Next.js app
|
|
5
|
+
where a business defines providers and services, publishes bookable time slots,
|
|
6
|
+
and clients book an appointment against an available slot — with auth so a
|
|
7
|
+
provider owns their calendar, optional Stripe deposits, and grid-shared Mongo
|
|
8
|
+
for persistence. Read this whole file, then build the app under `services/web/`
|
|
9
|
+
following the structure below. Do not skip the CloudGrid wiring rules — they are
|
|
10
|
+
what make it deploy.
|
|
11
|
+
|
|
12
|
+
The proven persistent shape is `app-with-data` (Next.js + Mongo). This blueprint
|
|
13
|
+
extends it with auth, availability/slot logic, and optional Stripe deposits.
|
|
14
|
+
Fetch that template for the Mongo lazy-client and App-Router API pattern:
|
|
15
|
+
`gridctl_fetch("template", "app-with-data")`.
|
|
16
|
+
|
|
17
|
+
## 1. File tree
|
|
18
|
+
|
|
19
|
+
Build exactly this layout. **App code MUST live under `services/web/`** — the
|
|
20
|
+
service is named `web`, so the CLI looks for `services/web/`. `path: /` in
|
|
21
|
+
`cloudgrid.yaml` is the URL mount, NOT the filesystem path. Files at the repo
|
|
22
|
+
root fail with `Error: Service directory not found: …/services/web`.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
cloudgrid.yaml # name + services.web (nextjs) + needs:{database:true} + vault: (auth + optional Stripe)
|
|
26
|
+
services/web/package.json # next, react, react-dom, mongodb, + auth SDK (e.g. @clerk/nextjs); stripe only if deposits
|
|
27
|
+
services/web/middleware.js # auth middleware: protects /dashboard/* + provider APIs — anon → sign-in
|
|
28
|
+
services/web/lib/db.js # lazy Mongo client from DATABASE_MONGODB_URL (legacy MONGODB_URL fallback)
|
|
29
|
+
services/web/lib/stripe.js # (optional) lazy Stripe client from process.env.STRIPE_KEY (never top-level)
|
|
30
|
+
services/web/lib/slots.js # availability math: expand a provider's rules into concrete open slots, minus booked
|
|
31
|
+
services/web/app/layout.js # root layout (+ auth provider wrapper if the SDK needs one)
|
|
32
|
+
services/web/app/page.js # public: list providers/services to book
|
|
33
|
+
services/web/app/book/[providerId]/page.js # public: pick a service + an open slot for one provider
|
|
34
|
+
services/web/app/dashboard/layout.js # gate: server-side require signed-in provider; redirect anon → sign-in
|
|
35
|
+
services/web/app/dashboard/page.js # provider view: their services, availability rules, upcoming appointments
|
|
36
|
+
services/web/app/api/providers/route.js # GET list providers (public) / POST create provider (auth: owner)
|
|
37
|
+
services/web/app/api/services/route.js # GET services for a provider / POST create a bookable service (auth)
|
|
38
|
+
services/web/app/api/availability/route.js # GET open slots for provider+date (computed) / POST set availability rules (auth)
|
|
39
|
+
services/web/app/api/appointments/route.js # POST book a slot (public/client) / GET a provider's appointments (auth)
|
|
40
|
+
services/web/app/api/appointments/[id]/route.js# PATCH reschedule/cancel / DELETE (auth or booking token)
|
|
41
|
+
services/web/app/api/checkout/route.js # (optional) POST: Stripe Checkout for a booking deposit → return url
|
|
42
|
+
services/web/app/api/webhook/route.js # (optional) POST: Stripe webhook — mark appointment deposit paid
|
|
43
|
+
services/reminders/ # (INTENDED cron job — PENDING #1543, see §7) reminder sender; not deployable yet
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 2. Mongo collections + fields
|
|
47
|
+
|
|
48
|
+
The grid provisions Mongo from `needs: { database: true }`. Use four core
|
|
49
|
+
collections. Booking correctness lives here — a slot is bookable only if no
|
|
50
|
+
active `appointments` doc already occupies that provider + start time.
|
|
51
|
+
|
|
52
|
+
**`providers`** — a bookable person/resource (doctor, stylist, room).
|
|
53
|
+
- `_id` (ObjectId)
|
|
54
|
+
- `ownerId` (string, indexed) — the auth provider's user id (Clerk/Auth0 `sub`) that owns this calendar
|
|
55
|
+
- `name` (string), `bio` (string), `timezone` (string, e.g. `"America/New_York"`)
|
|
56
|
+
- `createdAt` (Date)
|
|
57
|
+
|
|
58
|
+
**`services`** — a bookable offering (a "30-min consult", "haircut").
|
|
59
|
+
- `_id` (ObjectId)
|
|
60
|
+
- `providerId` (ObjectId, indexed)
|
|
61
|
+
- `name` (string), `durationMinutes` (number), `priceCents` (number, 0 = free)
|
|
62
|
+
- `depositCents` (number, 0 = no deposit) — drives the optional Stripe flow
|
|
63
|
+
- `active` (boolean)
|
|
64
|
+
|
|
65
|
+
**`availability`** — a provider's recurring open hours (the rules slots expand from).
|
|
66
|
+
- `_id` (ObjectId)
|
|
67
|
+
- `providerId` (ObjectId, indexed)
|
|
68
|
+
- `weekday` (number 0–6) — or store explicit date ranges if you prefer one-off availability
|
|
69
|
+
- `startMinute` (number, minutes past midnight in the provider's tz), `endMinute` (number)
|
|
70
|
+
- `slotMinutes` (number) — granularity to chop the window into
|
|
71
|
+
|
|
72
|
+
**`appointments`** — a booked slot. This is the source of truth for "taken".
|
|
73
|
+
- `_id` (ObjectId)
|
|
74
|
+
- `providerId` (ObjectId, indexed), `serviceId` (ObjectId)
|
|
75
|
+
- `startAt` (Date, UTC, indexed), `endAt` (Date, UTC)
|
|
76
|
+
- `clientName` (string), `clientEmail` (string), `clientPhone` (string)
|
|
77
|
+
- `status` (string) — `"pending" | "confirmed" | "cancelled" | "completed"`
|
|
78
|
+
- `depositStatus` (string) — `"none" | "required" | "paid"` (drives Stripe gating)
|
|
79
|
+
- `stripeSessionId` (string, optional), `reminderSentAt` (Date, optional — the cron sets this)
|
|
80
|
+
- `createdAt` (Date)
|
|
81
|
+
|
|
82
|
+
**Prevent double-booking.** Put a unique index on
|
|
83
|
+
`appointments { providerId, startAt }` for `status ∈ {pending, confirmed}` (a
|
|
84
|
+
partial unique index) and insert the booking inside a guarded write — so two
|
|
85
|
+
clients racing for the same slot cannot both win.
|
|
86
|
+
|
|
87
|
+
## 3. How CloudGrid injects everything (the wiring that matters)
|
|
88
|
+
|
|
89
|
+
- **Mongo** — declared by `needs: { database: true }`. The deployer provisions
|
|
90
|
+
shared Mongo and injects the connection string as **`DATABASE_MONGODB_URL`**
|
|
91
|
+
(plus the legacy **`MONGODB_URL`** alias) at runtime and under `grid dev`.
|
|
92
|
+
Read `process.env.DATABASE_MONGODB_URL || process.env.MONGODB_URL` **LAZILY,
|
|
93
|
+
inside the getter** in `lib/db.js` — never at module top level, or `next build`
|
|
94
|
+
fails when it imports the module for route analysis before the grid injects
|
|
95
|
+
the var. Never hardcode a connection string. Never set `needs:` and `requires:`
|
|
96
|
+
together — `requires:` is the deprecated v1 alias.
|
|
97
|
+
- **Secrets (auth + optional Stripe) → env vars via the `vault:` block.** In
|
|
98
|
+
`cloudgrid.yaml` the `vault:` block maps each env var to a vault item key:
|
|
99
|
+
```yaml
|
|
100
|
+
vault:
|
|
101
|
+
AUTH_PROVIDER_KEY: auth-provider-key
|
|
102
|
+
STRIPE_KEY: stripe-live-key # only if you take deposits
|
|
103
|
+
STRIPE_WEBHOOK_SECRET: stripe-webhook-secret # only if you take deposits
|
|
104
|
+
```
|
|
105
|
+
Set the vault items ONCE with `gridctl_secrets` (or `grid secrets set`), then
|
|
106
|
+
the deployer injects each as the named env var (`process.env.AUTH_PROVIDER_KEY`,
|
|
107
|
+
`process.env.STRIPE_KEY`, …) at runtime and under `grid dev`. Do NOT commit
|
|
108
|
+
keys; do NOT set secrets in `services.web.env` (that block is for non-secret
|
|
109
|
+
config only). Read them LAZILY inside `lib/stripe.js` and the auth setup — same
|
|
110
|
+
rule as the DB.
|
|
111
|
+
- **Public auth keys** — SDKs like Clerk also need a *publishable* key on the
|
|
112
|
+
client (`NEXT_PUBLIC_...`). Publishable keys are not secret; put them in the
|
|
113
|
+
non-secret `services.web.env` block (or as a build-time env), NOT the vault.
|
|
114
|
+
- **AI (optional)** — if you add AI features (e.g. natural-language "book me next
|
|
115
|
+
Tuesday afternoon"), declare `needs: { ai: true }` and call the gateway at
|
|
116
|
+
`process.env.AI_GATEWAY_URL` via `@cloudgrid-io/ai`. Not required for this
|
|
117
|
+
blueprint.
|
|
118
|
+
|
|
119
|
+
## 4. Wiring auth + payments
|
|
120
|
+
|
|
121
|
+
**Auth (provider SDK, e.g. Clerk or Auth0).** Auth is for the *business side* —
|
|
122
|
+
providers sign in to manage their calendar and see their appointments. Clients
|
|
123
|
+
booking a public slot need not sign in (identify them by `clientEmail`), unless
|
|
124
|
+
you want client accounts.
|
|
125
|
+
1. Add the SDK to `services/web/package.json` (e.g. `@clerk/nextjs`).
|
|
126
|
+
2. Server key from the vault (`process.env.AUTH_PROVIDER_KEY`); publishable key
|
|
127
|
+
from `services.web.env` as `NEXT_PUBLIC_...`.
|
|
128
|
+
3. Wrap the app in the provider in `app/layout.js`.
|
|
129
|
+
4. `services/web/middleware.js` protects `/dashboard/*` and the write/owner
|
|
130
|
+
endpoints (`POST /api/providers`, `/api/services`, `/api/availability`,
|
|
131
|
+
`GET /api/appointments`). The public booking routes (`GET /api/providers`,
|
|
132
|
+
`GET /api/availability`, `POST /api/appointments`) stay open. Every provider
|
|
133
|
+
API must scope its query by the signed-in `ownerId` — never trust a
|
|
134
|
+
`providerId` from the body for owner actions without checking ownership.
|
|
135
|
+
|
|
136
|
+
**Slot computation (`lib/slots.js`).** This is the heart of correctness:
|
|
137
|
+
1. For a provider + date, load their `availability` rules for that weekday and
|
|
138
|
+
the provider's `timezone`; chop each open window into `slotMinutes` candidate
|
|
139
|
+
starts, in the provider's local time, converted to UTC.
|
|
140
|
+
2. Load `appointments` for that provider on that date with
|
|
141
|
+
`status ∈ {pending, confirmed}`; subtract any candidate whose `[startAt,endAt)`
|
|
142
|
+
overlaps a booked one (respect each service's `durationMinutes`).
|
|
143
|
+
3. Return the remaining open slots. `GET /api/availability` returns these;
|
|
144
|
+
`POST /api/appointments` re-checks availability at write time (never trust the
|
|
145
|
+
client's slot) and inserts under the partial unique index from §2.
|
|
146
|
+
|
|
147
|
+
**Payments (optional Stripe deposit).** Only if a service has `depositCents > 0`.
|
|
148
|
+
1. Add `stripe` to `package.json`. Build a lazy Stripe client in `lib/stripe.js`
|
|
149
|
+
reading `process.env.STRIPE_KEY` inside the getter.
|
|
150
|
+
2. **Checkout** — on booking a deposit-required service, `app/api/checkout/route.js`
|
|
151
|
+
(POST) creates a Stripe Checkout Session (`mode: "payment"`, amount =
|
|
152
|
+
`depositCents`), stashes the `appointmentId` in `metadata`, sets `success_url`
|
|
153
|
+
/`cancel_url`, returns `session.url`; the booking is written `status: "pending"`,
|
|
154
|
+
`depositStatus: "required"`, and the client is redirected to pay.
|
|
155
|
+
3. **Webhook** — `app/api/webhook/route.js` (POST) verifies the signature with
|
|
156
|
+
`process.env.STRIPE_WEBHOOK_SECRET` (read the RAW request body — do not
|
|
157
|
+
JSON-parse before verifying). On `checkout.session.completed`, set the
|
|
158
|
+
appointment `depositStatus: "paid"`, `status: "confirmed"`. Register this
|
|
159
|
+
route's public URL as the webhook endpoint in the Stripe dashboard after
|
|
160
|
+
deploy. If a service has no deposit, book straight to `status: "confirmed"`.
|
|
161
|
+
|
|
162
|
+
## 5. Deploy steps
|
|
163
|
+
|
|
164
|
+
1. `gridctl_login_status` → `gridctl_login` if needed. Respect the grid picker
|
|
165
|
+
(ask which grid if the user has more than one).
|
|
166
|
+
2. `gridctl_init` an app `<name>` FIRST — it creates the entity, writes
|
|
167
|
+
`.cloudgrid/link.json`, and a `cloudgrid.yaml` with empty `services: {}`.
|
|
168
|
+
`plug` needs a linked directory.
|
|
169
|
+
3. Write the app under `services/web/` and set `cloudgrid.yaml` to the active
|
|
170
|
+
shape: `name` + `services.web{type: nextjs, path: /}` + `needs:{database:true}`
|
|
171
|
+
+ the `vault:` block. (Leave the `reminders` cron service COMMENTED — see §7.)
|
|
172
|
+
4. Set the secrets: `gridctl_secrets` for `auth-provider-key` (and, if taking
|
|
173
|
+
deposits, `stripe-live-key`, `stripe-webhook-secret` — the vault item keys the
|
|
174
|
+
`vault:` block maps from). Non-secret config (auth publishable key, price ids)
|
|
175
|
+
→ `gridctl_env` / `services.web.env`. Do NOT set `DATABASE_MONGODB_URL`
|
|
176
|
+
yourself — the grid injects it.
|
|
177
|
+
5. `gridctl_plug` to deploy. A runtime deploy is **ASYNC** — the first response
|
|
178
|
+
is `status: building`, not a live URL. Poll `gridctl_status` (or the returned
|
|
179
|
+
poll_url) until live; surface a liveness signal while it builds, never a bare
|
|
180
|
+
silent wait.
|
|
181
|
+
6. If taking deposits, once live add the `/api/webhook` URL as the Stripe webhook
|
|
182
|
+
endpoint, copy the signing secret into the `stripe-webhook-secret` vault item,
|
|
183
|
+
then re-plug. Return the live app URL (not the build/log link).
|
|
184
|
+
|
|
185
|
+
## 6. Edition note
|
|
186
|
+
|
|
187
|
+
An appointment-booking app is a built + deployed runtime container, so it
|
|
188
|
+
requires the **local edition** (Claude Desktop / Claude Code) or the CLI. The
|
|
189
|
+
**hosted** edition (Claude Web / hosted MCP) is inline-only and can only publish
|
|
190
|
+
static pages — it CANNOT build this app. On hosted, say so plainly and offer a
|
|
191
|
+
static "book us" landing page (via `gridctl_drop`) instead, then stop the runtime
|
|
192
|
+
path.
|
|
193
|
+
|
|
194
|
+
## 7. Reminders (cron — PENDING platform issue #1543)
|
|
195
|
+
|
|
196
|
+
The design wants a **scheduled reminder job**: on a fixed interval, find
|
|
197
|
+
appointments entering the reminder window (e.g. starting in ~24h) that have not
|
|
198
|
+
had a reminder sent, notify the client (email/SMS via a provider key from the
|
|
199
|
+
vault), and stamp `reminderSentAt` so each appointment is reminded once.
|
|
200
|
+
|
|
201
|
+
The **intended** cron service shape (already present, COMMENTED, in
|
|
202
|
+
`cloudgrid.yaml`):
|
|
203
|
+
|
|
204
|
+
```yaml
|
|
205
|
+
services:
|
|
206
|
+
reminders:
|
|
207
|
+
type: cron
|
|
208
|
+
schedule: "*/15 * * * *" # every 15 min
|
|
209
|
+
timezone: UTC
|
|
210
|
+
run: job # runs services/reminders/ as a one-shot job per tick
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The cron job would live under `services/reminders/` (its own entry that opens the
|
|
214
|
+
same Mongo via the injected `DATABASE_MONGODB_URL`, queries due appointments,
|
|
215
|
+
sends, and stamps `reminderSentAt`). It inherits the app-level `needs: database`
|
|
216
|
+
and can read a notification provider key from the `vault:` block.
|
|
217
|
+
|
|
218
|
+
**IMPORTANT: cron deploy is currently a PENDING platform issue (#1543) and is NOT
|
|
219
|
+
yet deployable.** Keep the `reminders` service COMMENTED in `cloudgrid.yaml` —
|
|
220
|
+
uncommenting it today will not deploy. Until cron ships, either (a) ship the
|
|
221
|
+
booking app without reminders, or (b) trigger reminders manually / from an
|
|
222
|
+
external scheduler hitting an authenticated `/api/appointments` reminder
|
|
223
|
+
endpoint. Document this limitation to the user; do not claim reminders are live.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# appointment-booking template — BLUEPRINT (Next.js + auth + Mongo, optional Stripe)
|
|
2
|
+
|
|
3
|
+
An appointment / clinic / salon booking app: a business defines providers and
|
|
4
|
+
bookable services, publishes availability, and clients book an open time slot —
|
|
5
|
+
with auth so a provider owns their calendar, optional Stripe deposits, and
|
|
6
|
+
grid-shared Mongo (`providers`, `services`, `availability`, `appointments`) as
|
|
7
|
+
the source of truth for what is booked. It exists because scheduling is
|
|
8
|
+
correctness-sensitive (no double-booking, availability minus taken slots), so it
|
|
9
|
+
ships as a **blueprint: the structure + the cloudgrid.yaml — adapt and build**,
|
|
10
|
+
not finished code. Read `AGENTS.md` for the file tree, Mongo collections, the
|
|
11
|
+
slot-computation and anti-double-booking rules, and the CloudGrid wiring
|
|
12
|
+
(`needs: { database: true }` → `DATABASE_MONGODB_URL`; auth/Stripe secrets via
|
|
13
|
+
the `vault:` block → env vars), then build the app under `services/web/` and
|
|
14
|
+
deploy (async — poll to a live URL; local edition only). A scheduled reminder
|
|
15
|
+
cron service is designed but its deploy is **PENDING platform issue #1543** — see
|
|
16
|
+
AGENTS.md § 7.
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# ============================================================================
|
|
2
|
+
# cloudgrid.yaml — Complete Example
|
|
3
|
+
# ============================================================================
|
|
4
|
+
#
|
|
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
|
|
23
|
+
name: appointment-booking
|
|
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
|
+
# Auth (so providers/clients own bookings) and optional deposit payments need
|
|
122
|
+
# secrets injected as env vars — this is the CloudGrid-correct way. Set each
|
|
123
|
+
# vault item once (grid secrets set), then the deployer injects it as the named
|
|
124
|
+
# env var at runtime and under `grid dev`. Read them LAZILY, never top-level.
|
|
125
|
+
vault:
|
|
126
|
+
AUTH_PROVIDER_KEY: auth-provider-key # auth SDK server key (e.g. Clerk secret / Auth0 client secret)
|
|
127
|
+
STRIPE_KEY: stripe-live-key # Stripe secret key — optional booking deposits / prepayment
|
|
128
|
+
STRIPE_WEBHOOK_SECRET: stripe-webhook-secret # verifies Stripe webhook signatures (deposit confirmation)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# ─── CONNECTORS AND HOOKS ──────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
# connectors:
|
|
134
|
+
# - id: team-slack
|
|
135
|
+
# target: org # 'system' | 'org'.
|
|
136
|
+
# channel: "#deploys"
|
|
137
|
+
# hooks:
|
|
138
|
+
# - on: deploy.failed # release.published | deploy.failed | feedback.received | entity.created
|
|
139
|
+
# via: team-slack
|
|
140
|
+
# template: "Deploy failed for {entity_name}: {error}"
|
|
141
|
+
# channel: "#alerts"
|
|
142
|
+
# triggers:
|
|
143
|
+
# - from: team-slack
|
|
144
|
+
# event: message
|
|
145
|
+
# channel: "#support"
|
|
146
|
+
# route: /webhooks/slack
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# ─── LOCAL DEVELOPMENT ──────────────────────────────────────────────────────
|
|
150
|
+
|
|
151
|
+
# Config for `grid dev`. Redact fields in dev data snapshots.
|
|
152
|
+
# dev:
|
|
153
|
+
# snapshot:
|
|
154
|
+
# mask:
|
|
155
|
+
# - users.email
|
|
156
|
+
# - users.phone
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# ─── AGENT METADATA ────────────────────────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
# An agent is an app with kind: agent (above) and an agent: block.
|
|
162
|
+
# agent:
|
|
163
|
+
# purpose: Sync customer data from external CRM every night
|
|
164
|
+
# schedule: "0 2 * * *"
|
|
165
|
+
# trigger: webhook
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# ─── PRIVATE RESOURCE AUTO-DEPENDENCIES ────────────────────────────────────
|
|
169
|
+
|
|
170
|
+
# When true (default), private resources are auto-injected as depends_on.
|
|
171
|
+
# auto_depends_on_private_requires: true
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# ─── SERVICES (REQUIRED) ───────────────────────────────────────────────────
|
|
175
|
+
#
|
|
176
|
+
# At least one service is required. Key = service name (slug rules).
|
|
177
|
+
# Types: node, nextjs, python, static, cron.
|
|
178
|
+
#
|
|
179
|
+
services:
|
|
180
|
+
web:
|
|
181
|
+
# type (REQUIRED): node | nextjs | python | static | cron
|
|
182
|
+
type: nextjs
|
|
183
|
+
# HTTP route: '/' | '/api' | false (internal) | omitted (=false + warning).
|
|
184
|
+
# Only one service per entity can claim '/'.
|
|
185
|
+
path: /
|
|
186
|
+
# Container port (default 8080; read process.env.PORT). Not for cron.
|
|
187
|
+
# port: 3000
|
|
188
|
+
# nextjs only: base_image: distroless (default) | alpine
|
|
189
|
+
# base_image: distroless
|
|
190
|
+
# node only: lang: javascript (default) | typescript
|
|
191
|
+
# lang: typescript
|
|
192
|
+
# Custom source location (default services/<name>/). '.' = project root.
|
|
193
|
+
# source:
|
|
194
|
+
# path: src/worker
|
|
195
|
+
# Health probe: false/omitted (TCP) | true (/health) | "/path" | {path,expected}
|
|
196
|
+
# health:
|
|
197
|
+
# path: /api/health
|
|
198
|
+
# expected: "200"
|
|
199
|
+
# Static runtime env vars (strings). Reserved: PORT, APP_NAME, SERVICE_NAME,
|
|
200
|
+
# NODE_ENV, MONGODB_URL, REDIS_URL, AI_GATEWAY_URL, N8N_WEBHOOK_URL, CLOUDGRID_*.
|
|
201
|
+
# env:
|
|
202
|
+
# LOG_LEVEL: info
|
|
203
|
+
# Sibling services/private resources that must be Ready first (no cron, no cycles).
|
|
204
|
+
# depends_on:
|
|
205
|
+
# - worker
|
|
206
|
+
# Per-service needs override (merges with app-level needs).
|
|
207
|
+
# needs:
|
|
208
|
+
# queue: true
|
|
209
|
+
# Static-only build step:
|
|
210
|
+
# build:
|
|
211
|
+
# command: npm run build
|
|
212
|
+
# output: dist
|
|
213
|
+
# env:
|
|
214
|
+
# VITE_API_URL: https://api.example.com
|
|
215
|
+
# node_version: "22" # static build step: '18'|'20'|'22'|'24' (quoted)
|
|
216
|
+
# Cron-only: schedule (REQUIRED), timezone (UTC|EST|PST), run (job | https URL)
|
|
217
|
+
# schedule: "0 9 * * 1"
|
|
218
|
+
# timezone: UTC
|
|
219
|
+
# run: job
|
|
220
|
+
# Verbose per-service persistence (prefer needs.disk):
|
|
221
|
+
# persist:
|
|
222
|
+
# - name: scratch
|
|
223
|
+
# path: /tmp/scratch
|
|
224
|
+
# size: 500Mi
|
|
225
|
+
|
|
226
|
+
# ── INTENDED cron service — appointment reminders (NOT YET DEPLOYABLE) ──
|
|
227
|
+
# This design wants a scheduled job to send reminders for upcoming
|
|
228
|
+
# appointments (e.g. "24h before"). The shape below is the intended cron
|
|
229
|
+
# service. Cron deploy is a PENDING platform issue (#1543) — leave this
|
|
230
|
+
# COMMENTED until cron ships; uncommenting it today will not deploy. See
|
|
231
|
+
# AGENTS.md § "Reminders (cron — PENDING #1543)" for the intended behaviour.
|
|
232
|
+
# reminders:
|
|
233
|
+
# type: cron
|
|
234
|
+
# schedule: "*/15 * * * *" # every 15 min: find appts entering the reminder window
|
|
235
|
+
# timezone: UTC
|
|
236
|
+
# run: job # runs services/reminders/ as a one-shot job per tick
|
|
237
|
+
# # Inherits app-level needs (database) + vault (for the notification provider key).
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
needs:
|
|
241
|
+
database: true
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ============================================================================
|
|
245
|
+
# NOTES
|
|
246
|
+
# - NOT here: org:/entity_id: (→ .cloudgrid/link.json), secrets (→ grid secrets set),
|
|
247
|
+
# Dockerfile (platform generates from services.*.type).
|
|
248
|
+
# - Deploy: grid plug | Local with grid resources: grid dev
|
|
249
|
+
# - Full reference: docs/cloudgrid-yaml-reference.md | CLI: docs/cli-reference.md
|
|
250
|
+
# ============================================================================
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Template: appointment-booking (BLUEPRINT — Next.js + auth + Mongo, optional Stripe)
|
|
2
|
+
|
|
3
|
+
An appointment / clinic / salon booking app. **Blueprint, not finished code**:
|
|
4
|
+
it ships the `cloudgrid.yaml` and a structure guide (`AGENTS.md`) so an agent can
|
|
5
|
+
build it correctly on CloudGrid — a Next.js app where a business defines
|
|
6
|
+
providers and bookable services, publishes availability, and clients book an open
|
|
7
|
+
slot, with auth so a provider owns their calendar, optional Stripe deposits, and
|
|
8
|
+
grid-shared Mongo. Read `AGENTS.md`, build the app under `services/web/`, adapt
|
|
9
|
+
the providers/services/slot rules, then deploy (async — poll to a live URL).
|
|
10
|
+
Local edition only.
|
|
11
|
+
|
|
12
|
+
**Fetch the bundle:**
|
|
13
|
+
- `gridctl_fetch("template", "appointment-booking")` — this blueprint (`cloudgrid.yaml` + `AGENTS.md`).
|
|
14
|
+
- `gridctl_fetch("template", "app-with-data")` — the proven Next.js + Mongo shape to extend (lazy db client, App-Router API).
|
|
15
|
+
|
|
16
|
+
**Key rules:**
|
|
17
|
+
|
|
18
|
+
1. **Blueprint — read `AGENTS.md` first.** It has the file tree, the Mongo
|
|
19
|
+
collections (`providers`, `services`, `availability`, `appointments`), the
|
|
20
|
+
slot-computation + anti-double-booking rules, the CloudGrid injection table,
|
|
21
|
+
and the auth + Stripe wiring. Build following it; do not invent structure.
|
|
22
|
+
2. **App code MUST live under `services/web/`.** `path: /` is the URL mount, NOT
|
|
23
|
+
the filesystem path. Root files fail with `Service directory not found`.
|
|
24
|
+
3. **Mongo via `needs:{database:true}`** → the grid injects
|
|
25
|
+
`DATABASE_MONGODB_URL` (legacy `MONGODB_URL` fallback). Read it LAZILY inside
|
|
26
|
+
the getter, never at module top level (top-level read fails `next build`).
|
|
27
|
+
4. **Secrets via the `vault:` block** → env vars. `AUTH_PROVIDER_KEY` (and, for
|
|
28
|
+
deposits, `STRIPE_KEY` / `STRIPE_WEBHOOK_SECRET`) map to vault items; set them
|
|
29
|
+
with `gridctl_secrets`, and the deployer injects them at runtime. Read lazily;
|
|
30
|
+
do not commit keys or put secrets in `services.web.env`.
|
|
31
|
+
5. **No double-booking.** `appointments` is the source of truth for "taken";
|
|
32
|
+
compute open slots as availability minus booked, re-check at write time, and
|
|
33
|
+
guard the insert with a partial unique index on `{ providerId, startAt }`.
|
|
34
|
+
6. **Never set `needs:` and `requires:` together** — `requires:` is the
|
|
35
|
+
deprecated v1 alias.
|
|
36
|
+
7. **Reminders (cron) are designed but PENDING platform issue #1543** — keep the
|
|
37
|
+
`reminders` cron service COMMENTED in `cloudgrid.yaml`; it is not yet
|
|
38
|
+
deployable. See AGENTS.md § 7.
|
|
39
|
+
|
|
40
|
+
## cloudgrid.yaml (active fields)
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
# On disk this file is the full-annotated reference (templates/_cloudgrid.yaml.reference) with EVERY
|
|
44
|
+
# field present as a comment; only the fields below are uncommented, so it
|
|
45
|
+
# deploys to exactly these active fields.
|
|
46
|
+
name: appointment-booking
|
|
47
|
+
services:
|
|
48
|
+
web:
|
|
49
|
+
type: nextjs
|
|
50
|
+
path: /
|
|
51
|
+
needs:
|
|
52
|
+
database: true
|
|
53
|
+
vault:
|
|
54
|
+
AUTH_PROVIDER_KEY: auth-provider-key
|
|
55
|
+
STRIPE_KEY: stripe-live-key
|
|
56
|
+
STRIPE_WEBHOOK_SECRET: stripe-webhook-secret
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
> **Capability:** `needs: { database: true }` → the deployer provisions Mongo and
|
|
60
|
+
> injects `DATABASE_MONGODB_URL` (+ legacy `MONGODB_URL`). The `vault:` block maps
|
|
61
|
+
> auth/Stripe secrets to env vars — the CloudGrid-correct way to inject
|
|
62
|
+
> credentials. `requires:` is the deprecated v1 alias; don't mix it with `needs:`.
|
|
63
|
+
> A `reminders` cron service is designed (commented) but cron deploy is PENDING
|
|
64
|
+
> #1543. See the capability-map for the full injection table.
|
|
65
|
+
|
|
66
|
+
## Deploy (async, local edition)
|
|
67
|
+
|
|
68
|
+
`gridctl_init` first (creates the entity + link.json), write the app under
|
|
69
|
+
`services/web/`, set the vault secrets with `gridctl_secrets`, `gridctl_plug`
|
|
70
|
+
(async — poll `gridctl_status` to a live URL). If taking deposits, register the
|
|
71
|
+
`/api/webhook` URL in Stripe and re-plug. Re-plug the same entity to update the
|
|
72
|
+
same URL.
|