DEV Community

孫昊
孫昊

Posted on • Originally published at jiejuefuyou.github.io

Day 61: I shipped a Twitter thread to my 60-day milestone account. Here's what n

Day 61: I shipped a Twitter thread to my 60-day milestone account. Here's what nobody tells you about indie launch threads.

Yesterday I crossed Day 60. 4 iOS apps in Apple's review queue. 6 Gumroad SKUs LIVE. 84 dev.to articles. $0 revenue.

Today I shipped my first 8-tweet thread on the milestone. Here's what I learned writing it that the typical "build in public" advice glosses over.

Tweet count is not the metric

Default advice: "make threads 8-12 tweets, that's the engagement sweet spot."

Real lesson: content density per tweet matters 10x more than count. 4 tweets with surgical numbers will outperform 12 tweets with vibes.

My thread had:

  • Tweet 1: hook with one specific number ($0 revenue, 4 apps in queue)
  • Tweet 2-4: what I shipped (6 Gumroad / 84 articles / 4 apps — concrete)
  • Tweet 5: the failure (zero sales)
  • Tweet 6: the real reason (no traffic, not bad product)
  • Tweet 7: what I'm doing about it
  • Tweet 8: CTA to follow + Day 90 plan

8 tweets, but each loadbearing. No tweet was "transition" filler.

CDP automation has 4 hidden gotchas

I shipped via Playwright CDP attached to my port-9222 Chrome. Hit these:

  1. Composer DOM duplication. X has both inline composer AND modal composer rendered simultaneously. Same data-testid="tweetTextarea_0". You MUST scope to div[role="dialog"] or you'll write to the invisible one.

  2. element.click() is anti-bot detected. Even with page.locator().click(), X anti-bot sometimes silently rolls back the action. The "Add tweet" button visually depresses but state reverts. Fix: use page.locator(selector).click() with Playwright's real-mouse-event mode, NOT page.evaluate("el.click()").

  3. "Add tweet" button only enables AFTER current editor has content. You can't pre-set up the thread structure. Must type → wait → check button enabled → click → type next.

  4. "Discard" button data-testid is confirmationSheetCancel (NOT confirmationSheetConfirm). Reverse from intuition. Misclick this and you nuke the entire draft.

These are 5-hour debugging sessions buried in a "10-minute" task. The X composer is brittle in a way that doesn't show in static HTML inspection.

Threads are not the funnel — they're the radar

I went in thinking "8 tweets = 1 conversion event."

Real model: each tweet is a radar ping. People who reply / quote / DM are the leads. The thread itself doesn't sell, the profile click rate from impressions is the real metric.

Targets I'm tracking 7 days from launch:

  • impressions: > 10k (baseline for a 600-follower account)
  • profile clicks: > 100
  • Gumroad referrals from Twitter: > 20
  • new follows: > 50

If profile clicks > 100, the thread did its job regardless of "did anyone buy?"

What I'd do differently

  1. Schedule for 9am ET, not midnight JST. I posted at midnight JST (11am ET) but indie / building Twitter is 9-11am ET prime.
  2. Pin tweet 1 immediately. Pinning is free distribution for 7 days. Default "post and pray" misses this.
  3. Quote-RT my own tweet 5 in 24 hours with a follow-up data point. X algorithm boosts self-quotes if there's NEW info.
  4. Tag 3 people in tweet 8 CTA — not for friends-feel, but to trigger their notification → reply → algorithmic boost.

The thread is here

https://x.com/Snakesun_H/status/2052380908423163968

If you're shipping your own milestone thread soon, the 4 CDP gotchas above will save you 5 hours.

What's next

Day 67 (next week) I'm posting the first-week data: real impressions, real conversions, real Gumroad referrals. No vibes, just numbers.

If you want the actual Python script that ships threads via CDP without the 4 gotchas, it's in the autoapp repo: orchestrator/scripts/x_thread_publish_v4.py.


Tools I used to ship this in 60 days:

Following the Day 60 → Day 90 journey: github.com/snake-sun

Top comments (0)