https://bsky.app/profile/aininjaarmy.bsky.social
Building SoftFlow in public: AI that turns job-site photos into Instagram & LinkedIn posts for trades businesses. No auto-publish — every post gets human approval first.
Follow the thread below for the real story: agents, failures, and lessons. 🥷🏗️
#buildinpublic #AI #n8n
Spent a decade on job sites. Most construction photos never leave the phone. Why? Taking a photo, writing a caption, choosing hashtags — that’s three decisions plus effort. For a busy day, it’s zero. Automation doesn’t just publish. 🥷
#buildinpublic #trades #automation
Spent a decade on job sites. Most construction photos never leave the phone. Why? Taking a photo, writing a caption, choosing hashtags — that’s three decisions plus effort. For a busy day, it’s zero. Automation doesn’t just publish. 🥷
#buildinpublic #trades #automation
Fifth lesson, the last: I named an army of 29 and built exactly 7. Budget was the governor on ambition. That’s not a compromise, that’s the feature. Constraints force decisions you’d never make otherwise. 🥷
#buildinpublic #n8n #lessonslearned
Fifth lesson, the last: I named an army of 29 and built exactly 7. Budget was the governor on ambition. That’s not a compromise, that’s the feature. Constraints force decisions you’d never make otherwise. 🥷
#buildinpublic #n8n #lessonslearned
Fourth lesson: an agent once told me the job was done. Clean summary, confident tone. The file was untouched. Since then, nothing gets marked done without proof - not from AI, not from me. hashtagi:
Confidence is not evidence. 🥷
#buildinpublic #AI #lessonslearned
Fourth lesson: an agent once told me the job was done. Clean summary, confident tone. The file was untouched. Since then, nothing gets marked done without proof - not from AI, not from me. hashtagi:
Confidence is not evidence. 🥷
#buildinpublic #AI #lessonslearned
Third lesson looking back: I didn't leave OpenClaw because n8n had better features. I left because OpenClaw had a wall I couldn't move - and no feature list compensates for that. Pick tools by their walls, not their brochures. 🥷
#buildinpublic #n8n #lessonslearned
Third lesson looking back: I didn't leave OpenClaw because n8n had better features. I left because OpenClaw had a wall I couldn't move - and no feature list compensates for that. Pick tools by their walls, not their brochures. 🥷
#buildinpublic #n8n #lessonslearned
Second hindsight lesson: I tested the happy path for weeks before asking one simple question — what happens when a stranger messages my bot? Answer: it crashed. Luck, not design. Test with hostile input from day one. 🥷
#buildinpublic #n8n #lessonslearned
Second hindsight lesson: I tested the happy path for weeks before asking one simple question — what happens when a stranger messages my bot? Answer: it crashed. Luck, not design. Test with hostile input from day one. 🥷
#buildinpublic #n8n #lessonslearned
If I could restart from day zero: skip the army. One boring workflow, doing one real thing, beats 22 named agents doing nothing. I spent weeks on mythology before shipping a single post. Name things after they work. 🥷
#buildinpublic #n8n #lessonslearned
If I could restart from day zero: skip the army. One boring workflow, doing one real thing, beats 22 named agents doing nothing. I spent weeks on mythology before shipping a single post. Name things after they work. 🥷
#buildinpublic #n8n #lessonslearned
The story has nearly caught up to today. Current state: one piece left in the approval system -parsing the button callbacks. Four actions to route: publish all, publish IG only, reject, reject & block. This is where I am right now. Building it this summer🥷
#buildinpublic #n8n
The story has nearly caught up to today. Current state: one piece left in the approval system -parsing the button callbacks. Four actions to route: publish all, publish IG only, reject, reject & block. This is where I am right now. Building it this summer🥷
#buildinpublic #n8n
Architecture call: the approval system lives in its own workflow, completely separate from the main pipeline. Why? So I can break, patch and redeploy the pipeline without ever touching pending approvals. Blast radius, contained. 🥷
#buildinpublic #n8n #architecture
Architecture call: the approval system lives in its own workflow, completely separate from the main pipeline. Why? So I can break, patch and redeploy the pipeline without ever touching pending approvals. Blast radius, contained. 🥷
#buildinpublic #n8n #architecture
Asked a friend to send a photo to my bot — no authorization, no whitelist, just a stranger’s number. Something crashed, nothing published. Good outcome, wrong reason.
Anyone who finds the bot can talk to it. That has to change. 🥷
#buildinpublic #n8n #security
Asked a friend to send a photo to my bot — no authorization, no whitelist, just a stranger’s number. Something crashed, nothing published. Good outcome, wrong reason.
Anyone who finds the bot can talk to it. That has to change. 🥷
#buildinpublic #n8n #security
Validation day: fed the pipeline real photos from an actual Vitrum job site. Seven photos, one reel. The AI caption correctly told two different glass systems apart — in the same frame. Months of prompt work, confirmed in one test. 🥷🏗️
#buildinpublic #AI #automation
Validation day: fed the pipeline real photos from an actual Vitrum job site. Seven photos, one reel. The AI caption correctly told two different glass systems apart — in the same frame. Months of prompt work, confirmed in one test. 🥷🏗️
#buildinpublic #AI #automation
Hardest prompt work yet: teaching the model to tell Vitrum systems apart. Not by material -by structure. Modular segmented frames mean one product line, smooth unified glass means another.
Ten years of glazier knowledge, compressed into a prompt. 🥷🏗️
#buildinpublic #AI #glazing
Hardest prompt work yet: teaching the model to tell Vitrum systems apart. Not by material -by structure. Modular segmented frames mean one product line, smooth unified glass means another.
Ten years of glazier knowledge, compressed into a prompt. 🥷🏗️
#buildinpublic #AI #glazing
Next up: automatic product overlays. The AI now detects which Vitrum.se system is in frame, picks a label position, checks if the photo is dark or light — and renders a clean product tag onto the image itself.
Small detail, very client-facing. 🥷🏗️
#buildinpublic #n8n #AI
Next up: automatic product overlays. The AI now detects which Vitrum.se system is in frame, picks a label position, checks if the photo is dark or light — and renders a clean product tag onto the image itself.
Small detail, very client-facing. 🥷🏗️
#buildinpublic #n8n #AI
Milestone day. Pressed “Publish” on the approval bot — callback traveled through the tunnel, hit n8n, parsed clean. The full chain: Telegram → Cloudflare → webhook → workflow. End to end, no polling, no hacks.
Months of walls, and now a door. 🥷🏗️
#buildinpublic #n8n #automation
Milestone day. Pressed “Publish” on the approval bot — callback traveled through the tunnel, hit n8n, parsed clean. The full chain: Telegram → Cloudflare → webhook → workflow. End to end, no polling, no hacks.
Months of walls, and now a door. 🥷🏗️
#buildinpublic #n8n #automation
Finished the tunnel setup: two hostnames, one for n8n webhooks, one for the reel renderer. Rebuilt the n8n container with the new webhook URL baked in — kept the old container as backup, just in case.
Trust nothing, keep backups. 🥷
#buildinpublic #n8n #selfhosted
Finished the tunnel setup: two hostnames, one for n8n webhooks, one for the reel renderer. Rebuilt the n8n container with the new webhook URL baked in — kept the old container as backup, just in case.
Trust nothing, keep backups. 🥷
#buildinpublic #n8n #selfhosted
Same evening as the domain: installed a named Cloudflare tunnel as a proper systemd service on the VPS. No more random URLs, no more restarts wiping the address.
One connector, permanent, surviving reboots. Infrastructure that acts🥷
#buildinpublic #n8n #selfhosted
Same evening as the domain: installed a named Cloudflare tunnel as a proper systemd service on the VPS. No more random URLs, no more restarts wiping the address.
One connector, permanent, surviving reboots. Infrastructure that acts🥷
#buildinpublic #n8n #selfhosted
The tunnel to my n8n instance had a random URL that changed on every restart. Fine for testing, embarrassing for anything real.
So I bought a domain. softflowcm.com — the project’s first permanent address on the internet. 🥷🏗️
#buildinpublic #n8n #selfhosted
The tunnel to my n8n instance had a random URL that changed on every restart. Fine for testing, embarrassing for anything real.
So I bought a domain. softflowcm.com — the project’s first permanent address on the internet. 🥷🏗️
#buildinpublic #n8n #selfhosted
Built the approval bot. Tested it. getUpdates kept returning empty — no errors, no clues, just silence, even though Telegram confirmed messages were delivered.
Never found the root cause. Made a new bot instead. 🥷
#buildinpublic #n8n #debugging
Built the approval bot. Tested it. getUpdates kept returning empty — no errors, no clues, just silence, even though Telegram confirmed messages were delivered.
Never found the root cause. Made a new bot instead. 🥷
#buildinpublic #n8n #debugging
Same day as the bug fixes, bigger decision: no post goes live without approval. Not just LinkedIn — Instagram too, split by format. Two independent gates, not one shared button.
Slower by design. That’s the point. 🥷
#buildinpublic #n8n #automation
Same day as the bug fixes, bigger decision: no post goes live without approval. Not just LinkedIn — Instagram too, split by format. Two independent gates, not one shared button.
Slower by design. That’s the point. 🥷
#buildinpublic #n8n #automation
Timestamps in the tracking sheet never matched reality. Turned out the VPS clock runs UTC, and my code just trusted it blindly — every log was quietly off by hours.
Fixed with an explicit Stockholm timezone conversion. 🥷
#buildinpublic #n8n #debugging
Timestamps in the tracking sheet never matched reality. Turned out the VPS clock runs UTC, and my code just trusted it blindly — every log was quietly off by hours.
Fixed with an explicit Stockholm timezone conversion. 🥷
#buildinpublic #n8n #debugging
LinkedIn Status in my tracking sheet always said “unknown.” Spent longer than I’d like to admit before finding it: a Merge node set to Combine mode, silently swallowing the second input every time.
Switched to Append. Fixed instantly. 🥷
#buildinpublic #n8n #debugging
LinkedIn Status in my tracking sheet always said “unknown.” Spent longer than I’d like to admit before finding it: a Merge node set to Combine mode, silently swallowing the second input every time.
Switched to Append. Fixed instantly. 🥷
#buildinpublic #n8n #debugging
Every caption opened with the same em dash. Every single one. Turns out my few-shot examples in the prompt all used em dashes — the model wasn’t following a rule, it was just copying my style.
Show, don’t just tell. 🥷
#buildinpublic #n8n #promptengineering
Every caption opened with the same em dash. Every single one. Turns out my few-shot examples in the prompt all used em dashes — the model wasn’t following a rule, it was just copying my style.
Show, don’t just tell. 🥷
#buildinpublic #n8n #promptengineering
First real content bug: captions came out with 14-15 hashtags. Way too many, way too spammy. Took a while to find it — the prompt itself had two contradicting instructions fighting each other.
Fixed, down to 4-6. 🥷
#buildinpublic #n8n #promptengineering
First real content bug: captions came out with 14-15 hashtags. Way too many, way too spammy. Took a while to find it — the prompt itself had two contradicting instructions fighting each other.
Fixed, down to 4-6. 🥷
#buildinpublic #n8n #promptengineering
Content isn’t one shape. A single photo, a carousel, a reel — each needed its own branch in the pipeline, its own logic, its own failure points, its own way to break.
One workflow pretending to be three specialists. 🥷🏗
#buildinpublic #n8n #automation
Content isn’t one shape. A single photo, a carousel, a reel — each needed its own branch in the pipeline, its own logic, its own failure points, its own way to break.
One workflow pretending to be three specialists. 🥷🏗
#buildinpublic #n8n #automation
First technical decision: Instagram’s Basic Display API wasn’t going to cut it for actual publishing. Had to migrate the whole approach to Facebook Graph API before writing a single caption.
Foundations first, features later. 🥷🏗️
#buildinpublic #n8n #MetaAPI
First technical decision: Instagram’s Basic Display API wasn’t going to cut it for actual publishing. Had to migrate the whole approach to Facebook Graph API before writing a single caption.
Foundations first, features later. 🥷🏗️
#buildinpublic #n8n #MetaAPI
After OpenClaw, Ninja Army, Dev.to bots, Pinterest experiments — one thought stuck: what if I built something for my actual day job? Glass partitions, not AI trends.
That thought became SoftFlow. 🥷
#buildinpublic #AI #n8n
After OpenClaw, Ninja Army, Dev.to bots, Pinterest experiments — one thought stuck: what if I built something for my actual day job? Glass partitions, not AI trends.
That thought became SoftFlow. 🥷
#buildinpublic #AI #n8n