DEV Community

Youvandra Febrial
Youvandra Febrial

Posted on

Auto‑Post Your Slack Prompt to LinkedIn

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
Enter fullscreen mode Exit fullscreen mode

1️⃣ Set Up a Slack App & Slash Command

  1. Go to api.slack.com/appsCreate New App.
  2. Choose From scratch, give it a name (e.g., Slack2LinkedIn) and a workspace.
  3. 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]
  1. Enable Interactivity & Shortcuts (just to keep the UI happy).
  2. 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
Enter fullscreen mode Exit fullscreen mode

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!');
})();
Enter fullscreen mode Exit fullscreen mode

3️⃣ Get LinkedIn API Credentials

  1. Head to the LinkedIn Developer PortalCreate App.
  2. Fill in the basics, then under Products enable Sign In with LinkedIn and Share on LinkedIn.
  3. Add a Redirect URL (e.g., https://your-domain.com/auth/linkedin/callback).
  4. 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;
}
Enter fullscreen mode Exit fullscreen mode

One‑time setup:

  1. Run console.log(getAuthUrl()), open the URL, authorize the app.
  2. Capture the code query param from the redirect and feed it to exchangeCodeForToken.
  3. Save the returned access_token in .env as LINKEDIN_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
Enter fullscreen mode Exit fullscreen mode
  • 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`;
Enter fullscreen mode Exit fullscreen mode
  • 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:

  1. Create a Slack app with a /postln command.
  2. Spin up a Node.js server using Bolt.
  3. Hook into LinkedIn’s ugcPosts API with an OAuth token.
  4. 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)