Field notes from a solo dev shipping in public.

A code-first record of automation pipelines, small web apps, paper trading experiments, and AI-assisted development. Screenshots, commands, and failure notes are the main material.

Featured notes

Featured
Tools & Dev Environment

One build setting killed all 61 tests during boot

Defaulting actor isolation to the main actor synthesizes an isolated deinit only for classes that do not write one. The classes that wrote nothing are the dangerous ones — the exact opposite of intuition.

7 min read
script -> edge-tts -> caption sync -> ffmpeg
The Business Reality

The same caption won by 325% in one app and lost by 42% in another

I read five store product page A/B tests on the same day. All five treatments were the identical lever — synthesized captions — and the results spread from -42% to +325%. And my power calculation from days earlier was 9x wrong because it used pre-dedupe impressions.

7 min read
Automation Pipeline

The flag I set to zero was on, and it burned 43 topics

MediaWiki API booleans are true if the parameter is present, whatever its value. exintro=0 cut article bodies to 292 characters, and verdicts built on those 292 characters permanently blacklisted 43 perfectly good topics.

5 min read

Latest posts

All posts
On the left, a verification log reading 'five reviewed, five approved'; on the right, the same log reread as 'zero rejections'
AI-Assisted Dev5 min read

My Review Committee Had Never Once Said No

I added an LLM review stage to an unattended publishing pipeline and committed it as verified. The verification: five Japanese posts, all approved. Here is what an all-approve result proves about a gate, and what it does not.

#llm-judge#content-pipeline#automation#verification
Left: a channel-setup script taking country and language as arguments. Right: a hook-data grid with only three apps and two languages filled.
Automation Pipeline3 min read

The Channel Was One Script. The Hooks Were One File Per App Per Language.

One commit added a channel-setup script and hook translation data. The channel side takes country and language as arguments and scales for free. The content side needs a hand-filled entry per app per language before the renderer has anything to overlay. A note on how deep 'multi-language support' actually goes.

#localization#youtube#oauth#shorts
Two-panel diagram: on the left, a native-app branch attaching Korean base hashtags to an English Short; on the right, both the web and native branches reading per-language basetags
Automation Pipeline3 min read

My English Shorts Were Carrying Korean Hashtags

My YouTube uploader already localized hashtags for web-app videos. The native-app branch still attached a single Korean base-tag set to every language. This post covers a fix that had landed in only one of two branches, the 20-line change that closed the gap, and what I still don't know.

#youtube-shorts#hashtags#i18n#localization
Flow diagram of 27 blog posts converted into video scripts one by one, with generation stopping at the end
Automation Pipeline4 min read

My script generator was built to run out at 27

I added a daily job that turns blog posts into video scripts and queues them before publishing. On purpose, its only source is the 27 blog posts I actually wrote, so it stops on its own once they are used up. Where to stop the automation turned out to be the real decision.

#automation#launchd#llm#video-pipeline
Left: a Reel whose cover is a solid-color intro screen. Right: a Reel whose cover is set to an app-screen frame.
Automation Pipeline3 min read

My Reels cover was selling a blank intro, not my app

I auto-crossposted my short videos to Instagram Reels, and the cover came out as the solid-color intro screen. The offset parameters were ignored for Reels, so I switched to extracting the cover image myself, hosting it, and passing its URL.

#instagram#reels#thumbnail#ffmpeg
Left: a post with placeholders and pending links. Right: the same post with diagrams in place and the empty video section gone.
Screenshots & Assets3 min read

My articles were shipping empty frames

Several posts had placeholders where concept diagrams belonged, and posts with no video still rendered a video section. One commit added 17 diagrams and hid the empty video sections. One post still couldn't be fixed the cheap way.

#placeholders#svg#nextjs#frontmatter
Left: different apps sharing one hashtag set. Right: separate generated and cached hashtag lists per app.
Automation Pipeline3 min read

My Sleep App and My K-pop Quiz Were Wearing the Same Hashtags

My Instagram crosspost pipeline put the same default hashtags on every app. Nothing errored, because the pipeline only checked that tags were attached, never that they fit the app. This post covers generating tags once per app, caching them, keeping the defaults only as a fallback, and what I still don't know.

#instagram#hashtags#claude-cli#automation
Diagram of four promotion channels where only the Instagram app cards still read the web app manifest
Automation Pipeline6 min read

My Instagram App Cards Were Still Selling Web Apps

Told to promote only store apps, I audited four channels and found just one still pushing web apps. Swapping its content pool wasn't enough. Language, price claims, and tone all came along with it, and a running experiment window had to be reopened.

#instagram#localization#itunes-lookup#automation
Concept diagram: on the left, a paragraph with a name removed; on the right, the same name still embedded in a URL path and an OG image filename.
Shipping & Infra3 min read

The name I scrubbed from the text was still in the URL

I set out to mask two identifiers across my blog and internal docs. I assumed that meant editing sentences. One of them was in a post's filename, which is its URL slug, so renaming it also meant changing the URL, the OG images, and a slug list in a design doc.

#privacy#slug#build-output#grep
A launchd job shown as loaded with zero runs, next to the Day key that makes it monthly
Automation Pipeline3 min read

The job that grounded my posts had never run

The launchd job that refreshes the store-listing file, the only grounding source for my auto-published Threads and Facebook posts, had zero runs since it was loaded. The cause was one plist key: Day=1. No errors, not even a log file, so nobody noticed.

#launchd#macos#scheduling#monitoring