The lesson wasn’t in the code
I spent a week building an AI-assisted publishing engine — one idea in, three native formats out: a blog post, a LinkedIn carousel, and a YouTube Short, each staged for review and released on a human’s say-so. The interesting part wasn’t the rendering pipeline or the React dashboard. It was three shifts in how I worked: let the data pick the work, automate the mechanics, and stop blaming the tool.
1. Read the analytics before writing the post
The instinct is to write what you find interesting. The discipline is to look first. I pulled a LinkedIn analytics export into the dashboard and the picture was clarifying, if a little humbling:
- Reach was fine; engagement was thin — under 1% on ~900 weekly impressions.
- The audience was mostly local and mostly not my ICP — a large share in one metro, and a long tail of industries that will never engage with a post about rate-limiting an LLM API.
- The content that did land was tactical — API design, cost-cutting, retry strategies. Reference material people save, not hot takes.
So I built an Audience view to track this over time, and — because the export only gives a publish date, not a time — I recovered the publish hour straight from each post’s id (LinkedIn ids are snowflake-style: the high bits are a timestamp). That turned “post whenever” into a day-of-week × time-of-day heatmap. With a few posts it’s only directional, but the loop is the point: topic, format, and timing are decisions you make from evidence, not vibes.
2. Automate the mechanics, keep the judgment
Turning one source into three formats by hand is an afternoon of tool-juggling. So I made it a pipeline: generate the carousel, auto-render the Short (off in CI, not on my laptop), and stage all three on the calendar in a pending state. Nothing goes live on its own — a human reviews each as it would actually appear and hits release.
That division is the whole game. The machine does the breadth — drafting, rendering, captioning, scheduling. I keep the part that needs taste: is this true, is it on-brand, is it ready. The automation earns its keep precisely because there’s a gate between “generated” and “published.”
3. The mindset shift: stop blaming the tier, read the API
This is the one worth keeping. Twice this week, something broke, and the easy story was “the service is the problem.”
When a batch of Short renders failed, the lazy conclusion was “the free tier is throttling us — we need to pay.” It wasn’t. Two real causes hid under that story: a TypeScript error a bundler had quietly skipped, and a concurrency limit — the voice API caps how many requests run at once, and I’d fired six renders simultaneously. The tier wasn’t conspiring against me; I’d ignored the documented contract. The fix wasn’t money, it was serializing the work to respect the concurrency rule — which the docs spell out plainly.
And earlier, the assistant I was working with nearly published to my real channel on the assumption I was on a paid plan I’d never confirmed. The right model isn’t “trust the tool’s assumptions” — it’s operator-owned compliance: the rules that carry real-world consequences are switches the human sets, grounded in the actual terms, never inferred.
The pattern in both: blame is a dead end; the API reference and the knowledge base are the way out. “It’s the free tier” is a story you tell when you haven’t read the limits. The moment I treated the service’s documentation as the source of truth instead of my own frustration, the failures turned into one-line fixes.
The connective tissue: verify, don’t assume
Underneath all three is the same habit. Don’t argue from memory about which repo deploys — run the experiment. Don’t trust a decoded timestamp — check it against a post whose date you know. Don’t assume a bundler typechecked your code — run the type checker. Don’t assume a service is broken — read what it actually promises. Every place I substituted a quick assumption for a five-minute check, the check won.
What I’d add
Here’s the part nobody tells you: AI tooling amplifies whatever habit you bring to it. Bring blame, and you’ll get a faster way to be wrong and ship it. Bring curiosity — read the analytics, read the API, read the terms — and you get a genuinely capable collaborator that handles the breadth while you hold the judgment. The engine I built this week works not because I found a magic tier or a clever prompt, but because, every time it broke, I went to the documentation instead of the blame.
That’s the whole upgrade. Not the model. The method.
Frequently Asked Questions
How can you recover the publish time of a LinkedIn post if the analytics export only shows a date?
LinkedIn post IDs are Snowflake-style identifiers, meaning the high-order bits of the ID encode a millisecond-precision UTC timestamp. By extracting and decoding those bits, you can reconstruct the exact publish hour without relying on the analytics export, enabling day-of-week and time-of-day engagement analysis.
What is the difference between automating content mechanics and automating content judgment?
Automating mechanics means delegating repeatable, deterministic tasks — format conversion, rendering, calendar staging — to code or CI pipelines. Automating judgment would mean letting the system decide what goes live, which introduces quality and brand risk. The recommended pattern is to automate mechanics fully while keeping a mandatory human approval step before any content is published.
How should LinkedIn analytics data influence a content strategy?
LinkedIn analytics exports reveal the gap between reach and engagement, audience geography versus your ICP, and which content formats or topics actually drive saves and interactions. Using this data to build a tracked Audience view lets you make topic, format, and timing decisions from evidence rather than intuition, closing the feedback loop between publishing and performance.
Why run video rendering in CI rather than locally when building a content automation pipeline?
Rendering short-form video (such as YouTube Shorts) is computationally expensive and slow on a developer laptop, and tying it to a local environment makes the pipeline fragile and non-repeatable. Offloading rendering to a CI job makes it reproducible, parallelizable, and decoupled from the developer’s machine, treating content generation as a first-class build artifact.