Auto‑Post Your Slack Prompt to LinkedIn in 5 Minutes 🚀
Ever typed a brilliant idea in Slack, wished you could share it on LinkedIn without copy‑pasting, and thought “there’s got to be a better way”? 🙋♀️ You’re not alone. In this post I’ll walk you through building a tiny Node.js service that listens to a Slack command, formats the message, and publishes it to your LinkedIn feed—all automatically.
Grab a coffee, open your favorite editor, and let’s turn that Slack‑to‑LinkedIn dream into reality. ☕️💻
Why Automate This?
- Stay in the flow – No context‑switching between apps.
- Consistent branding – Use a template so every post looks polished.
- Showcase expertise – Your network sees your latest insights instantly.
If you’ve ever felt the “I should post this on LinkedIn” brain‑tick, this guide is for you.
The Blueprint: From Slack Slash Command to LinkedIn Post
Below is the high‑level flow we’ll implement:
Slack slash command (/postln) → Your server (Node.js) → LinkedIn API → Your LinkedIn feed
1️⃣ Set Up a Slack App & Slash Command
- Go to api.slack.com/apps → Create New App.
- Choose From scratch, give it a name (e.g.,
Slack2LinkedIn
) and a workspace. - Under Features → Slash Commands, click Create New Command:
Field | Value |
---|---|
Command | /postln |
Request URL | https://your‑domain.com/slack/events |
Short description | “Post to LinkedIn in one go” |
Usage hint | [your message] |
- Enable Interactivity & Shortcuts (just to keep the UI happy).
- Install the app to your workspace – you’ll get a Bot User OAuth Token (
xoxb-…
).
Tip: Keep the token in a
.env
file, never commit it!
2️⃣ Spin Up a Tiny Express Server
We’ll use Bolt for JavaScript, Slack’s official framework.
npm init -y
npm install @slack/bolt dotenv node-fetch
Create index.js
:
// index.js
require('dotenv').config();
const { App } = require('@slack/bolt');
const fetch = require('node-fetch');
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
socketMode: false, // we’ll use HTTP endpoint
port: process.env.PORT || 3000,
});
/**
* Helper: Post a text update to LinkedIn
*/
async function postToLinkedIn(text) {
const accessToken = process.env.LINKEDIN_ACCESS_TOKEN; // see step 4
const payload = {
author: `urn:li:person:${process.env.LINKEDIN_PERSON_URN}`,
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: { text },
shareMediaCategory: 'NONE',
},
},
visibility: { 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' },
};
const res = await fetch('https://api.linkedin.com/v2/ugcPosts', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'X-Restli-Protocol-Version': '2.0.0',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!res.ok) {
const err = await res.text();
throw new Error(`LinkedIn error: ${res.status} – ${err}`);
}
return res.json();
}
/**
* Slash command handler
*/
app.command('/postln', async ({ command, ack, respond }) => {
await ack(); // tell Slack we received it
const message = command.text.trim();
if (!message) {
await respond('⚠️ Please provide a message after the command.');
return;
}
try {
const result = await postToLinkedIn(message);
await respond(`✅ Your post is live! LinkedIn ID: ${result.id}`);
} catch (e) {
console.error(e);
await respond('❌ Oops! Something went wrong posting to LinkedIn.');
}
});
(async () => {
await app.start();
console.log('⚡️ Slack app is running!');
})();
3️⃣ Get LinkedIn API Credentials
- Head to the LinkedIn Developer Portal → Create App.
- Fill in the basics, then under Products enable Sign In with LinkedIn and Share on LinkedIn.
- Add a Redirect URL (e.g.,
https://your-domain.com/auth/linkedin/callback
). - Grab the Client ID and Client Secret – store them in
.env
.
4️⃣ OAuth 2.0 Flow to Obtain an Access Token
LinkedIn’s share endpoint requires a User Access Token with the w_member_social
scope.
// auth.js (simplified)
require('dotenv').config();
const fetch = require('node-fetch');
const querystring = require('querystring');
const CLIENT_ID = process.env.LINKEDIN_CLIENT_ID;
const CLIENT_SECRET = process.env.LINKEDIN_CLIENT_SECRET;
const REDIRECT_URI = process.env.LINKEDIN_REDIRECT_URI;
// Step 1: Direct user to this URL (run once)
function getAuthUrl() {
const params = querystring.stringify({
response_type: 'code',
client_id: CLIENT_ID,
redirect_uri: REDIRECT_URI,
scope: 'w_member_social',
state: 'random_state_string', // protect against CSRF
});
return `https://www.linkedin.com/oauth/v2/authorization?${params}`;
}
// Step 2: Exchange code for token (your callback endpoint)
async function exchangeCodeForToken(code) {
const params = querystring.stringify({
grant_type: 'authorization_code',
code,
redirect_uri: REDIRECT_URI,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
});
const res = await fetch('https://www.linkedin.com/oauth/v2/accessToken', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params,
});
const data = await res.json();
// Save data.access_token somewhere safe
return data;
}
One‑time setup:
- Run
console.log(getAuthUrl())
, open the URL, authorize the app. - Capture the
code
query param from the redirect and feed it toexchangeCodeForToken
. - Save the returned
access_token
in.env
asLINKEDIN_ACCESS_TOKEN
.
⚡️ Tip: Tokens expire after 60 days. Store the refresh token (if you request
offline_access
) or set a cron job to re‑auth automatically.
5️⃣ Deploy & Test
- Local testing: Use ngrok to expose your localhost.
ngrok http 3000
- Update the Slack command’s Request URL to
https://<ngrok‑subdomain>.ngrok.io/slack/events
. - In Slack, type
/postln Hello LinkedIn world!
and watch it appear on your feed.
6️⃣ Bonus Tips & Tricks
- Template your posts – prepend a hashtag or a link to your blog automatically.
const formatted = `#TechThoughts ${message}\nRead more: https://myblog.com`;
-
Add images – use LinkedIn’s
media
object (requires uploading an asset first). - Rate‑limit safety – LinkedIn caps at 100 posts per day per app. Keep a counter if you’re automating a lot.
- Error handling – Slack expects a response within 3 seconds. If LinkedIn is slow, respond with a “Processing…” message and use a background job (e.g., BullMQ) to finish the post.
🎉 Wrap‑Up
You now have a plug‑and‑play service that turns any Slack slash command into a LinkedIn post:
-
Create a Slack app with a
/postln
command. - Spin up a Node.js server using Bolt.
-
Hook into LinkedIn’s
ugcPosts
API with an OAuth token. - Deploy (ngrok for dev, Vercel/Render/Heroku for production).
The whole thing fits in under 100 lines of code, but the impact? Huge. Your insights get broadcast the moment you type them, and you keep the conversation flowing across platforms.
Got ideas for extra features—like auto‑adding a screenshot, tagging a company page, or scheduling posts? Drop a comment below! 👇 Let’s keep the dev community buzzing.
References
Happy hacking! 🎈
Top comments (0)