The bot could think. The bot could write. The bot could even publish. But in a social media landscape dominated by visuals, words alone weren't enough.
The Missing Piece
By this point, WizardThoughts had evolved significantly.
The platform could:
✅ Generate original content
✅ Create engagement-focused posts
✅ Store everything in DynamoDB
✅ Publish automatically to X
From a technical perspective, things were working.
From a social media perspective, something was missing.
The posts looked empty.
I had built a content engine.
What I hadn't built was a visual identity.
And on modern social platforms, visuals often determine whether people stop scrolling long enough to read the content.
The next challenge became obvious:
Every post needed its own unique piece of artwork.
Why Images Matter
Take these two posts:
Version One
Every great wizard begins as a student.
Version Two
Every great wizard begins as a student.
Accompanied by:
- An enchanted library
- Floating spell books
- Golden magical lighting
- A student surrounded by ancient knowledge
The words haven't changed.
The experience has.
Images create context.
They create atmosphere.
Most importantly, they create attention.
Exploring Image Generation
Since text generation was already running through Amazon Bedrock, my first instinct was to stay inside the Bedrock ecosystem.
The ideal workflow looked like:
Generate Quote
↓
Generate Image Prompt
↓
Generate Artwork
↓
Publish Together
Simple.
At least in theory.
The Model Hunt
The first surprise came from discovering that not all image models are available everywhere.
While experimenting, I discovered models that:
- Existed in one AWS region
- Didn't exist in another
- Were marked as legacy
- Required different API formats
Something as simple as changing AWS regions suddenly became important.
I found myself bouncing between:
London
Ireland
US East
US West
trying to discover which models were actually available.
For a while, my most common error looked like this:
The provided model identifier is invalid.
Nothing was wrong with the code.
The model simply didn't exist in that region.
The Nova Canvas Detour
Initially, I experimented with Amazon Nova Canvas.
On paper, it seemed perfect.
An AWS-native image generation service integrated directly into Bedrock.
Then reality arrived.
The model was marked as legacy.
Attempts to invoke it resulted in messages like:
Access denied.
This model is marked as Legacy.
The lesson was frustrating but useful:
Just because a service appears in a catalogue doesn't mean it is the right service for your account.
Enter Stability AI
Eventually I shifted towards Stability AI's image models through Bedrock.
These were actively supported and capable of generating entirely original artwork from text prompts.
This introduced a new architecture:
GenerateContent
↓
Bedrock
↓
Quote + Image Prompt
↓
GenerateImage
↓
Stability AI
↓
PNG Image
The workflow was finally beginning to resemble the original vision.
Building the GenerateImage Lambda
The GenerateContent Lambda already produced output like:
{
"quote": "Every wizard begins as a student.",
"imagePrompt": "Young wizard studying glowing spell books inside an enchanted library"
}
Now I needed a second Lambda.
Its job was simple:
- Read pending content from DynamoDB
- Use the image prompt
- Generate artwork
- Save the result
The process looked like this:
DynamoDB
↓
Image Prompt
↓
Stability AI
↓
Base64 Image
↓
PNG File
↓
S3
Prompt Engineering, Part Two
Creating image prompts required a different mindset from creating text.
A poor image prompt looked like:
Wizard library
Technically valid.
Visually boring.
A stronger prompt looked like:
Ancient enchanted library, floating spell books,
golden magical lighting, cinematic fantasy artwork,
rich colours, volumetric light, highly detailed,
social media quality, no text
The difference was dramatic.
The more descriptive the prompt became, the more consistent the results became.
Another Unexpected Problem
The image generation worked.
The upload didn't.
After successfully creating images, I suddenly started receiving:
PermanentRedirect
errors from S3.
At first I assumed permissions were broken.
They weren't.
The issue was embarrassingly simple.
My bucket was located in:
eu-west-2
while the code was trying to access:
eu-west-1
One region mismatch.
Hours of debugging.
A classic cloud engineering lesson.
The S3 Layer
Once the region mismatch was fixed, every generated image flowed into an S3 bucket.
The storage structure looked like:
wizardthoughts-images/
├── post-123.png
├── post-124.png
├── post-125.png
Each image became its own reusable asset.
This provided several benefits:
- Durable storage
- Easy retrieval
- Lower complexity
- Simpler workflow management
Most importantly, it separated content generation from content publishing.
Updating DynamoDB
The image generation process wasn't complete until DynamoDB knew about it.
A successful image generation updated the record:
{
"PostId": "post-123",
"Status": "Pending",
"ImageStatus": "Complete",
"ImageUrl": "https://bucket.s3.amazonaws.com/post-123.png"
}
This allowed downstream services to know exactly what stage every post had reached.
The database effectively became a workflow engine.
Building a State-Driven System
As more functionality was added, an interesting pattern emerged.
Every component only needed to know one thing:
What is the current state?
The workflow became:
Pending
↓
Image Pending
↓
Image Complete
↓
Published
No service needed to know what happened before.
No service needed to care what happened next.
Everything was driven entirely by state transitions.
That dramatically simplified the architecture.
Seeing the First Results
The most satisfying moment came when the first generated image appeared.
Not downloaded.
Not manually uploaded.
Not created in a design tool.
Generated automatically.
Stored automatically.
Ready for publishing.
The project suddenly felt real.
The content wasn't just being written anymore.
It was being illustrated.
Every quote now had a matching visual story.
Lessons Learned
Three lessons stood out more than anything else.
1. Images Are a Force Multiplier
Good content becomes significantly more engaging when paired with relevant visuals.
The artwork amplified the message.
It didn't replace it.
2. AI Image Generation Is Prompt Engineering
The same lesson from text generation applied to images.
Better prompts produced better outcomes.
The model wasn't the limiting factor.
The instructions were.
3. Regions Matter
Cloud services are rarely as universal as they appear.
Always verify:
- Region support
- Model availability
- Service limitations
before writing code.
It will save hours of debugging.
What's Next?
By this point, WizardThoughts could:
✅ Generate content
✅ Generate image prompts
✅ Create original artwork
✅ Store assets in S3
✅ Track workflow state in DynamoDB
The system was finally capable of producing complete content packages.
But one final challenge remained.
Everything still required orchestration.
The content engine needed a conductor.
In Part 4, we'll complete the journey by introducing EventBridge scheduling, automated publishing, workflow orchestration, and the architecture that transformed WizardThoughts into a fully autonomous social media platform.
Next: Part 4 — Going Fully Autonomous: EventBridge, DynamoDB, and Automated Publishing
Top comments (0)