A LinkedIn content pipeline that drafts, asks, and publishes.
Every morning a post is written from a planned calendar and lands in Telegram with an Approve button. Tap it and it publishes on schedule. Reply with a note instead and the post rewrites itself within the hour. No one opens LinkedIn until the post is live.
Consistent posting is a discipline problem dressed up as a writing problem.
The client had a clear point of view and a backlog of ideas, and still posted about once a fortnight. Each post meant opening a doc, writing, finding or making an image, second-guessing it, and then remembering to publish. The writing wasn't the bottleneck; the dozen small steps around it were.
The brief was specific: one post a day, on brand, with a real human approving every single one before it goes out, and the approval had to take seconds, from a phone, not a login to any tool.
Two constraints shaped the design. The client did not want an AI posting unsupervised, so the approval step had to be a hard gate rather than a notification. And they did not want to pay for or debug an AI-agent-style workflow, so the orchestration had to be plain, inspectable nodes.
Two systems that never talk to each other, joined by a folder.
Claude's scheduled tasks and n8n have no shared runtime, so Google Drive is the shared state. Six folders under one parent act as a state machine: Calendar, Images, Pending Review, Revisions, Approved, Posted. A post is a text file plus one or more image files with the same base name, and which folder those files sit in is the only status that exists.
Files move left to right through Drive. The only loop is the revision path: a Telegram reply becomes a feedback file, the hourly task rewrites the post in place, and the updated file re-triggers the review notification.
Claude side: two scheduled tasks
| Task | Runs | Job |
|---|---|---|
| Daily generator | 06:00 local, every day | Reads today's row from the calendar, writes the post text, copies the matching image(s) from Images into Pending Review. |
| Revision handler | Hourly, at :25 | Looks for any *.feedback.txt in Revisions, applies the note, updates the post text in place, which re-fires the review notification. |
Each run is a fresh session with no memory, so every prompt carries its own folder IDs, naming rules and a guard: if there is no calendar row for today, stop and do nothing.
n8n side: three workflows, no AI nodes
Drive trigger → Telegram
Fires on file created or updated in Pending Review, filters to .txt, downloads the text and sends it to Telegram with an inline Approve button.
Telegram trigger → Switch
A button tap moves every file with that base name to Approved. A typed reply is written to Revisions as a feedback file for the hourly task.
Schedule → LinkedIn
Takes the oldest approved post, uploads each slide through LinkedIn's asset API in a loop, publishes, moves everything to Posted and confirms on Telegram.
Five deliverables, in the order they had to exist.
Content calendar
One row per day: date, phase, audience, format (image or carousel), post type, headline, core message, CTA, hashtags, status. Generated from a script kept on disk so it can be rebuilt without a Drive round-trip.
Brand renderer
A Python renderer built from the client's own logo and colours. Supersampled 3× and downscaled for clean curves. Light and bold variants alternate across days for rhythm.
Pre-rendered image library
Every image for the whole calendar rendered once, up front. YYYY-MM-DD.jpg for single posts, YYYY-MM-DD_01.jpg…_NN.jpg for carousels, so the filename alone tells the task which format a day is.
Scheduled task prompts
Self-contained prompts with hard-coded folder IDs, both naming shapes, a strict truth rule and an explicit ban on generating or uploading images.
n8n workflows as JSON
Three importable workflows built from Drive, Telegram, HTTP Request, Switch, Code and loop nodes. Re-select credentials and set the chat ID after import; nothing else to configure.
Five failures that produced no error message.
This is the part of the build that cost the most time and the reason the architecture looks the way it does. Each of these failed silently.
Never move image bytes through the AI connector.
Uploading a file through a model tool call caps out around 20,000 base64 characters, roughly 15 KB. A branded 1080×1350 JPEG is 100–200 KB. The run doesn't error; it hangs for hours and gets marked abandoned. We also saw silent truncation: a 13,817-byte file arrived as 6,872 bytes.
Fix: pre-render the entire library once, put it in Drive by hand, and have the scheduled task do a server-side copy. Zero bytes pass through the model.LinkedIn accepts the post and then quietly drops it.
A valid share URN comes back and the post never appears. The cause is almost always the image: palette or indexed PNGs and progressive JPEGs fail processing. Querying the asset endpoint shows CLIENT_ERROR.
A carousel is a loop, not a limit.
A single-image workflow with a "limit 1" node posts slide 1 of 8 and silently discards the rest. Inside a loop, n8n's item pairing also breaks after a binary upload.
Fix: sort slides by zero-padded filename, loop one slide at a time through register → download → upload, collect every asset URN, then build one media array after the loop completes.OAuth belongs to the account owner.
Automating someone's LinkedIn means they click Authorize in n8n's OAuth flow themselves. A retired scope in the request fails with an unauthorised-scope error, and tokens expire after roughly 60 days.
Fix: use current Community Management scopes, keep every secret in n8n credentials only, and tell the client in advance to expect a re-auth every couple of months.A rendered image can't be corrected after it ships.
Regulatory dates, prices and statistics move. Rendering a slide from memory nearly published three wrong dates under the client's brand.
Fix: every fact that lands in a graphic is web-verified first, and the task prompts carry a strict truth rule: never invent names, numbers or outcomes; insert a marked placeholder instead.Four calls to put an image post on LinkedIn.
The LinkedIn side is the least forgiving part of the pipeline, so it's worth showing exactly what workflow 03 does per post. Each slide goes through steps two and three in a loop; step four runs once with all the collected asset references.
- Identify the member.
GET /v2/userinforeturns the ID that becomes the author URN. - Register an upload for each image and receive a one-time upload URL and an asset reference.
- Upload the raw bytes to that URL with a PUT.
- Create the post with the text and the ordered media array.
Then every file for that post moves to Posted and Telegram gets a confirmation with the live URL. The workflow doesn't consider a post done until that URL opens; a returned URN is not proof of publication.
GET /v2/userinfo → sub ⇒ urn:li:person:{sub} POST /v2/assets?action=registerUpload X-Restli-Protocol-Version: 2.0.0 → uploadUrl, asset PUT {uploadUrl} body: baseline RGB JPEG bytes POST /v2/ugcPosts X-Restli-Protocol-Version: 2.0.0 author: urn:li:person:{sub} media: [asset_01 … asset_NN] GET /v2/assets/{assetId} status must not be CLIENT_ERROR
What "done" meant before we handed it over.
Automation that fails quietly is worse than no automation, so the sign-off checklist was about proving the silent paths, not the happy one:
- Every Drive folder ID listed and confirmed to resolve. A pasted ID with one stray character fails for days without a message.
- Image library count matched the calendar's day count, including every carousel slide.
- After each image copy, the returned file size compared to the source.
- Both scheduled tasks checked for a clean last run; a long "pending" almost always means image bytes.
- One real post pushed end to end and opened in the LinkedIn feed before anyone called it live.
What the client operates day to day: a Telegram chat. A post arrives each morning. They tap Approve, or type "make the second line punchier", and go back to their day. The calendar is an editable spreadsheet they own; the workflows run in their own n8n account; the images live in their Drive.
If eezadigital disappeared tomorrow, every part of this keeps running and every part is theirs to change.
Results to add: posting cadence before vs after, time per post, and engagement change over the first 30 days, once the client has signed off on sharing them.Tell us where the hours go. We'll show you what to get back.
Leave your email and we'll reply within one business day to set up a 30-minute call. No slide deck, no pressure.
Or write to us directly at eezadigital@gmail.com.