PostCreator
How I Tried to Automate Writing Popular Science Articles about the IT World — and It Kind of Worked
Recently, the second version of this tool was released — I described it in this article: https://medium.com/@power_dot/postcreator-v2-e73136d7932d
Hi, my name is Ilia, and watching the incredibly rapid development of AI, I decided to “disrupt” another profession — content creators, or as they’re called, social media managers.
The initial idea was simple: I want more posts on LinkedIn to increase my reach, but I don’t have the time to write them. So, why not let AI handle it for me for just 5 cents?
Let’s take a look at the tasks I needed to solve:
- Writing the article
- The articles must not be repetitive
- I need current, relevant topics
- The text should not sound like it’s AI-generated but rather in a friendly, human tone
- I need a hook for comments
- I need hashtags - Creating an image
- The image should visualize the article’s problem
- The image should feature a headline and subheadline with a hook to entice reading
- The text should be readable and not overlap with anything
Great! It feels like we’re getting closer after laying out the plan.
But the most interesting part is still ahead.
I built a network of several GPTs and DALL·E so that, just like on a real production line, they would generate something, pass it to the next one in turn, and so on in a cycle.
Given that even GPT-4 sometimes struggles to handle complex tasks correctly (like writing an article according to specific rules due to context loss during generation), I decided to break down one big task into several smaller ones. Each AI would be given only the piece it needed to complete. This way, the context for each AI remains short, which makes task completion more accurate.
Chapter 1. Storage
For storing the articles, I decided to use a simple PostgreSQL database.
The structure I used involved two main tables:
- Social Media Authorization Table — to store data for logging in through social media platforms.
- Articles Table — to store the content of previously created articles.
What’s in the Articles Table?
Here’s what each field represents:
- id — The unique identifier for each article.
- topic — The main idea or theme of the article.
- topicReason — The reason behind choosing that particular topic.
- title — The article’s title (used in the image).
- subtitle — A subtitle for the article (also used in the image).
- content — The full body of the article.
- imageKey — The filename of the image associated with the article.
- createdAt — Timestamp when the article was created.
- shared — A flag that indicates if the article was published on social media.
- views — The number of views the article has received.
In summary, the table looks like this:
These data points serve two key purposes:
- To confirm that the program is functioning correctly.
- To assist the program in generating new articles based on the content and performance of previous ones.
Chapter 2. Generation.
(One second, let me finish my cola.)
Let’s dive into the coolest part of my article generation tool — how it thinks and what it writes.
As I mentioned earlier, I divided the task across several GPTs using function-calling so they would return their results only in the format I need.
Meet the team!
topicsCreator
This is the assistant that gets a list of articles with their view counts from the last two months and is responsible for generating a list of 15 new topics for future posts. It returns something like this:
[
"One of the easiest ways to learn English is to become a programmer.",
"Understanding AI in Scientific Research: A Beginner's Guide",
"Discovering Vue 3: The Future of Frontend Development",
"5 Things You Didn't Know About DALL-E 3",
…
]topicSelector
This assistant receives the topics generated by topicsCreator as well as the list of articles with their view counts. Its task is to choose one topic and explain why it was selected.
It returns something like this:
{
"topic": "Understanding AI in Scientific Research: A Beginner's Guide",
"reason": "Given the previous topic on learning English through programming, it makes sense to introduce a technology-focused topic but one that has a broad appeal and broad applicability. AI in scientific research is a hot and timely subject, drawing interest from not just tech enthusiasts but also from the general public and researchers across various fields. This will provide variety to your site while appealing to a wide audience."
}titleSubtitleCreator
This one creates a title and subtitle for the selected topic, which will be used for the article’s image.
It returns something like this:
{
"title": "AI in Science",
"subtitle": "Exploring how AI is reshaping scientific research for beginners."
}textCreator
Generates the article text based on the topic and the reason for its selection.
It returns something like this:
{
"text": `Ever thought of AI as the Sherlock Holmes of scientific research? No deerstalker hat, but AI is a real game-changer. Just like Sherlock solves mysteries using deductive reasoning, AI sifts through vast data to find patterns, make predictions, and generate insights previously unimaginable…
#AI #ScientificResearch #TechInnovation`
}textChecker
This assistant checks the generated text. It receives the full text, the topic, and the reason for topic selection. It ensures:
- The article’s idea is consistent and complete (since sometimes GPT generates incomplete texts).
The article includes hashtags that match the article’s concept (hashtags are crucial for page growth!).
It returns something like this:
{
"complete": true,
"hashtags": true
}If any parameter is false, the article goes back for revision until it’s perfect according to textChecker.
Get Ilia Rychagov’s stories in your inbox
Join Medium for free to get updates from this writer.
thumbnailPromptCreator
Generates a prompt for DALL-E based on the topic.
It returns something like this:
{
"prompt": "A detailed, non-futuristic image of a server room with multiple active servers. Include a light background and emphasize data processing and threads connecting between the servers. No people faces."
}DALL-E 3
This part is straightforward: it generates the image based on the prompt. Then I overlay a random frame and place the title and subtitle on the image.
I made five frames for this purpose.
imageChecker
This is the Vision API assistant. It receives the composed image and answers two questions:
- Is the text readable?
- Does the text not overlap with anything?
It returns something like this:
{
"readable": true,
"noOverlap": true
}If any of these values are false, the image is recreated.
That’s it! After that, everything is saved in the database and sent to social media.
Chapter 3. System Prompting
Of course, a neural network on its own won’t do anything.
First, you need to clearly explain what you expect from it, ideally providing a few examples, and in the case of function calling, you also need to give it a function schema with some arguments.
Overall, modern neural networks are quite easy to guide with clear instructions.
Here’s how I explained things to TopicSelector, for example:
You help me choose one topic from those presented to you to write an article on.
I will provide you with a list of articles that already exist and a list of topics that I am thinking of implementing.
You must help me choose only 1 topic from the list of suggested topics and explain why.
Repeating topics one after another is a bad idea, but from time to time (after some interval) you can continue a previously existing topic.
I strive for variety in the articles on my site, so I want to make the topics as interesting and varied as possible.
Call the generate function as your submission.And here’s the function it has to call:
{
"name": "generate",
"description": "Function that submits selected topic",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "Selected topic"
},
"reason": {
"type": "string",
"description": "Reason why the topic was selected"
}
},
"additionalProperties": false,
"required": [
"topic",
"reason"
]
}
}And yes, this is done for each AI in the chain:
Chapter 4. Additional Features
As you can imagine, I simply had to equip this tool with some extra cool features!
Web Server
I created a small API for myself that allows me to perform the following operations:
- GET /api/posts — Retrieves a list of articles from the database, so I don’t have to query it manually as often.
- POST /api/makePost — Manually triggers the process of creating a post (came in handy during debugging).
- POST /api/makePostWithOwnTopic — Creates a post with a custom topic! For example, if I come up with an interesting idea and want the AI to beautifully write it and generate an image.
- POST /api/{social}/setToken — An endpoint for updating authorization data for auto-posting.
Cron
Of course, my posts are released completely automatically.
I scheduled them to be generated every even day at 15:00 UTC+0.
By the way, if a post has already been published today (e.g., if I manually created an article via the tool), no new post will be generated. I don’t want to spam the feeds of hardworking people with too many posts.
CI/CD
Automatic code deployment to the server via GitHub Actions whenever there are updates. There’s not much to explain here — it just works!
These features make the entire process seamless and give me full control over the tool’s behavior without much hassle.
Chapter 5. Problems I Encountered
Incorrect Uploads to LinkedIn
A very strange issue: when I upload articles via the API, LinkedIn only posts part of them. This happens inconsistently, and I couldn’t pinpoint the cause. I debugged it manually, and the only theory I have is that it could be due to escaping certain characters or encoding issues.
As a result, sometimes I have to update the post manually by copying it from the database and pasting it into the LinkedIn post editor.
Images Often Look Similar
Often, the generated image ends up featuring some kind of workspace or server room.
Sure, I understand this is peak geekiness, but come on, is our IT world really so boring that it can only be visually represented through such a narrow range of images? This issue isn’t fully resolved yet, but I suspect it could be improved by tweaking the prompts for thumbnailPromptCreator.
Infinite Loop
Once, during the early development stages, I encountered an infinite loop in text regeneration.
The issue was simple: since social networks have text length limits, when the AI-generated article text was too long, it would be sent for regeneration. In about 2 hours, this ended up costing me around $10, which taught me the following valuable lessons:
- Since GPT is a text-based model, telling it “the text should be less than 3000 characters” is pointless. You have to use good old-fashioned length checks (e.g., JavaScript’s string.length).
- For any long text, I send the entire version back to GPT and append “Make it shorter” (or something like that).
- If after 5 attempts it still fails to shorten the text, I create a new version of the text based on the same topic.
- If after 5 attempts to create a new text on the same topic it still fails, I regenerate the topic itself.
Chapter 6. Tech Stack
- Node.JS + TypeScript
- PostgreSQL
- OpenAI GPT-4 (4o)
- OpenAI DALL·E 3
- OpenAI Vision API
- LinkedIn API
Chapter 7. Conclusions
While the “Dead Internet” theory is more of a meme than a proven social issue, I ultimately managed to create my own little pocket media outlet, which I occasionally read myself. Not only is it interesting to see what your creation does, but you can also sometimes learn life hacks from it that you hadn’t thought of before.
By building this pipeline, I was once again convinced that integrating AI into processes — whether for companies or individuals — is extremely easy. It literally took me 6 hours to build and another 4 to debug.
I’m considering sharing the code on my GitHub (@powerdot), but I’d like to tidy it up a bit first.
What do you think about a future where at least half of the sources of information and customer support (like in Amazon) will be generated by AI?








