Plugin Manager
Extend the platform with plugins (Slack, Discord, email, and more).

By the end of this guide, you'll understand how to extend your SaaS platform with third-party integrations using the Plugin Manager. You'll learn to create plugins, register them, and trigger their actions from your application events, enabling seamless connections to services like Slack, Discord, and email providers.
Overview
The Plugin Manager is a powerful system that simplifies delivering integrations to your users. By defining plugins with standardized schemas, you automatically get:
- Auto-generated UI: Integration forms appear instantly in your dashboard without additional frontend work
- Type-safe Configuration: Zod schemas ensure valid inputs and provide TypeScript support
- Organization Scoping: Each organization configures integrations independently
- Event-driven Automation: Trigger actions from domain events like lead creation or form submissions
When you add a plugin, it immediately becomes available in the integrations dashboard at /app/integrations, where users can install, configure, and manage their third-party connections. This creates a seamless experience where new integrations enhance your platform's capabilities without requiring UI development.
Core Concepts
Plugins
Self-contained modules that define integration logic with external services. Each plugin includes:
- Configuration schema (Zod)
- Metadata for UI display
- Actions that can be triggered
Actions
Functions a plugin can perform, like sending notifications or syncing data. Each action has:
- Input schema for validation
- Handler function with business logic
Integrations
Organization-specific instances of plugins with stored configuration and enabled/disabled state.
Creating a Plugin
Create Plugin Instance
Define your plugin with schema, metadata, and actions.
// src/plugins/my-service.plugin.ts
import { PluginManager } from '@/@saas-boilerplate/providers/plugin-manager/provider'
import { z } from 'zod'
export const myService = PluginManager.plugin({
slug: 'my-service',
name: 'My Service',
schema: z.object({
apiKey: z.string().describe('API Key for My Service'),
apiSecret: z.string().describe('API Secret for My Service'),
webhookUrl: z.string().url().optional().describe('Optional webhook URL'),
}),
metadata: {
verified: false,
published: true,
description: 'Integrate with My Service for notifications and automation.',
category: 'notifications',
developer: 'Your Company',
website: 'https://my-service.com',
logo: 'https://my-service.com/logo.png',
links: {
docs: 'https://docs.my-service.com',
support: 'https://support.my-service.com',
},
},
actions: {
sendEvent: {
name: 'Send Event',
schema: z.object({
event: z.string(),
data: z.record(z.any()),
}),
handler: async ({ config, input }) => {
const response = await fetch('https://api.my-service.com/notify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${config.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: `${input.event}: ${JSON.stringify(input.data)}`,
}),
})
if (!response.ok) {
throw new Error('Failed to send notification')
}
return { success: true }
},
},
},
})Prop
Type
Register Plugin Instance
Add the plugin to the PluginManager initialization.
// src/services/plugin-manager.ts
import { myService } from '../plugins/my-service.plugin'
// ... other imports
export const plugins = PluginManager.initialize({
plugins: {
slack,
discord,
telegram,
myService, // Add your new plugin here
// ... other plugins
},
})Trigger Plugin Actions
Create a complete controller that triggers your custom plugin action. Here's an example notification controller:
// src/features/notification/controllers/notification.controller.ts
import { igniter } from '@/igniter'
import { AuthFeatureProcedure } from '@/@saas-boilerplate/features/auth/procedures/auth.procedure'
import { IntegrationFeatureProcedure } from '@/@saas-boilerplate/features/integration/procedures/integration.procedure'
import { z } from 'zod'
export const NotificationController = igniter.controller({
name: 'Notification',
path: '/notifications',
actions: {
sendTest: igniter.mutation({
name: 'Send Test Notification',
description: 'Send a test notification using configured integrations.',
path: '/test',
method: 'POST',
use: [AuthFeatureProcedure(), IntegrationFeatureProcedure()],
body: z.object({
message: z.string(),
}),
handler: async ({ context, request, response }) => {
// Authentication: Get user session and organization
const session = await context.auth.getSession({
requirements: 'authenticated',
roles: ['admin', 'owner'],
})
if (!session?.organization) {
return response.unauthorized('Organization access required')
}
const organizationId = session.organization.id
// Business Logic: Setup plugins for the organization
const plugins = await context.integration.setupPluginsForOrganization(organizationId)
// Trigger the custom 'my-service' plugin action
const myServicePlugin = plugins['my-service']
if (myServicePlugin && 'sendEvent' in myServicePlugin) {
await myServicePlugin.sendEvent({
event: 'test.notification',
data: {
message: request.body.message,
organizationId,
timestamp: new Date().toISOString(),
},
})
}
// Response: Confirm notification sent
return response.success({ sent: true })
},
}),
},
})Managing Integrations
The default SaaS Boilerplate provides a complete integrations dashboard at /app/integrations where users can install, configure, and manage plugins through a user-friendly interface. You typically won't need to manually call these endpoints unless you're building custom integration management features elsewhere in your application.