@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,191 @@
|
|
|
1
|
+
# AGENTS.md — subscription-management (BLUEPRINT)
|
|
2
|
+
|
|
3
|
+
This is a **blueprint**, not runnable code. It tells an agent how to build a
|
|
4
|
+
self-serve subscription-management app correctly on CloudGrid: a Next.js app
|
|
5
|
+
where a signed-in customer sees their current plan, changes/upgrades/downgrades
|
|
6
|
+
or cancels it, and manages billing (card, invoices) through the Stripe Billing
|
|
7
|
+
Portal — with a Stripe webhook keeping local subscription state in sync, and
|
|
8
|
+
Mongo for persistence. Read this whole file, then build the app under
|
|
9
|
+
`services/web/` following the structure below. Do not skip the CloudGrid wiring
|
|
10
|
+
rules — they are what make it deploy.
|
|
11
|
+
|
|
12
|
+
Scope note: this is the **manage-what-you-already-have** surface (view plan,
|
|
13
|
+
switch plan, update payment method, cancel), not the acquisition funnel. If the
|
|
14
|
+
user wants the *sign-up + paywall + gated content* flow, that is the
|
|
15
|
+
`membership-site` blueprint; this one owns the ongoing plan/billing lifecycle.
|
|
16
|
+
The two share the same Stripe + Mongo wiring.
|
|
17
|
+
|
|
18
|
+
The proven persistent shape is `app-with-data` (Next.js + Mongo). This blueprint
|
|
19
|
+
extends it with Stripe subscriptions + the Billing Portal. Fetch that template
|
|
20
|
+
for the Mongo lazy-client and App-Router API pattern:
|
|
21
|
+
`gridctl_fetch("template", "app-with-data")`.
|
|
22
|
+
|
|
23
|
+
## 1. File tree
|
|
24
|
+
|
|
25
|
+
Build exactly this layout. **App code MUST live under `services/web/`** — the
|
|
26
|
+
service is named `web`, so the CLI looks for `services/web/`. `path: /` in
|
|
27
|
+
`cloudgrid.yaml` is the URL mount, NOT the filesystem path. Files at the repo
|
|
28
|
+
root fail with `Error: Service directory not found: …/services/web`.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
cloudgrid.yaml # name + services.web (nextjs) + needs:{database:true} + vault: (Stripe secrets)
|
|
32
|
+
services/web/package.json # next, react, react-dom, mongodb, stripe (+ auth SDK if used, e.g. @clerk/nextjs)
|
|
33
|
+
services/web/middleware.js # auth middleware: protects /account/* + the subscription API routes
|
|
34
|
+
services/web/lib/db.js # lazy Mongo client from DATABASE_MONGODB_URL (legacy MONGODB_URL fallback)
|
|
35
|
+
services/web/lib/stripe.js # lazy Stripe client from process.env.STRIPE_KEY (never top-level)
|
|
36
|
+
services/web/lib/subscription.js # getSubscription(customerRef): read current plan/status from subscriptions collection
|
|
37
|
+
services/web/lib/plans.js # plan catalog: { key, name, price, stripePriceId } for each plan (upgrade/downgrade options)
|
|
38
|
+
services/web/app/layout.js # root layout (+ auth provider wrapper if the SDK needs one)
|
|
39
|
+
services/web/app/page.js # entry: link to /account (or the plans view for the unsubscribed)
|
|
40
|
+
services/web/app/account/page.js # THE dashboard: current plan, status, renewal date, "Change plan" + "Manage billing" + "Cancel"
|
|
41
|
+
services/web/app/account/plans.js # client component: plan cards + change-plan / cancel buttons calling the API
|
|
42
|
+
services/web/app/api/subscription/route.js # GET current subscription; PATCH to change plan (Stripe subscription update, prorated)
|
|
43
|
+
services/web/app/api/subscription/cancel/route.js # POST: cancel at period end (or resume) via Stripe
|
|
44
|
+
services/web/app/api/portal/route.js # POST: create a Stripe Billing Portal session → return url (card, invoices, receipts)
|
|
45
|
+
services/web/app/api/webhook/route.js # POST: Stripe webhook — upsert subscription state on subscription/invoice events
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 2. Mongo collections + fields
|
|
49
|
+
|
|
50
|
+
The grid provisions Mongo from `needs: { database: true }`. Use two collections:
|
|
51
|
+
|
|
52
|
+
**`customers`** — links your app's user to their Stripe customer. (If an auth SDK
|
|
53
|
+
owns identity you may not need a separate profile store, but you DO need the
|
|
54
|
+
user↔`stripeCustomerId` mapping somewhere — keep it here.)
|
|
55
|
+
- `_id` (ObjectId)
|
|
56
|
+
- `userRef` (string, indexed) — your app's user id (auth provider `sub`, or email)
|
|
57
|
+
- `email` (string)
|
|
58
|
+
- `stripeCustomerId` (string, indexed) — the Stripe customer this user maps to
|
|
59
|
+
- `createdAt` (Date)
|
|
60
|
+
|
|
61
|
+
**`subscriptions`** — the local mirror of Stripe subscription state. The webhook
|
|
62
|
+
writes it; the account dashboard and plan-change API read it. Never trust the
|
|
63
|
+
client for plan/status — read this (kept current by the webhook).
|
|
64
|
+
- `_id` (ObjectId)
|
|
65
|
+
- `userRef` (string, indexed)
|
|
66
|
+
- `stripeCustomerId` (string, indexed)
|
|
67
|
+
- `stripeSubscriptionId` (string, indexed)
|
|
68
|
+
- `planKey` (string) — matches a `key` in `lib/plans.js` (e.g. `"basic"`, `"pro"`)
|
|
69
|
+
- `stripePriceId` (string) — the active Stripe price
|
|
70
|
+
- `status` (string) — `"active" | "trialing" | "past_due" | "canceled" | "incomplete"`
|
|
71
|
+
- `cancelAtPeriodEnd` (boolean) — user asked to cancel but access runs to period end
|
|
72
|
+
- `currentPeriodEnd` (Date) — renewal / lapse date shown on the dashboard
|
|
73
|
+
- `updatedAt` (Date)
|
|
74
|
+
|
|
75
|
+
## 3. How CloudGrid injects everything (the wiring that matters)
|
|
76
|
+
|
|
77
|
+
- **Mongo** — declared by `needs: { database: true }`. The deployer provisions
|
|
78
|
+
shared Mongo and injects the connection string as **`DATABASE_MONGODB_URL`**
|
|
79
|
+
(plus the legacy **`MONGODB_URL`** alias) at runtime and under `grid dev`.
|
|
80
|
+
Read `process.env.DATABASE_MONGODB_URL || process.env.MONGODB_URL` **LAZILY,
|
|
81
|
+
inside the getter** in `lib/db.js` — never at module top level, or `next build`
|
|
82
|
+
fails when it imports the module for route analysis before the grid injects
|
|
83
|
+
the var. Never hardcode a connection string. Never set `needs:` and `requires:`
|
|
84
|
+
together — `requires:` is the deprecated v1 alias.
|
|
85
|
+
- **Secrets (Stripe) → env vars via the `vault:` block.** In `cloudgrid.yaml`
|
|
86
|
+
the `vault:` block maps each env var to a vault item key:
|
|
87
|
+
```yaml
|
|
88
|
+
vault:
|
|
89
|
+
STRIPE_KEY: stripe-live-key
|
|
90
|
+
STRIPE_WEBHOOK_SECRET: stripe-webhook-secret
|
|
91
|
+
```
|
|
92
|
+
Set the vault items ONCE with `gridctl_secrets` (or `grid secrets set`), then
|
|
93
|
+
the deployer injects each as the named env var (`process.env.STRIPE_KEY`, etc.)
|
|
94
|
+
at runtime and under `grid dev`. Do NOT commit keys; do NOT set them in
|
|
95
|
+
`services.web.env` (that block is for non-secret config only). Read them lazily
|
|
96
|
+
inside `lib/stripe.js` — same rule as the DB. If you add an auth SDK, add
|
|
97
|
+
`AUTH_PROVIDER_KEY: auth-provider-key` to the vault block too.
|
|
98
|
+
- **Public / non-secret config** — the Stripe *publishable* key
|
|
99
|
+
(`NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`) and price ids are not secret; put them
|
|
100
|
+
in the non-secret `services.web.env` block (or a build-time env), not the
|
|
101
|
+
vault. An auth SDK's publishable key goes here too.
|
|
102
|
+
- **AI (optional)** — if you add AI features (e.g. churn-reason summaries),
|
|
103
|
+
declare `needs: { ai: true }` and call the gateway at
|
|
104
|
+
`process.env.AI_GATEWAY_URL` via `@cloudgrid-io/ai`. Not required for this
|
|
105
|
+
blueprint.
|
|
106
|
+
|
|
107
|
+
## 4. Wiring auth + payments
|
|
108
|
+
|
|
109
|
+
**Auth (identify the customer).** Every subscription action must be tied to a
|
|
110
|
+
known user — otherwise anyone could change anyone's plan.
|
|
111
|
+
1. Add an auth SDK to `services/web/package.json` (e.g. `@clerk/nextjs`, or
|
|
112
|
+
Auth0) OR use your own session. Server key from the vault
|
|
113
|
+
(`process.env.AUTH_PROVIDER_KEY`); publishable key from `services.web.env` as
|
|
114
|
+
`NEXT_PUBLIC_...`.
|
|
115
|
+
2. `services/web/middleware.js` protects `/account/*` and the
|
|
116
|
+
`/api/subscription*` + `/api/portal` routes — unauthenticated users get
|
|
117
|
+
redirected to sign-in. Resolve the current `userRef` server-side in each API
|
|
118
|
+
route and only ever act on THAT user's `stripeCustomerId`.
|
|
119
|
+
|
|
120
|
+
**Payments (Stripe subscriptions + Billing Portal).**
|
|
121
|
+
1. Add `stripe` to `package.json`. Build a lazy Stripe client in `lib/stripe.js`
|
|
122
|
+
reading `process.env.STRIPE_KEY` inside the getter.
|
|
123
|
+
2. **Plan catalog** — `lib/plans.js` is the single source of which plans exist and
|
|
124
|
+
their `stripePriceId`s. The dashboard renders from it; the change-plan API
|
|
125
|
+
validates the requested plan against it (never accept an arbitrary price id
|
|
126
|
+
from the client).
|
|
127
|
+
3. **Change plan** — `app/api/subscription/route.js` PATCH: resolve the user's
|
|
128
|
+
`stripeSubscriptionId` from Mongo, look up the target `stripePriceId` from
|
|
129
|
+
`lib/plans.js`, call Stripe `subscriptions.update` swapping the item's price
|
|
130
|
+
with `proration_behavior` set as you want (e.g. `create_prorations`). Do NOT
|
|
131
|
+
write the new plan to Mongo here — let the resulting webhook be the source of
|
|
132
|
+
truth so Stripe and Mongo never diverge.
|
|
133
|
+
4. **Cancel / resume** — `app/api/subscription/cancel/route.js` POST: set
|
|
134
|
+
`cancel_at_period_end: true` (or `false` to resume) on the Stripe
|
|
135
|
+
subscription. Again, the webhook reconciles Mongo.
|
|
136
|
+
5. **Billing Portal** — `app/api/portal/route.js` POST: create a Stripe Billing
|
|
137
|
+
Portal session (`billingPortal.sessions.create`) for the user's
|
|
138
|
+
`stripeCustomerId` with a `return_url` back to `/account`, and return
|
|
139
|
+
`session.url`. The "Manage billing" button POSTs here and redirects the
|
|
140
|
+
browser to the returned URL — Stripe hosts card updates, invoices, and
|
|
141
|
+
receipts, so you don't rebuild them.
|
|
142
|
+
6. **Webhook (source of truth)** — `app/api/webhook/route.js` POST: verify the
|
|
143
|
+
signature with `process.env.STRIPE_WEBHOOK_SECRET` (read the RAW request body
|
|
144
|
+
— do not JSON-parse before verifying). On `customer.subscription.created`,
|
|
145
|
+
`customer.subscription.updated`, `customer.subscription.deleted`, and
|
|
146
|
+
`invoice.payment_failed` / `invoice.paid`, upsert the `subscriptions` doc
|
|
147
|
+
keyed by `stripeSubscriptionId` with the new `planKey` / `stripePriceId` /
|
|
148
|
+
`status` / `cancelAtPeriodEnd` / `currentPeriodEnd`. Register this route's
|
|
149
|
+
public URL as the webhook endpoint in the Stripe dashboard after deploy.
|
|
150
|
+
|
|
151
|
+
**Reading state (the dashboard).**
|
|
152
|
+
- `lib/subscription.js` exports `getSubscription(userRef)` → reads the
|
|
153
|
+
`subscriptions` collection and returns the current plan/status/renewal.
|
|
154
|
+
- `app/account/page.js` is a server component: resolve the signed-in `userRef`,
|
|
155
|
+
call `getSubscription`, and render the current plan, status, renewal date, and
|
|
156
|
+
the Change-plan / Manage-billing / Cancel actions. Read state server-side from
|
|
157
|
+
Mongo; never derive entitlement purely on the client.
|
|
158
|
+
|
|
159
|
+
## 5. Deploy steps
|
|
160
|
+
|
|
161
|
+
1. `gridctl_login_status` → `gridctl_login` if needed. Respect the grid picker
|
|
162
|
+
(ask which grid if the user has more than one).
|
|
163
|
+
2. `gridctl_init` an app `<name>` FIRST — it creates the entity, writes
|
|
164
|
+
`.cloudgrid/link.json`, and a `cloudgrid.yaml` with empty `services: {}`.
|
|
165
|
+
`plug` needs a linked directory.
|
|
166
|
+
3. Write the app under `services/web/` and set `cloudgrid.yaml` to the active
|
|
167
|
+
shape: `name` + `services.web{type: nextjs, path: /}` + `needs:{database:true}`
|
|
168
|
+
+ the `vault:` block.
|
|
169
|
+
4. Set the secrets: `gridctl_secrets` for `stripe-live-key`,
|
|
170
|
+
`stripe-webhook-secret` (and `auth-provider-key` if you use an auth SDK) — the
|
|
171
|
+
vault item keys the `vault:` block maps from. Non-secret config (Stripe
|
|
172
|
+
publishable key, price ids, auth publishable key) → `gridctl_env` /
|
|
173
|
+
`services.web.env`. Do NOT set `DATABASE_MONGODB_URL` yourself — the grid
|
|
174
|
+
injects it.
|
|
175
|
+
5. `gridctl_plug` to deploy. A runtime deploy is **ASYNC** — the first response
|
|
176
|
+
is `status: building`, not a live URL. Poll `gridctl_status` (or the returned
|
|
177
|
+
poll_url) until live; surface a liveness signal while it builds, never a bare
|
|
178
|
+
silent wait.
|
|
179
|
+
6. Once live, add the `/api/webhook` URL as the Stripe webhook endpoint, copy
|
|
180
|
+
the signing secret into the `stripe-webhook-secret` vault item, and configure
|
|
181
|
+
the Billing Portal in the Stripe dashboard, then re-plug. Return the live app
|
|
182
|
+
URL (not the build/log link).
|
|
183
|
+
|
|
184
|
+
## 6. Edition note
|
|
185
|
+
|
|
186
|
+
A subscription-management app is a built + deployed runtime container, so it
|
|
187
|
+
requires the **local edition** (Claude Desktop / Claude Code) or the CLI. The
|
|
188
|
+
**hosted** edition (Claude Web / hosted MCP) is inline-only and can only publish
|
|
189
|
+
static pages — it CANNOT build this app. On hosted, say so plainly and offer a
|
|
190
|
+
static pricing/plans page (via `gridctl_drop`) instead, then stop the runtime
|
|
191
|
+
path.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# subscription-management template — BLUEPRINT
|
|
2
|
+
|
|
3
|
+
A self-serve subscription-management app: a Next.js app where a signed-in
|
|
4
|
+
customer sees their current plan, upgrades/downgrades or cancels it, and manages
|
|
5
|
+
billing (card, invoices) through the Stripe Billing Portal — with a Stripe
|
|
6
|
+
webhook keeping local subscription state in sync, and grid-shared Mongo for
|
|
7
|
+
persistence. This is a **blueprint** — it ships the `cloudgrid.yaml` and a
|
|
8
|
+
structure guide (`AGENTS.md`), not finished app code. Read `AGENTS.md` for the
|
|
9
|
+
file tree, Mongo collections, and the CloudGrid wiring (Mongo via
|
|
10
|
+
`needs:{database:true}` → `DATABASE_MONGODB_URL`; Stripe secrets via the `vault:`
|
|
11
|
+
block → env vars), then build the app under `services/web/` following it, adapt
|
|
12
|
+
the plans/fields to the user, and deploy (async — poll to a live URL). It
|
|
13
|
+
requires the local edition.
|
|
14
|
+
|
|
15
|
+
- `cloudgrid.yaml` — active: `name` + `services.web{type: nextjs, path: /}` +
|
|
16
|
+
`needs:{database:true}` + `vault:` (Stripe secrets → env vars).
|
|
17
|
+
- `AGENTS.md` — the structure guide: file tree, collections, CloudGrid injection,
|
|
18
|
+
Stripe change-plan / cancel / billing-portal / webhook wiring, deploy steps,
|
|
19
|
+
edition note.
|
|
20
|
+
|
|
21
|
+
**blueprint: structure + cloudgrid.yaml, adapt and build.**
|
|
@@ -0,0 +1,236 @@
|
|
|
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: subscription-management
|
|
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
|
+
# Self-serve subscription management needs Stripe secrets injected as env vars —
|
|
122
|
+
# this is the CloudGrid-correct way. Set the vault items once (grid secrets set),
|
|
123
|
+
# then the deployer injects each as the named env var at runtime and under
|
|
124
|
+
# `grid dev`. Add AUTH_PROVIDER_KEY here too if you use an auth SDK (e.g. Clerk).
|
|
125
|
+
vault:
|
|
126
|
+
STRIPE_KEY: stripe-live-key # Stripe secret key (billing portal sessions + subscription updates)
|
|
127
|
+
STRIPE_WEBHOOK_SECRET: stripe-webhook-secret # verifies Stripe webhook signatures
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# ─── CONNECTORS AND HOOKS ──────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
# connectors:
|
|
133
|
+
# - id: team-slack
|
|
134
|
+
# target: org # 'system' | 'org'.
|
|
135
|
+
# channel: "#deploys"
|
|
136
|
+
# hooks:
|
|
137
|
+
# - on: deploy.failed # release.published | deploy.failed | feedback.received | entity.created
|
|
138
|
+
# via: team-slack
|
|
139
|
+
# template: "Deploy failed for {entity_name}: {error}"
|
|
140
|
+
# channel: "#alerts"
|
|
141
|
+
# triggers:
|
|
142
|
+
# - from: team-slack
|
|
143
|
+
# event: message
|
|
144
|
+
# channel: "#support"
|
|
145
|
+
# route: /webhooks/slack
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# ─── LOCAL DEVELOPMENT ──────────────────────────────────────────────────────
|
|
149
|
+
|
|
150
|
+
# Config for `grid dev`. Redact fields in dev data snapshots.
|
|
151
|
+
# dev:
|
|
152
|
+
# snapshot:
|
|
153
|
+
# mask:
|
|
154
|
+
# - users.email
|
|
155
|
+
# - users.phone
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# ─── AGENT METADATA ────────────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
# An agent is an app with kind: agent (above) and an agent: block.
|
|
161
|
+
# agent:
|
|
162
|
+
# purpose: Sync customer data from external CRM every night
|
|
163
|
+
# schedule: "0 2 * * *"
|
|
164
|
+
# trigger: webhook
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# ─── PRIVATE RESOURCE AUTO-DEPENDENCIES ────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
# When true (default), private resources are auto-injected as depends_on.
|
|
170
|
+
# auto_depends_on_private_requires: true
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# ─── SERVICES (REQUIRED) ───────────────────────────────────────────────────
|
|
174
|
+
#
|
|
175
|
+
# At least one service is required. Key = service name (slug rules).
|
|
176
|
+
# Types: node, nextjs, python, static, cron.
|
|
177
|
+
#
|
|
178
|
+
services:
|
|
179
|
+
web:
|
|
180
|
+
# type (REQUIRED): node | nextjs | python | static | cron
|
|
181
|
+
type: nextjs
|
|
182
|
+
# HTTP route: '/' | '/api' | false (internal) | omitted (=false + warning).
|
|
183
|
+
# Only one service per entity can claim '/'.
|
|
184
|
+
path: /
|
|
185
|
+
# Container port (default 8080; read process.env.PORT). Not for cron.
|
|
186
|
+
# port: 3000
|
|
187
|
+
# nextjs only: base_image: distroless (default) | alpine
|
|
188
|
+
# base_image: distroless
|
|
189
|
+
# node only: lang: javascript (default) | typescript
|
|
190
|
+
# lang: typescript
|
|
191
|
+
# Custom source location (default services/<name>/). '.' = project root.
|
|
192
|
+
# source:
|
|
193
|
+
# path: src/worker
|
|
194
|
+
# Health probe: false/omitted (TCP) | true (/health) | "/path" | {path,expected}
|
|
195
|
+
# health:
|
|
196
|
+
# path: /api/health
|
|
197
|
+
# expected: "200"
|
|
198
|
+
# Static runtime env vars (strings). Reserved: PORT, APP_NAME, SERVICE_NAME,
|
|
199
|
+
# NODE_ENV, MONGODB_URL, REDIS_URL, AI_GATEWAY_URL, N8N_WEBHOOK_URL, CLOUDGRID_*.
|
|
200
|
+
# env:
|
|
201
|
+
# LOG_LEVEL: info
|
|
202
|
+
# Sibling services/private resources that must be Ready first (no cron, no cycles).
|
|
203
|
+
# depends_on:
|
|
204
|
+
# - worker
|
|
205
|
+
# Per-service needs override (merges with app-level needs).
|
|
206
|
+
# needs:
|
|
207
|
+
# queue: true
|
|
208
|
+
# Static-only build step:
|
|
209
|
+
# build:
|
|
210
|
+
# command: npm run build
|
|
211
|
+
# output: dist
|
|
212
|
+
# env:
|
|
213
|
+
# VITE_API_URL: https://api.example.com
|
|
214
|
+
# node_version: "22" # static build step: '18'|'20'|'22'|'24' (quoted)
|
|
215
|
+
# Cron-only: schedule (REQUIRED), timezone (UTC|EST|PST), run (job | https URL)
|
|
216
|
+
# schedule: "0 9 * * 1"
|
|
217
|
+
# timezone: UTC
|
|
218
|
+
# run: job
|
|
219
|
+
# Verbose per-service persistence (prefer needs.disk):
|
|
220
|
+
# persist:
|
|
221
|
+
# - name: scratch
|
|
222
|
+
# path: /tmp/scratch
|
|
223
|
+
# size: 500Mi
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
needs:
|
|
227
|
+
database: true
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# ============================================================================
|
|
231
|
+
# NOTES
|
|
232
|
+
# - NOT here: org:/entity_id: (→ .cloudgrid/link.json), secrets (→ grid secrets set),
|
|
233
|
+
# Dockerfile (platform generates from services.*.type).
|
|
234
|
+
# - Deploy: grid plug | Local with grid resources: grid dev
|
|
235
|
+
# - Full reference: docs/cloudgrid-yaml-reference.md | CLI: docs/cli-reference.md
|
|
236
|
+
# ============================================================================
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Template: subscription-management (BLUEPRINT — Next.js + Stripe + Mongo)
|
|
2
|
+
|
|
3
|
+
A self-serve subscription-management app. **Blueprint, not finished code**: it
|
|
4
|
+
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 signed-in customer views
|
|
6
|
+
their current plan, changes/upgrades/downgrades or cancels it, and manages
|
|
7
|
+
billing through the Stripe Billing Portal, with a Stripe webhook syncing local
|
|
8
|
+
state and grid-shared Mongo. Read `AGENTS.md`, build the app under
|
|
9
|
+
`services/web/`, adapt plans/fields, then deploy (async — poll to a live URL).
|
|
10
|
+
Local edition only.
|
|
11
|
+
|
|
12
|
+
This is the **manage-what-you-already-have** surface (view / switch plan, update
|
|
13
|
+
payment method, cancel). For the sign-up + paywall + gated-content acquisition
|
|
14
|
+
flow, use the `membership-site` blueprint — the two share the same Stripe + Mongo
|
|
15
|
+
wiring.
|
|
16
|
+
|
|
17
|
+
**Fetch the bundle:**
|
|
18
|
+
- `gridctl_fetch("template", "subscription-management")` — this blueprint (`cloudgrid.yaml` + `AGENTS.md`).
|
|
19
|
+
- `gridctl_fetch("template", "app-with-data")` — the proven Next.js + Mongo shape to extend (lazy db client, App-Router API).
|
|
20
|
+
|
|
21
|
+
**Key rules:**
|
|
22
|
+
|
|
23
|
+
1. **Blueprint — read `AGENTS.md` first.** It has the file tree, Mongo
|
|
24
|
+
collections (`customers`, `subscriptions`), CloudGrid injection table, and the
|
|
25
|
+
Stripe change-plan / cancel / billing-portal / webhook wiring. Build following
|
|
26
|
+
it; do not invent structure.
|
|
27
|
+
2. **App code MUST live under `services/web/`.** `path: /` is the URL mount, NOT
|
|
28
|
+
the filesystem path. Root files fail with `Service directory not found`.
|
|
29
|
+
3. **Mongo via `needs:{database:true}`** → the grid injects
|
|
30
|
+
`DATABASE_MONGODB_URL` (legacy `MONGODB_URL` fallback). Read it LAZILY inside
|
|
31
|
+
the getter, never at module top level (top-level read fails `next build`).
|
|
32
|
+
4. **Secrets via the `vault:` block** → env vars. `STRIPE_KEY` and
|
|
33
|
+
`STRIPE_WEBHOOK_SECRET` map to vault items; set them with `gridctl_secrets`,
|
|
34
|
+
and the deployer injects them at runtime. Read lazily; do not commit keys or
|
|
35
|
+
put secrets in `services.web.env` (publishable key + price ids go there).
|
|
36
|
+
5. **The webhook is the source of truth.** Change-plan / cancel APIs call Stripe;
|
|
37
|
+
the `/api/webhook` route reconciles the `subscriptions` collection so Stripe
|
|
38
|
+
and Mongo never diverge. Read plan/status server-side from Mongo, never trust
|
|
39
|
+
the client. Validate requested plans against `lib/plans.js`.
|
|
40
|
+
6. **Never set `needs:` and `requires:` together** — `requires:` is the
|
|
41
|
+
deprecated v1 alias.
|
|
42
|
+
|
|
43
|
+
## cloudgrid.yaml (active fields)
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
# On disk this file is the full-annotated reference (templates/_cloudgrid.yaml.reference) with EVERY
|
|
47
|
+
# field present as a comment; only the fields below are uncommented, so it
|
|
48
|
+
# deploys to exactly these active fields.
|
|
49
|
+
name: subscription-management
|
|
50
|
+
services:
|
|
51
|
+
web:
|
|
52
|
+
type: nextjs
|
|
53
|
+
path: /
|
|
54
|
+
needs:
|
|
55
|
+
database: true
|
|
56
|
+
vault:
|
|
57
|
+
STRIPE_KEY: stripe-live-key
|
|
58
|
+
STRIPE_WEBHOOK_SECRET: stripe-webhook-secret
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
> **Capability:** `needs: { database: true }` → the deployer provisions Mongo and
|
|
62
|
+
> injects `DATABASE_MONGODB_URL` (+ legacy `MONGODB_URL`). The `vault:` block maps
|
|
63
|
+
> Stripe secrets to env vars — the CloudGrid-correct way to inject credentials.
|
|
64
|
+
> `requires:` is the deprecated v1 alias; don't mix it with `needs:`. See the
|
|
65
|
+
> capability-map for the full injection table.
|
|
66
|
+
|
|
67
|
+
## Deploy (async, local edition)
|
|
68
|
+
|
|
69
|
+
`gridctl_init` first (creates the entity + link.json), write the app under
|
|
70
|
+
`services/web/`, set the vault secrets with `gridctl_secrets`, `gridctl_plug`
|
|
71
|
+
(async — poll `gridctl_status` to a live URL), then register the `/api/webhook`
|
|
72
|
+
URL in Stripe, configure the Billing Portal, and re-plug. Re-plug the same entity
|
|
73
|
+
to update the same URL.
|