The workspace surface is organised into 20 modules (the count registered in
lib/workspace-nav.ts, excluding the Overview dashboard). Each module is a top-level route under
apps/workspace/app/(workspace)/, with its own page, components, and (usually) a small set of
API routes that back its CRUD operations.
All modules share the same shape:
apps/workspace/app/(workspace)/<module>/
├── page.tsx — entry point, redirect to first view or dashboard
├── client-page.tsx — main client component (where applicable)
├── components/ — module-specific UI
├── hooks/ — module-specific hooks (data fetching, mutations)
├── types.ts — TypeScript types
├── constants.ts — module-specific constants
└── <sub-route>/page.tsx — additional pages
Backing API routes live at apps/workspace/app/api/workspace/<module>/ (or one of the
dedicated app/api/{admin,settings,user,whitepapers/admin,careers/settings} trees for legacy
naming reasons).
Categories, Master Downloader, Site Banner, Snippet Generator, Downloads
Backed by
WordPress REST API, MongoDB
Notable
The snippet generator builds reusable WordPress block snippets; Testimonial blocks hydrate from a shared registry consumed by both the public site and the studio preview.
Public surface is /videos (single gallery with deep-link modal). Falls back to static lib/data/product-videos.ts registry if the CPT is empty or unreachable.
All Webinars, Registrations, Speakers, Topics & Tags, Partners, Event Logs
Backed by
MongoDB webinars, webinar_registrations, webinar_event_log, webinar_standalone_subscribers; AWS SES for invites; Salesforce Web-to-Lead for CRM sync
Notable
Bulk-invite is rate-limited at 3/hour/user (up to 500 emails/call). Salesforce sync is rate-limited at 5/hour/user (up to 1000 leads/call). Event logs require org:webinars:manage (was previously unprotected — closed in commit 3dd76d5).
Add an entry to lib/workspace-nav.ts so the sidebar picks it up.
Add corresponding API routes under apps/workspace/app/api/workspace/<module>/.
Define a new permission string in lib/auth/rbac-shared.ts (Permission type) and add it
to ROLE_PERMISSIONS for the roles that should have it.
Gate every API handler with checkRole(...). Wrap mutations with enforceRateLimit +
auditMutation from @/lib/security/api-guards.
Document the module here.
If the module is content-editorial and backed by WordPress (like industries, use cases,
videos), follow the CPT-backed module pattern instead —
it's the shared blueprint with file-by-file instructions and copy-pasteable references.