The problem
Managing content on LinkedIn, Instagram and Facebook manually takes about 45 minutes a day. Multiplied by 6 working days, that's nearly 4.5 hours a week spent on copy-pasting, hashtag research and adapting tone for each platform. Not to mention that every platform has its own preferences: LinkedIn wants bullet points and a professional tone, Instagram wants emoji and a CTA, Facebook wants a conversational approach with no hashtags.
The solution was obvious. The implementation wasn't.
The 6-node architecture
The workflow runs on n8n self-hosted on a Raspberry Pi and follows this schema:
| Node | What it does |
|---|---|
| Cron trigger | Fires every day Mon–Sat at 09:00 |
| Code (fs) | Reads with fs.readFileSync and looks for the file dated today in /home/node/.n8n/contenuti/ |
| IF | If the file exists → continue; otherwise → error notification on Telegram |
| Groq API | Llama 3.3 70B with response_format: json_object → produces 3 optimized versions |
| HTTP Request ×3 | Publishes to Graph API (IG), Graph API (FB page feed), LinkedIn UGC Posts API |
| Telegram | Confirmation notification with a preview of the published text |
A note on n8n 2.x: the executeCommand node is no longer available. To read files from the filesystem you need to use the Code node with require('fs'). This is an important difference from the older guides you'll find online.
One prompt, three different texts
The most interesting part of the architecture is how Groq generates the content. Instead of making three separate API calls, I use response_format: json_object with a single prompt that directly produces an object with three keys:
- LinkedIn: professional tone, bullet points, technical hashtags, max 1300 characters
- Instagram: engaging text, moderate emoji, hashtags at the bottom, a CTA, max 2200 characters
- Facebook: conversational, short, invites comments, no hashtags
One API call, three versions optimized for each algorithm. The cost per post with Groq (llama-3.3-70b-versatile) is essentially zero within the current free tier.
The 3 problems no guide tells you about
This is the part that's worth the read.
1. The Meta token isn't the page token. The Instagram and Facebook API requires different tokens depending on what you want to do. The user token isn't enough to post to a Facebook Page. You need to derive the page access token dynamically by calling /me/accounts on every run and using the specific page's token. I lost two hours on this before figuring it out.
2. instagram_content_publish isn't included by default. Even with a correctly generated long-lived token, if you don't explicitly enable this scope in the Meta app, Instagram returns error 10: "Application does not have permission for this action." The fix: enable the permission in the Meta Developer app settings, regenerate the token, extend it with fb_exchange_token to bring it to 60 days.
3. The JSON breaks if the text contains quotes. This was the sneakiest bug. Telegram received a malformed body every time Groq returned text containing double quotes, backslashes or newlines. The notification arrived, but with the text truncated or corrupted. The fix: in the Code node, I sanitize the text with a replace that strips \r\n"\\ before using it as previewText.
The technical part gets solved in a Saturday. The part that takes time is the creative one: writing good content. Automation doesn't replace strategy — it frees you up to work on it.
How I add a piece of content
The operational flow is deliberately simple:
- I write a
.mdfile incontenuti/linkedin/YYYYMMDD_title.mdwith the post draft - I run
python publish.py YYYYMMDD linkedinwhich copies it to the Pi asYYYYMMDD_contenuto.md - n8n reads it automatically at 09:00 and publishes to all three platforms
The naming convention matters: the workflow looks for the file whose name starts with today's date in YYYYMMDD format. If it finds nothing, it notifies via Telegram through a secondary bot.
Real cost
This is one of the most concrete advantages of self-hosting:
- n8n on Raspberry Pi: €0/month
- Groq API (llama-3.3-70b): free within current limits, then ~€0.001/post
- Meta and LinkedIn tokens: free (expire every 60 days, semi-automatic renewal)
- Telegram bot: free
Cost per post: essentially zero. Cost in time after the initial setup: zero.
What I'd add
The system works, but there are three natural evolutions I'll implement sooner or later. AI-generated images for Instagram (right now I use a static image from a URL). Platform-differentiated scheduling: LinkedIn performs better early morning, Instagram in the evening. An analytics loop that automatically tweaks the Groq prompt based on previous posts' performance.
The third point is the most interesting — and the most ambitious. But I'll save that for a future article.