Skip to content

poojithdevan4D/auto_linkedin

Repository files navigation

auto_linkedin

Post to LinkedIn automatically, every day, for free. No paid scheduler, no LinkedIn Premium, no server, no monthly fee. Your machine can be off — it all runs on GitHub's free infrastructure.

You write your posts as plain text files. auto_linkedin handles the rest: picks the next post each day, generates a clean image card, publishes it to LinkedIn, and drops your link in the first comment (where LinkedIn doesn't penalise it).

posts/01.txt  ──►  [ daily GitHub Action ]  ──►  your LinkedIn feed
meta/01.json  ──►  generated image card    ──►  + link in first comment

Why it exists

Every "schedule your LinkedIn posts" tool wants a subscription. None of the moving parts here actually cost money:

Piece Cost
GitHub Actions (the scheduler) Free — unlimited on public repos
LinkedIn API (posting + comment) Free — no Premium required
Image cards (Pillow) Free

So this is a free, self-hosted alternative you fully own.

What it does

  • ✅ Posts one queued post per day — or two a day (morning + evening slots)
  • ✅ Generates a branded dark image card per post (5 layouts, 4 accent colours)
  • ✅ Adds your link/source as the first comment (better reach than a body link)
  • ✅ Reliable: each window front-loads retries + fallbacks to survive GitHub's flaky cron, and a per-slot guard means it never double-posts
  • ✅ Timezone-aware "day" (TZ_OFFSET_MINUTES) so scheduling follows your clock
  • ✅ Runs entirely in the cloud — your computer can be off

It does not write your posts for you (that needs an AI/human). You supply the text; it handles posting. Simple and free.


Setup (~15 minutes, one time)

1. Use this template

Click "Use this template" → Create a new repository (or fork it). Make it private if you like — private repos still get plenty of free Actions minutes.

2. Create a free LinkedIn app

  1. Go to https://www.linkedin.com/developers/appsCreate app. You must attach a LinkedIn Page; a free placeholder Page is fine.
  2. On the Auth tab, copy your Client ID and Client Secret.
  3. Under Authorized redirect URLs, add exactly: http://localhost:8000/callback
  4. On the Products tab, add "Sign In with LinkedIn using OpenID Connect" and "Share on LinkedIn" (usually approved instantly).

3. Get your token (runs locally, once)

cp config.example.json config.json     # paste your Client ID + Secret into it
python3 get_token.py                    # opens a browser → click Allow

This writes tokens.json with your access token and your person_urn.

4. Add the secrets to GitHub

In your repo → Settings → Secrets and variables → Actions, add:

Secret Value (from config.json / tokens.json)
LINKEDIN_CLIENT_ID your client id
LINKEDIN_CLIENT_SECRET your client secret
LINKEDIN_ACCESS_TOKEN access_token from tokens.json
LINKEDIN_ACCESS_EXPIRES_AT access_expires_at from tokens.json
LINKEDIN_PERSON_URN person_urn from tokens.json
LINKEDIN_REFRESH_TOKEN refresh_token (leave empty if none)

5. Make the cards yours

Edit brand.json with your name + tagline (shown in every card's footer).

6. Set your time (and timezone)

In .github/workflows/post.yml:

  • Edit the cron: lines — times are UTC; the default targets ~08:00 IST. Keep the window pattern (several attempts + fallbacks): GitHub's free cron regularly delays or skips single slots, and the window is what makes posting reliable. The script guarantees it still posts at most once per slot.
  • Set TZ_OFFSET_MINUTES to your UTC offset in minutes (IST 330, CET 60, EST −300, PST −480) so "one post per day" follows your day.

7. Go

Push your changes. Add your posts (below), and it posts one per day. Test immediately with Actions → Daily LinkedIn post → Run workflow.

Optional: post twice a day

Uncomment the EVENING window cron block in post.yml and set SLOT_BOUNDARY_UTC_HOUR to any UTC hour between your two windows. Each window ("am" / "pm") posts at most once per day, so you get exactly two posts daily — never doubles. (Heads-up: on LinkedIn, two posts/day can compete with each other for reach; many people do better with one strong post.)


Writing posts

Each post is three files sharing a number:

  • posts/NN.txt — the post text (posted in order, lowest number first).
  • meta/NN.json — describes the image card (see below). Optional; omit for text-only.
  • comments/NN.txt — the first comment, e.g. a link. Optional.

Generate/preview a card locally:

pip install Pillow
python3 render_card.py 01        # writes posts/01.png
python3 render_card.py --all

Card layouts (meta/NN.json)

accent: green · blue · purple · amber. layout is one of:

  • stat — big number: {"layout":"stat","accent":"green","tag":"// note","headline":"...","stat":"6.5x","stat_label":"..."}
  • statement — big bold claim: {"layout":"statement","accent":"amber","tag":"// take","headline":"...","sub":"..."}
  • list — numbered points: {"layout":"list","accent":"blue","tag":"// tips","headline":"...","items":["...","..."]}
  • compare — two columns: {"layout":"compare","accent":"purple","tag":"// vs","headline":"...","left":{"title":"A","lines":["..."]},"right":{"title":"B","lines":["..."]}}
  • news — headline + figure: {"layout":"news","accent":"blue","tag":"// news","date":"2026-06","headline":"...","stat":"10x","stat_label":"..."}

The included posts/01 and posts/02 are examples — replace them with your own.


Good to know

  • State: state.json tracks what's posted so nothing repeats. The Action commits it back after each run.
  • Token expiry: LinkedIn access tokens last ~60 days (personal apps usually don't get a refresh token). When posting stops, re-run python3 get_token.py and update the LINKEDIN_ACCESS_TOKEN / LINKEDIN_ACCESS_EXPIRES_AT secrets. GitHub emails you when a run fails, so you'll know.
  • Queue empty? When you run out of posts, it simply stops until you add more.
  • Timing: GitHub cron is best-effort — expect posts within the window, not to the exact second.

License

MIT — do whatever you want with it. Built by Poojith Devan. If it's useful, a ⭐ is appreciated.

About

Post to LinkedIn automatically, every day, for free. No paid scheduler, no Premium, no server. GitHub Actions + LinkedIn API.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages