@cloudgrid-io/mcp 0.12.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 +82 -2
- package/src/corpus/examples/crm/index.md +273 -0
- package/src/corpus/examples/kanban/index.md +256 -0
- package/src/corpus/templates/_cloudgrid.yaml.reference +228 -0
- package/src/corpus/templates/admin-dashboard/README.md +75 -0
- package/src/corpus/templates/admin-dashboard/cloudgrid.yaml +233 -0
- package/src/corpus/templates/admin-dashboard/index.md +81 -0
- package/src/corpus/templates/admin-dashboard/services/web/app/api/orders/route.js +64 -0
- package/src/corpus/templates/admin-dashboard/services/web/app/api/users/route.js +63 -0
- package/src/corpus/templates/admin-dashboard/services/web/app/layout.js +39 -0
- package/src/corpus/templates/admin-dashboard/services/web/app/page.js +73 -0
- package/src/corpus/templates/admin-dashboard/services/web/app/resource-table.js +94 -0
- package/src/corpus/templates/admin-dashboard/services/web/lib/db.js +32 -0
- package/src/corpus/templates/admin-dashboard/services/web/package.json +16 -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/README.md +28 -0
- package/src/corpus/templates/api-docs/cloudgrid.yaml +228 -0
- package/src/corpus/templates/api-docs/index.html +136 -0
- package/src/corpus/templates/api-docs/index.md +28 -0
- 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/README.md +27 -0
- package/src/corpus/templates/changelog/cloudgrid.yaml +228 -0
- package/src/corpus/templates/changelog/index.html +80 -0
- package/src/corpus/templates/changelog/index.md +28 -0
- 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/README.md +72 -0
- package/src/corpus/templates/crm/cloudgrid.yaml +233 -0
- package/src/corpus/templates/crm/index.md +71 -0
- package/src/corpus/templates/crm/services/web/app/api/contacts/route.js +80 -0
- package/src/corpus/templates/crm/services/web/app/contact-manager.js +102 -0
- package/src/corpus/templates/crm/services/web/app/layout.js +35 -0
- package/src/corpus/templates/crm/services/web/app/page.js +34 -0
- package/src/corpus/templates/crm/services/web/lib/db.js +32 -0
- package/src/corpus/templates/crm/services/web/package.json +16 -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/README.md +28 -0
- package/src/corpus/templates/docs-site/cloudgrid.yaml +228 -0
- package/src/corpus/templates/docs-site/index.html +122 -0
- package/src/corpus/templates/docs-site/index.md +28 -0
- 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/README.md +72 -0
- package/src/corpus/templates/kanban/cloudgrid.yaml +233 -0
- package/src/corpus/templates/kanban/index.md +71 -0
- package/src/corpus/templates/kanban/services/web/app/api/cards/route.js +70 -0
- package/src/corpus/templates/kanban/services/web/app/board.js +93 -0
- package/src/corpus/templates/kanban/services/web/app/layout.js +37 -0
- package/src/corpus/templates/kanban/services/web/app/page.js +32 -0
- package/src/corpus/templates/kanban/services/web/lib/db.js +32 -0
- package/src/corpus/templates/kanban/services/web/package.json +16 -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/README.md +29 -0
- package/src/corpus/templates/portfolio/cloudgrid.yaml +228 -0
- package/src/corpus/templates/portfolio/index.html +126 -0
- package/src/corpus/templates/portfolio/index.md +28 -0
- 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/README.md +30 -0
- package/src/corpus/templates/saas-marketing/cloudgrid.yaml +228 -0
- package/src/corpus/templates/saas-marketing/index.html +212 -0
- package/src/corpus/templates/saas-marketing/index.md +28 -0
- package/src/corpus/templates/status-page/README.md +28 -0
- package/src/corpus/templates/status-page/cloudgrid.yaml +228 -0
- package/src/corpus/templates/status-page/index.html +117 -0
- package/src/corpus/templates/status-page/index.md +28 -0
- 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/README.md +72 -0
- package/src/corpus/templates/task-manager/cloudgrid.yaml +233 -0
- package/src/corpus/templates/task-manager/index.md +71 -0
- package/src/corpus/templates/task-manager/services/web/app/api/tasks/route.js +77 -0
- package/src/corpus/templates/task-manager/services/web/app/layout.js +39 -0
- package/src/corpus/templates/task-manager/services/web/app/page.js +33 -0
- package/src/corpus/templates/task-manager/services/web/app/task-list.js +110 -0
- package/src/corpus/templates/task-manager/services/web/lib/db.js +32 -0
- package/src/corpus/templates/task-manager/services/web/package.json +16 -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/README.md +38 -0
- package/src/corpus/templates/waitlist/cloudgrid.yaml +228 -0
- package/src/corpus/templates/waitlist/index.html +69 -0
- package/src/corpus/templates/waitlist/index.md +39 -0
- package/src/corpus/templates/web-app/cloudgrid.yaml +228 -4
- package/src/corpus/templates/web-app/index.md +3 -5
- package/src/corpus/workflows/admin-dashboard.md +102 -0
- 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/api-docs.md +36 -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/changelog.md +33 -0
- package/src/corpus/workflows/company-website.md +46 -0
- package/src/corpus/workflows/course-platform.md +126 -0
- package/src/corpus/workflows/crm.md +101 -0
- package/src/corpus/workflows/directory.md +101 -0
- package/src/corpus/workflows/docs-site.md +35 -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/kanban.md +102 -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/portfolio.md +35 -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/saas-marketing.md +37 -0
- package/src/corpus/workflows/status-page.md +35 -0
- package/src/corpus/workflows/subscription-management.md +141 -0
- package/src/corpus/workflows/task-manager.md +101 -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
- package/src/corpus/workflows/waitlist.md +42 -0
|
@@ -1,10 +1,234 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
#
|
|
1
|
+
# ============================================================================
|
|
2
|
+
# cloudgrid.yaml — Complete Example
|
|
3
|
+
# ============================================================================
|
|
4
4
|
#
|
|
5
|
-
#
|
|
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
|
+
# THIS TEMPLATE (landing-page): a single self-contained static page. The active fields
|
|
17
|
+
# are exactly name + services.web{type: static, path: /}; there are no needs.
|
|
18
|
+
# This cloudgrid.yaml is the reference for plugging it as an OWNED static
|
|
19
|
+
# runtime; the fast path is to deploy it as an INSPIRATION via gridctl_drop
|
|
20
|
+
# (instant, and works on the hosted edition too).
|
|
21
|
+
# ============================================================================
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ─── IDENTITY ───────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
# Entity slug (REQUIRED). 2-42 chars, lowercase alphanumeric + hyphens.
|
|
27
|
+
# Must start and end with a letter or digit.
|
|
28
|
+
# Becomes part of your public URL: <name>-<4hex>.<org>.cloudgrid.io
|
|
6
29
|
name: landing-page
|
|
30
|
+
|
|
31
|
+
# One-line summary. Max 280 chars. If omitted, Grid Brain auto-generates one.
|
|
32
|
+
# description: Order processing API for the e-commerce platform
|
|
33
|
+
|
|
34
|
+
# Single emoji or short text shown as the entity icon. Max 64 chars.
|
|
35
|
+
# icon: "📦"
|
|
36
|
+
|
|
37
|
+
# Entity type: 'app' (default) or 'agent'. An agent is an app with an agent: block.
|
|
38
|
+
# kind: app
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# ─── NETWORKING ─────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
# Whether this entity serves public HTTP traffic.
|
|
44
|
+
# true = public URL + Ingress (default). false = internal only.
|
|
45
|
+
# expose: true
|
|
46
|
+
|
|
47
|
+
# Additional domain names this entity serves on (the platform URL is always active).
|
|
48
|
+
# custom_domains:
|
|
49
|
+
# - orders.example.com
|
|
50
|
+
# - shop.example.com
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ─── HEALTH PROBE (entity-level override) ──────────────────────────────────
|
|
54
|
+
|
|
55
|
+
# Override the default health check for the entire entity.
|
|
56
|
+
# probe:
|
|
57
|
+
# path: /healthz # HTTP path to probe (default: /).
|
|
58
|
+
# expected: "<500" # '<500' (default), '200', '2xx'.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ─── DEPLOY NOTIFICATIONS ──────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
# Slack notification to the org's default channel on deploy failure.
|
|
64
|
+
# true = notify (default), false = silent.
|
|
65
|
+
# notify: true
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ─── SCALING ────────────────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
# Replica scaling intent.
|
|
71
|
+
# 'auto' — platform decides from the grid tier (default).
|
|
72
|
+
# 'alert' — single-replica, emit a SPOF warning at plug time.
|
|
73
|
+
# 1-10 — explicit replica count, clamped to the grid max.
|
|
74
|
+
# scale: auto
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ─── INFRASTRUCTURE NEEDS ──────────────────────────────────────────────────
|
|
78
|
+
#
|
|
79
|
+
# Declare infrastructure; the platform provisions it and injects connection
|
|
80
|
+
# details as env vars. Nine needs: database, cache, kv, queue, pubsub, vector,
|
|
81
|
+
# object_storage, disk, ai. Simplest form is `true`.
|
|
82
|
+
#
|
|
83
|
+
# needs:
|
|
84
|
+
# # database — MongoDB. Injects DATABASE_MONGODB_URL (+ legacy MONGODB_URL).
|
|
85
|
+
# # true | pool | dedicated | { tier: external, secret: MY_DB }
|
|
86
|
+
# database: true
|
|
87
|
+
# # cache — Redis, LRU eviction (derived data). Injects CACHE_REDIS_URL (+ REDIS_URL).
|
|
88
|
+
# # true | redis | { engine: external, secret: MY_REDIS_URL }
|
|
89
|
+
# cache: true
|
|
90
|
+
# # kv — Redis, no eviction (durable: flags, idempotency). Injects KV_REDIS_URL.
|
|
91
|
+
# kv: true
|
|
92
|
+
# # queue — Redis job-queue substrate (BullMQ). Injects QUEUE_REDIS_URL.
|
|
93
|
+
# queue: true
|
|
94
|
+
# # pubsub — Redis broadcast pub/sub. Injects PUBSUB_REDIS_URL.
|
|
95
|
+
# pubsub: true
|
|
96
|
+
# # vector — pgvector on Postgres. Injects VECTOR_PGVECTOR_URL (+ PGVECTOR_URL).
|
|
97
|
+
# # true | pgvector | { engine: pgvector, dim: 1536 }
|
|
98
|
+
# vector: pgvector
|
|
99
|
+
# # object_storage — GCS bucket. Injects OBJECT_STORAGE_GCS_BUCKET, _GCS_REGION.
|
|
100
|
+
# # true | { size: 10Gi }
|
|
101
|
+
# object_storage: true
|
|
102
|
+
# # disk — persistent FS mount (PVC). Injects DISK_PATH. Pins to 1 replica.
|
|
103
|
+
# # true | { size: 1Gi, mount: /var/data } (forbidden: /proc /sys /dev)
|
|
104
|
+
# disk: true
|
|
105
|
+
# # ai — AI Gateway via @cloudgrid-io/ai. Injects AI_GATEWAY_URL. true | false.
|
|
106
|
+
# ai: true
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# ─── INTER-ENTITY COMMUNICATION ────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
# Entities this app calls (outbound). Service-account token injected per pair.
|
|
112
|
+
# calls:
|
|
113
|
+
# - org:atomic/billing-api
|
|
114
|
+
|
|
115
|
+
# Inbound caller policy — who can call YOUR entity.
|
|
116
|
+
# callers:
|
|
117
|
+
# policy: auto # 'auto' | 'manual' (default).
|
|
118
|
+
# scope: org # 'org' (default) | 'space' | 'explicit'.
|
|
119
|
+
# fallback: deny # 'deny' (default) | 'warn'.
|
|
120
|
+
# # allowed_apps: # required only when scope: explicit
|
|
121
|
+
# # - org:atomic/frontend
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ─── VAULT ──────────────────────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
# Map org vault items to env vars. Keys UPPER_SNAKE_CASE; values = vault item keys.
|
|
127
|
+
# vault:
|
|
128
|
+
# STRIPE_KEY: stripe-live-key
|
|
129
|
+
# SENDGRID_API_KEY: sendgrid-key
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# ─── CONNECTORS AND HOOKS ──────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
# connectors:
|
|
135
|
+
# - id: team-slack
|
|
136
|
+
# target: org # 'system' | 'org'.
|
|
137
|
+
# channel: "#deploys"
|
|
138
|
+
# hooks:
|
|
139
|
+
# - on: deploy.failed # release.published | deploy.failed | feedback.received | entity.created
|
|
140
|
+
# via: team-slack
|
|
141
|
+
# template: "Deploy failed for {entity_name}: {error}"
|
|
142
|
+
# channel: "#alerts"
|
|
143
|
+
# triggers:
|
|
144
|
+
# - from: team-slack
|
|
145
|
+
# event: message
|
|
146
|
+
# channel: "#support"
|
|
147
|
+
# route: /webhooks/slack
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ─── LOCAL DEVELOPMENT ──────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
# Config for `grid dev`. Redact fields in dev data snapshots.
|
|
153
|
+
# dev:
|
|
154
|
+
# snapshot:
|
|
155
|
+
# mask:
|
|
156
|
+
# - users.email
|
|
157
|
+
# - users.phone
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# ─── AGENT METADATA ────────────────────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
# An agent is an app with kind: agent (above) and an agent: block.
|
|
163
|
+
# agent:
|
|
164
|
+
# purpose: Sync customer data from external CRM every night
|
|
165
|
+
# schedule: "0 2 * * *"
|
|
166
|
+
# trigger: webhook
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# ─── PRIVATE RESOURCE AUTO-DEPENDENCIES ────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
# When true (default), private resources are auto-injected as depends_on.
|
|
172
|
+
# auto_depends_on_private_requires: true
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ─── SERVICES (REQUIRED) ───────────────────────────────────────────────────
|
|
176
|
+
#
|
|
177
|
+
# At least one service is required. Key = service name (slug rules).
|
|
178
|
+
# Types: node, nextjs, python, static, cron.
|
|
179
|
+
#
|
|
7
180
|
services:
|
|
8
181
|
web:
|
|
182
|
+
# type (REQUIRED): node | nextjs | python | static | cron
|
|
9
183
|
type: static
|
|
184
|
+
# HTTP route: '/' | '/api' | false (internal) | omitted (=false + warning).
|
|
185
|
+
# Only one service per entity can claim '/'.
|
|
10
186
|
path: /
|
|
187
|
+
# Container port (default 8080; read process.env.PORT). Not for cron.
|
|
188
|
+
# port: 3000
|
|
189
|
+
# nextjs only: base_image: distroless (default) | alpine
|
|
190
|
+
# base_image: distroless
|
|
191
|
+
# node only: lang: javascript (default) | typescript
|
|
192
|
+
# lang: typescript
|
|
193
|
+
# Custom source location (default services/<name>/). '.' = project root.
|
|
194
|
+
# source:
|
|
195
|
+
# path: src/worker
|
|
196
|
+
# Health probe: false/omitted (TCP) | true (/health) | "/path" | {path,expected}
|
|
197
|
+
# health:
|
|
198
|
+
# path: /api/health
|
|
199
|
+
# expected: "200"
|
|
200
|
+
# Static runtime env vars (strings). Reserved: PORT, APP_NAME, SERVICE_NAME,
|
|
201
|
+
# NODE_ENV, MONGODB_URL, REDIS_URL, AI_GATEWAY_URL, N8N_WEBHOOK_URL, CLOUDGRID_*.
|
|
202
|
+
# env:
|
|
203
|
+
# LOG_LEVEL: info
|
|
204
|
+
# Sibling services/private resources that must be Ready first (no cron, no cycles).
|
|
205
|
+
# depends_on:
|
|
206
|
+
# - worker
|
|
207
|
+
# Per-service needs override (merges with app-level needs).
|
|
208
|
+
# needs:
|
|
209
|
+
# queue: true
|
|
210
|
+
# Static-only build step:
|
|
211
|
+
# build:
|
|
212
|
+
# command: npm run build
|
|
213
|
+
# output: dist
|
|
214
|
+
# env:
|
|
215
|
+
# VITE_API_URL: https://api.example.com
|
|
216
|
+
# node_version: "22" # static build step: '18'|'20'|'22'|'24' (quoted)
|
|
217
|
+
# Cron-only: schedule (REQUIRED), timezone (UTC|EST|PST), run (job | https URL)
|
|
218
|
+
# schedule: "0 9 * * 1"
|
|
219
|
+
# timezone: UTC
|
|
220
|
+
# run: job
|
|
221
|
+
# Verbose per-service persistence (prefer needs.disk):
|
|
222
|
+
# persist:
|
|
223
|
+
# - name: scratch
|
|
224
|
+
# path: /tmp/scratch
|
|
225
|
+
# size: 500Mi
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# ============================================================================
|
|
229
|
+
# NOTES
|
|
230
|
+
# - NOT here: org:/entity_id: (→ .cloudgrid/link.json), secrets (→ grid secrets set),
|
|
231
|
+
# Dockerfile (platform generates from services.*.type).
|
|
232
|
+
# - Deploy: grid plug | Local with grid resources: grid dev
|
|
233
|
+
# - Full reference: docs/cloudgrid-yaml-reference.md | CLI: docs/cli-reference.md
|
|
234
|
+
# ============================================================================
|
|
@@ -17,11 +17,9 @@ The fillable HTML is the real template — fetch it with
|
|
|
17
17
|
## cloudgrid.yaml (reference only)
|
|
18
18
|
|
|
19
19
|
```yaml
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
# needs: {} # none — static, no infrastructure
|
|
20
|
+
# On disk this file is the full-annotated reference (templates/_cloudgrid.yaml.reference) with EVERY
|
|
21
|
+
# field present as a comment; only the fields below are uncommented, so it
|
|
22
|
+
# deploys to exactly these active fields.
|
|
25
23
|
name: landing-page
|
|
26
24
|
services:
|
|
27
25
|
web:
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# AGENTS.md — lms (blueprint)
|
|
2
|
+
|
|
3
|
+
This is a **blueprint**, not runnable app code. It is the structure guide an agent
|
|
4
|
+
follows to build a learning management system (LMS) on CloudGrid: a training
|
|
5
|
+
platform where instructors publish courses (organized into modules and lessons),
|
|
6
|
+
students enroll and work through them, and instructors grade submissions and track
|
|
7
|
+
progress. Role-based auth (instructor vs. student) is the spine of the whole app.
|
|
8
|
+
|
|
9
|
+
The `cloudgrid.yaml` in this directory is complete and correct — copy it as-is.
|
|
10
|
+
Everything below tells you WHAT to build under `services/web/` and HOW CloudGrid
|
|
11
|
+
wires it together. Build the app following this; do not expect the code to exist.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. File tree (build this under `services/web/`)
|
|
16
|
+
|
|
17
|
+
App code MUST live under `services/<service-name>/`. The service is named `web`,
|
|
18
|
+
so the CLI looks in `services/web/`. `path: /` in `cloudgrid.yaml` is the URL
|
|
19
|
+
mount, NOT the filesystem path. Files at the project root fail with
|
|
20
|
+
`Error: Service directory not found: …/services/web`.
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
cloudgrid.yaml # this dir — name + vault + services.web(nextjs) + needs:{database:true}
|
|
24
|
+
services/web/package.json # next, react, react-dom, mongodb, + auth SDK (e.g. @clerk/nextjs)
|
|
25
|
+
services/web/middleware.js # auth middleware — protects /dashboard, /learn/*, /teach/* ; publishes session
|
|
26
|
+
services/web/lib/db.js # LAZY Mongo client from DATABASE_MONGODB_URL (legacy MONGODB_URL fallback)
|
|
27
|
+
services/web/lib/auth.js # helpers: getUserId(), getRole() from the auth provider session; requireRole()
|
|
28
|
+
services/web/lib/enrollment.js # server guard: isEnrolled(userId, courseId); computeProgress(userId, courseId)
|
|
29
|
+
services/web/app/layout.js # root layout + auth provider wrapper + inline CSS
|
|
30
|
+
services/web/app/page.js # course catalog (server component: lists published courses from Mongo)
|
|
31
|
+
services/web/app/courses/[slug]/page.js # course detail + module/lesson outline; "Enroll" vs "Continue"
|
|
32
|
+
services/web/app/learn/[courseSlug]/[lessonId]/page.js # lesson player — GATED: redirect unless enrolled (student)
|
|
33
|
+
services/web/app/dashboard/page.js # student dashboard: enrolled courses + progress bars + grades
|
|
34
|
+
services/web/app/teach/page.js # instructor dashboard — GATED to role=instructor: courses + submissions to grade
|
|
35
|
+
services/web/app/api/courses/route.js # GET list (public: published) / POST create (instructor only)
|
|
36
|
+
services/web/app/api/modules/route.js # GET modules+lessons for a course / POST add (instructor only)
|
|
37
|
+
services/web/app/api/enrollments/route.js # GET my enrollments / POST enroll student in a course
|
|
38
|
+
services/web/app/api/progress/route.js # POST mark-lesson-complete (upsert) ; GET course progress %
|
|
39
|
+
services/web/app/api/submissions/route.js # POST student submits assignment/quiz ; GET a student's submissions
|
|
40
|
+
services/web/app/api/grades/route.js # POST instructor grades a submission (score + feedback) ; GET a student's grades
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Keep it a real Next.js App Router app (`next@^15`, `react@^19`). Only add
|
|
44
|
+
dependencies you use: `mongodb` and one auth SDK (add `stripe` only if you sell
|
|
45
|
+
paid courses — see §4).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Mongo collections + fields
|
|
50
|
+
|
|
51
|
+
The grid provisions a shared MongoDB (`needs: { database: true }`). Suggested
|
|
52
|
+
collections (adapt names/fields freely):
|
|
53
|
+
|
|
54
|
+
- **`users`** — `{ _id, authId, name, email, role: "instructor" | "student",
|
|
55
|
+
createdAt }`. Mirrors the auth-provider user; `role` drives every gate. Upsert
|
|
56
|
+
on first login keyed by `authId`.
|
|
57
|
+
- **`courses`** — `{ _id, slug, title, description, instructorId, published: bool,
|
|
58
|
+
createdAt }`. One document per course. `instructorId` = the owning instructor.
|
|
59
|
+
- **`modules`** — `{ _id, courseId, title, order }`. A course is organized into
|
|
60
|
+
ordered modules (chapters/units).
|
|
61
|
+
- **`lessons`** — `{ _id, moduleId, courseId, title, order, content, videoUrl,
|
|
62
|
+
isFreePreview: bool }`. Ordered lessons inside a module.
|
|
63
|
+
- **`assignments`** — `{ _id, courseId, lessonId, title, prompt, maxScore }`.
|
|
64
|
+
A gradable task attached to a lesson (assignment or quiz).
|
|
65
|
+
- **`enrollments`** — `{ _id, userId, courseId, enrolledAt }`. The access grant —
|
|
66
|
+
the lesson player and submission APIs check for it.
|
|
67
|
+
- **`progress`** — `{ _id, userId, courseId, lessonId, completedAt }`. One doc per
|
|
68
|
+
student per completed lesson. Course progress % = `completed lessons / total lessons`.
|
|
69
|
+
- **`submissions`** — `{ _id, userId, assignmentId, courseId, answer, submittedAt }`.
|
|
70
|
+
A student's work turned in for an assignment.
|
|
71
|
+
- **`grades`** — `{ _id, submissionId, userId, assignmentId, courseId, score,
|
|
72
|
+
feedback, gradedBy, gradedAt }`. The instructor's grade for a submission.
|
|
73
|
+
|
|
74
|
+
Add indexes: `users.authId` (unique), `courses.slug` (unique),
|
|
75
|
+
`modules.courseId+order`, `lessons.moduleId+order`,
|
|
76
|
+
`enrollments.userId+courseId` (unique), `progress.userId+lessonId` (unique),
|
|
77
|
+
`submissions.userId+assignmentId` (unique).
|
|
78
|
+
|
|
79
|
+
Two access rules the whole platform hinges on — **enforce both on the server**
|
|
80
|
+
(in the page + API route), never only in the UI:
|
|
81
|
+
- **A lesson is viewable if** `isFreePreview` OR an `enrollments` doc exists for
|
|
82
|
+
`(userId, courseId)`.
|
|
83
|
+
- **Only `role: instructor`** may create courses/modules/lessons/assignments and
|
|
84
|
+
post grades. A student may only submit work and read their own grades/progress.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 3. How CloudGrid injects everything
|
|
89
|
+
|
|
90
|
+
You never provision infra or set connection strings by hand. Declared needs and
|
|
91
|
+
vault items are injected as environment variables at `grid dev` (local) and at
|
|
92
|
+
runtime (after `grid plug`).
|
|
93
|
+
|
|
94
|
+
- **Mongo** — `needs: { database: true }` → the grid injects
|
|
95
|
+
**`DATABASE_MONGODB_URL`** (plus the legacy **`MONGODB_URL`** alias). Read
|
|
96
|
+
`process.env.DATABASE_MONGODB_URL || process.env.MONGODB_URL` **lazily inside a
|
|
97
|
+
getter** in `lib/db.js`. A top-level read (`const uri = process.env…; if (!uri)
|
|
98
|
+
throw`) breaks `next build`, which imports the module for route analysis before
|
|
99
|
+
the grid injects the var. Never hardcode a URI; never commit a secret.
|
|
100
|
+
- **Secrets via the `vault:` block** — the block maps org vault items to env vars:
|
|
101
|
+
`AUTH_PROVIDER_KEY` ← `auth-provider-key` (the server-side auth secret that lets
|
|
102
|
+
you verify sessions and roles). Set each vault item ONCE with
|
|
103
|
+
`grid secrets set <item>` (e.g. `grid secrets set auth-provider-key`); the
|
|
104
|
+
platform injects it as the named env var. Read it lazily too (inside the auth
|
|
105
|
+
client getter in `lib/auth.js`), not at module top level. If you add paid
|
|
106
|
+
courses, map `STRIPE_KEY`/`STRIPE_WEBHOOK_SECRET` the same way.
|
|
107
|
+
- **AI (optional — auto-grading / quiz generation / a study tutor)** — add
|
|
108
|
+
`needs: { ai: true }` → the grid injects **`AI_GATEWAY_URL`**; call it via
|
|
109
|
+
`@cloudgrid-io/ai`. Not enabled in this blueprint; add the need if you want it.
|
|
110
|
+
|
|
111
|
+
Reserved env var names you must NOT set yourself: `PORT`, `NODE_ENV`,
|
|
112
|
+
`DATABASE_MONGODB_URL`/`MONGODB_URL`, `AI_GATEWAY_URL`, `CLOUDGRID_*`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 4. Wiring auth (roles) + optional payments
|
|
117
|
+
|
|
118
|
+
### Auth + roles (provider SDK) — the core of the LMS
|
|
119
|
+
Use a hosted auth provider SDK (e.g. Clerk or Auth0) rather than rolling your own.
|
|
120
|
+
Role-based access (instructor vs. student) is what separates an LMS from a plain
|
|
121
|
+
content site, so wire it first.
|
|
122
|
+
|
|
123
|
+
1. Add the SDK to `package.json` (e.g. `@clerk/nextjs`).
|
|
124
|
+
2. Wrap `app/layout.js` in the provider; add `middleware.js` to protect
|
|
125
|
+
`/dashboard`, `/learn/*` (any signed-in user) and `/teach/*` (instructors only).
|
|
126
|
+
3. The **publishable** key is a non-secret client env var → set it with
|
|
127
|
+
`grid env` (e.g. `grid env NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=…`). The **secret**
|
|
128
|
+
server key comes from the vault → `AUTH_PROVIDER_KEY` (mapped in `cloudgrid.yaml`),
|
|
129
|
+
read lazily in `lib/auth.js`.
|
|
130
|
+
4. `lib/auth.js` exposes `getUserId()` and `getRole()` reading the provider's
|
|
131
|
+
server session, plus `requireRole("instructor")` that throws/redirects for
|
|
132
|
+
students. Every instructor-only API route (`/api/courses` POST,
|
|
133
|
+
`/api/modules` POST, `/api/grades` POST) calls `requireRole("instructor")`
|
|
134
|
+
server-side. Store the role on the `users` doc and/or in the provider's
|
|
135
|
+
user metadata; upsert the `users` doc on first login keyed by `authId`.
|
|
136
|
+
|
|
137
|
+
### Grading flow (the LMS-specific loop)
|
|
138
|
+
1. A student POSTs to `/api/submissions` (guarded by `isEnrolled`) to turn in an
|
|
139
|
+
assignment answer → one `submissions` doc per `(userId, assignmentId)`.
|
|
140
|
+
2. The instructor sees ungraded submissions on `/teach`, and POSTs to
|
|
141
|
+
`/api/grades` (guarded by `requireRole("instructor")`) with `score` + `feedback`
|
|
142
|
+
→ a `grades` doc referencing the `submissionId`. Never let a client set its own
|
|
143
|
+
score; derive `gradedBy` from the server session.
|
|
144
|
+
3. The student reads their grades on `/dashboard` via `/api/grades` GET, scoped to
|
|
145
|
+
`getUserId()` so students only ever see their own grades.
|
|
146
|
+
|
|
147
|
+
### Payments (Stripe) — OPTIONAL, only for paid courses
|
|
148
|
+
If courses are sold rather than freely enrollable, add `stripe` to `package.json`
|
|
149
|
+
and a `vault:` mapping for `STRIPE_KEY` + `STRIPE_WEBHOOK_SECRET`:
|
|
150
|
+
1. `lib/stripe.js` builds the Stripe client lazily from `process.env.STRIPE_KEY`.
|
|
151
|
+
2. **Checkout route** `app/api/checkout/route.js`: POST with a `courseId`, read the
|
|
152
|
+
course price server-side, create a Stripe Checkout Session (`payment` mode) with
|
|
153
|
+
`client_reference_id = userId` and `metadata.courseId`, return `session.url`.
|
|
154
|
+
Never trust a price sent from the client.
|
|
155
|
+
3. **Webhook route** `app/api/webhooks/stripe/route.js`: verify the signature with
|
|
156
|
+
`STRIPE_WEBHOOK_SECRET` (`stripe.webhooks.constructEvent(rawBody, sig, secret)`
|
|
157
|
+
— read the RAW body, do not JSON-parse first). On `checkout.session.completed`,
|
|
158
|
+
upsert an `enrollments` doc. This webhook — not the checkout redirect — grants
|
|
159
|
+
access. Register the webhook URL (`https://<live-url>/api/webhooks/stripe`) in
|
|
160
|
+
the Stripe dashboard after the first deploy, then set `stripe-webhook-secret`.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 5. Deploy steps
|
|
165
|
+
|
|
166
|
+
A runtime deploy is **asynchronous** and requires the **local edition** (§6).
|
|
167
|
+
|
|
168
|
+
1. **`grid init`** an app named `lms`. `init` creates the entity +
|
|
169
|
+
`.cloudgrid/link.json` and writes a `cloudgrid.yaml` with an empty
|
|
170
|
+
`services: {}`. Run it FIRST — `plug` needs a linked directory.
|
|
171
|
+
2. **Fill** — replace the generated `cloudgrid.yaml` with the one in this template
|
|
172
|
+
(name + vault + `services.web` nextjs + `needs: { database: true }`), and write
|
|
173
|
+
the app under `services/web/` per the tree above.
|
|
174
|
+
3. **Set secrets** — `grid secrets set auth-provider-key` (and, if selling courses,
|
|
175
|
+
`grid secrets set stripe-live-key` + `grid secrets set stripe-webhook-secret`).
|
|
176
|
+
Set non-secret client config with `grid env` (e.g. the auth publishable key).
|
|
177
|
+
Do NOT set the DB vars — the grid injects them.
|
|
178
|
+
4. **`grid plug`** — builds + deploys `services/web/`. The first response is
|
|
179
|
+
`status: building`, NOT a live URL. Poll `grid status` (or the returned
|
|
180
|
+
poll_url) until it is live; surface a liveness signal while it builds, never a
|
|
181
|
+
bare silent wait. Only then return the live app URL.
|
|
182
|
+
5. **Iterate** — re-plug the SAME entity so it updates the same URL. (If you added
|
|
183
|
+
Stripe, wire the webhook to the live URL first — §4.)
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 6. Edition note
|
|
188
|
+
|
|
189
|
+
An LMS is a built + deployed **runtime** container. It requires the **local
|
|
190
|
+
edition** (Claude Desktop / Claude Code) or the CLI. On the **hosted** edition
|
|
191
|
+
(Claude Web / hosted MCP) you cannot build a runtime app — hosted is inline-only
|
|
192
|
+
and can only publish static pages. If you are on hosted, say so plainly and stop
|
|
193
|
+
the runtime path (a static course *landing* page is the only thing hosted can ship).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# lms template — blueprint (structure + cloudgrid.yaml)
|
|
2
|
+
|
|
3
|
+
A learning management system / training platform: instructors publish courses
|
|
4
|
+
organized into modules and lessons, students enroll and progress through them,
|
|
5
|
+
and instructors grade submissions and track each student's progress — a
|
|
6
|
+
persistent Next.js + Mongo app with role-based (instructor/student) auth. This is
|
|
7
|
+
a **blueprint**: it ships the correct `cloudgrid.yaml` and an `AGENTS.md`
|
|
8
|
+
structure guide (file tree, Mongo collections, CloudGrid env/vault wiring, the
|
|
9
|
+
auth-role + grading flow, deploy steps), not runnable app code. Adapt the
|
|
10
|
+
structure and build the app under `services/web/`.
|
|
11
|
+
|
|
12
|
+
## What's here
|
|
13
|
+
|
|
14
|
+
- **`cloudgrid.yaml`** — full-annotated reference with only the active fields
|
|
15
|
+
uncommented: `name`, a `vault:` block (`AUTH_PROVIDER_KEY`), `services.web`
|
|
16
|
+
(type: nextjs, path: /), and `needs: { database: true }`. Copy it as-is.
|
|
17
|
+
- **`AGENTS.md`** — the structure guide. Read it before building: it is the
|
|
18
|
+
CloudGrid-specific spec for the file tree, collections, secret injection, the
|
|
19
|
+
instructor/student role gates + grading loop, and the async runtime deploy.
|
|
20
|
+
|
|
21
|
+
## Blueprint: structure + cloudgrid.yaml, adapt and build
|
|
22
|
+
|
|
23
|
+
Read `AGENTS.md`, then build the app following it — put the code under
|
|
24
|
+
`services/web/`, read `DATABASE_MONGODB_URL` (legacy `MONGODB_URL` fallback) and
|
|
25
|
+
the vault-injected `AUTH_PROVIDER_KEY` lazily inside getters, enforce the
|
|
26
|
+
instructor/student role gates on the server, declare `needs: { database: true }`,
|
|
27
|
+
and deploy with `grid plug` (async — poll to a live URL; local edition only).
|