Connect your Slack workspace to receive real-time notifications about project activities, team updates, and important milestones directly in your team channels.
The Slack integration provides:
Before setting up the Slack integration, ensure you have:
Add our app to your Slack workspace:
Link your Slack workspace with your platform team:
Set up which platform activities notify which Slack channels:
{
"channel_mappings": [
{
"slack_channel": "#general",
"notifications": [
"team.member.added",
"project.created",
"milestone.completed"
]
},
{
"slack_channel": "#dev-team",
"notifications": [
"task.created",
"task.assigned",
"task.completed",
"github.pull_request"
]
},
{
"slack_channel": "#design",
"notifications": [
"brief.updated",
"file.uploaded",
"comment.added"
]
}
]
}
Configure individual notification preferences:
Slack notifications use rich formatting for better readability:
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "šÆ Task Completed"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Task:* Implement user authentication API\n*Project:* Mobile App Redesign\n*Completed by:* <@U123456789>\n*Duration:* 2 days"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "View Task"
},
"url": "https://platform.com/tasks/task_123"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "š
Completed on time ⢠š <https://platform.com/projects/proj_456|Mobile App Redesign>"
}
]
}
]
}
Create custom message templates for different notification types:
const messageTemplates = {
task_completed: {
header: "šÆ Task Completed",
body: "*{task.title}* has been completed by *{task.assignee}*",
footer: "Project: {project.name} ⢠Duration: {task.duration}",
actions: [
{ text: "View Task", url: "{task.url}" },
{ text: "View Project", url: "{project.url}" }
]
},
project_milestone: {
header: "š Milestone Reached",
body: "*{project.name}* has reached milestone: *{milestone.name}*",
footer: "Progress: {project.progress}% ⢠Next: {milestone.next}",
mentions: "{project.owner} {project.stakeholders}"
},
deadline_reminder: {
header: "ā° Deadline Reminder",
body: "*{task.title}* is due {task.due_date}",
footer: "Assigned to: {task.assignee} ⢠Priority: {task.priority}",
urgency: "high"
}
};
Use slash commands for quick platform actions:
# View your tasks
/platform tasks
# Create a new task
/platform create task "Implement search feature" --project mobile-app
# Check project status
/platform status mobile-app
# Get team overview
/platform team summary
# Search platform content
/platform search "user authentication"
Interact with notifications using buttons:
Set up automated workflows triggered by Slack actions:
# Slack workflow automation
workflows:
- name: "Task approval workflow"
trigger:
platform: "slack"
action: "button_click"
button_id: "approve_task"
steps:
- update_task_status:
status: "approved"
approver: "{{ slack.user.email }}"
- notify_assignee:
message: "Your task has been approved and is ready to start"
- create_calendar_event:
title: "{{ task.title }}"
start_date: "{{ task.planned_start }}"
- name: "Daily standup reminder"
trigger:
schedule: "0 9 * * 1-5" # 9 AM weekdays
steps:
- post_to_slack:
channel: "#dev-team"
message: "Good morning team! Time for standup š
"
include_task_summary: true
mention_team_members: true
Create custom bot commands for advanced platform interactions:
// Slack bot command handler
app.event('app_mention', async ({ event, client, context }) => {
const message = event.text.toLowerCase();
if (message.includes('status report')) {
const report = await generateStatusReport(event.channel);
await client.chat.postMessage({
channel: event.channel,
text: formatStatusReport(report),
thread_ts: event.ts
});
}
if (message.includes('create sprint')) {
const sprintData = parseSprintRequest(event.text);
const sprint = await createSprintFromSlack(sprintData);
await client.chat.postMessage({
channel: event.channel,
text: `ā
Sprint "${sprint.name}" created successfully!`,
blocks: formatSprintSummary(sprint)
});
}
});
Implement conversational workflows for complex tasks:
// Multi-step task creation workflow
const taskCreationFlow = {
async start(channel, user) {
await postMessage(channel, {
text: "Let's create a new task! What's the task title?",
metadata: { flow: 'task_creation', step: 'title', user }
});
},
async handleTitle(channel, user, title) {
await postMessage(channel, {
text: `Great! "${title}" - Which project should this belong to?`,
blocks: generateProjectSelector(),
metadata: { flow: 'task_creation', step: 'project', title, user }
});
},
async handleProject(channel, user, title, project) {
const task = await createTask({ title, project, creator: user });
await postMessage(channel, {
text: `ā
Task created successfully!`,
blocks: formatTaskCard(task)
});
}
};
Create automated workflows using Slack's native Workflow Builder:
Project Kickoff Workflow:
Task Assignment Workflow:
Sprint Planning Workflow:
Build dedicated Slack apps for your team's specific needs:
// Custom Slack app configuration
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
endpoints: {
events: '/slack/events',
commands: '/slack/commands',
actions: '/slack/actions'
}
});
// Platform-specific shortcuts
app.shortcut('create_platform_task', async ({ shortcut, ack, client }) => {
await ack();
await client.views.open({
trigger_id: shortcut.trigger_id,
view: {
type: 'modal',
callback_id: 'task_creation_modal',
title: { type: 'plain_text', text: 'Create Task' },
blocks: generateTaskCreationForm()
}
});
});
#general - Team announcements, milestone updates
#project-updates - All project-related notifications
#dev-notifications - Development team specific updates
#design-updates - Design team notifications
#client-updates - Client-facing project updates (if applicable)
#platform-alerts - System notifications and maintenance
{
"channel_configs": {
"#general": {
"notification_types": ["high_priority", "milestones", "team_changes"],
"frequency": "immediate",
"format": "summary",
"mentions": "stakeholders_only"
},
"#dev-notifications": {
"notification_types": ["task_assignments", "code_reviews", "deployments"],
"frequency": "immediate",
"format": "detailed",
"mentions": "assignees",
"thread_replies": true
},
"#project-updates": {
"notification_types": ["all_project_activities"],
"frequency": "batched_hourly",
"format": "digest",
"mentions": "none"
}
}
}
Configure individual team member preferences:
const personalSettings = {
direct_messages: {
task_assigned: true,
task_due_soon: true,
mentioned_in_comment: true,
project_milestone: false,
team_updates: false
},
mention_preferences: {
high_priority_tasks: true,
project_deadlines: true,
approval_requests: true,
status_updates: false
},
digest_settings: {
daily_summary: {
enabled: true,
time: "09:00",
timezone: "America/New_York"
},
weekly_report: {
enabled: true,
day: "monday",
time: "08:00"
}
},
quiet_hours: {
enabled: true,
start: "18:00",
end: "09:00",
weekends: true
}
};
Implement intelligent notification filtering:
// Smart notification filtering logic
function shouldSendNotification(notification, userPreferences, context) {
// Check quiet hours
if (isQuietHours(userPreferences.quiet_hours)) {
return false;
}
// Priority-based filtering
if (notification.priority === 'low' && !userPreferences.include_low_priority) {
return false;
}
// Context-aware filtering
if (notification.type === 'task_created' && !isUserProjectMember(context.user, notification.project)) {
return false;
}
// Frequency limits
if (exceedsFrequencyLimit(notification, userPreferences.frequency_limits)) {
return { action: 'batch_for_later' };
}
return true;
}
Track how your team engages with platform notifications in Slack:
const slackAnalytics = {
notification_metrics: {
messages_sent: 1250,
message_clicks: 890,
button_interactions: 340,
slash_command_usage: 125
},
engagement_rates: {
overall_click_rate: 0.71,
task_completion_rate: 0.85,
response_time_avg: "2.3 hours"
},
popular_features: [
{ feature: "task_status_updates", usage: 450 },
{ feature: "project_summaries", usage: 320 },
{ feature: "deadline_reminders", usage: 280 },
{ feature: "team_mentions", usage: 200 }
]
};
Analyze how Slack integration affects team communication:
Symptoms:
Diagnostic Steps:
// Check notification delivery status
async function diagnoseLackNotifications(teamId, channelId) {
const diagnostics = {
slack_connection: await testSlackConnection(),
webhook_status: await checkWebhookStatus(teamId),
channel_permissions: await checkChannelPermissions(channelId),
notification_rules: await getNotificationRules(teamId, channelId),
recent_errors: await getRecentSlackErrors(teamId)
};
return diagnostics;
}
Common Solutions:
Symptoms:
Solutions:
// Validate Slack message format
function validateSlackMessage(message) {
const issues = [];
if (message.blocks) {
// Check block structure
message.blocks.forEach((block, index) => {
if (!block.type) {
issues.push(`Block ${index} missing type`);
}
if (block.type === 'section' && !block.text) {
issues.push(`Section block ${index} missing text`);
}
});
}
// Validate user mentions
const mentions = message.text?.match(/<@U[A-Z0-9]+>/g) || [];
mentions.forEach(mention => {
if (!isValidSlackUserId(mention)) {
issues.push(`Invalid user mention: ${mention}`);
}
});
return issues;
}
Handle Slack API rate limits effectively:
const slackRateLimiter = {
limits: {
messages: { rate: 1, period: 1000 }, // 1 message per second
webhook: { rate: 1, period: 1000 }, // 1 webhook per second
api_calls: { rate: 50, period: 60000 } // 50 API calls per minute
},
async sendMessage(channel, message) {
await this.waitForRateLimit('messages');
return await slackClient.chat.postMessage({
channel,
...message
});
},
async waitForRateLimit(type) {
const limit = this.limits[type];
const now = Date.now();
const lastCall = this.lastCalls[type] || 0;
const timeSinceLastCall = now - lastCall;
if (timeSinceLastCall < limit.period) {
const waitTime = limit.period - timeSinceLastCall;
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.lastCalls[type] = Date.now();
}
Optimize notification delivery through batching:
// Batch multiple notifications into digest messages
class NotificationBatcher {
constructor() {
this.batches = new Map();
this.flushInterval = 5 * 60 * 1000; // 5 minutes
}
addNotification(channelId, notification) {
if (!this.batches.has(channelId)) {
this.batches.set(channelId, []);
setTimeout(() => this.flushBatch(channelId), this.flushInterval);
}
this.batches.get(channelId).push(notification);
// Immediate flush for high priority
if (notification.priority === 'critical') {
this.flushBatch(channelId);
}
}
async flushBatch(channelId) {
const notifications = this.batches.get(channelId) || [];
this.batches.delete(channelId);
if (notifications.length === 0) return;
if (notifications.length === 1) {
await sendSingleNotification(channelId, notifications[0]);
} else {
await sendDigestMessage(channelId, notifications);
}
}
}
#platform-[team] - Team-specific platform notifications
#project-[name] - Project-specific updates
#alerts-platform - System alerts and maintenance
#digest-daily - Daily summary digests
#approvals-[type] - Approval workflows
// Good: Clear, actionable message
const goodMessage = {
text: "šÆ Task assigned to you",
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: "*Implement user search feature* has been assigned to you\nš
Due: Tomorrow at 5 PM\nš <https://platform.com/tasks/123|View Task>"
}
},
{
type: "actions",
elements: [
{ type: "button", text: "Accept", action_id: "accept_task" },
{ type: "button", text: "Discuss", action_id: "discuss_task" }
]
}
]
};
// Avoid: Vague, non-actionable message
const poorMessage = {
text: "Task update",
blocks: [
{
type: "section",
text: { type: "plain_text", text: "Something happened with a task" }
}
]
};
// Secure Slack token handling
const slackTokenManager = {
async getToken(teamId) {
const encryptedToken = await db.getEncryptedSlackToken(teamId);
return decrypt(encryptedToken, process.env.ENCRYPTION_KEY);
},
async rotateToken(teamId, newToken) {
const encryptedToken = encrypt(newToken, process.env.ENCRYPTION_KEY);
await db.updateSlackToken(teamId, encryptedToken, new Date());
// Test new token
const isValid = await testSlackToken(newToken);
if (!isValid) {
throw new Error('New token validation failed');
}
}
};
Your Slack integration is now set up! Here are the recommended next steps:
For additional customization and advanced workflows, explore:
Need help? Join our Slack community.