Inspiration
I'm on my computer all day. Every time Claude is generating something or my code is building, I'd grab my phone and doom-scroll TikTok for 10 minutes. The whole context-switch (pick up phone, unlock, open app) breaks my focus every single time.
So I thought, why can't TikTok just live in a strip on the side of my monitor and scroll itself while I keep working? That was the whole inspiration. Build a TikTok that doom-scrolls for me.
What it does
Mood Scroll is a Chrome extension. You open TikTok in a narrow strip on the side of your screen and it scrolls the feed for you. You pick what you want to see (cooking, gym girls, brain rot, or type your own niche) and a vision AI looks at every video as it loads. If it matches your mode, it watches the whole thing and double-taps to like. If it doesn't, it scrolls past in under a second.
After about 10 minutes the algorithm catches on and your For You page is fully tuned to whatever you asked for.
If you don't feel like picking a mode, there's an Auto Scroll mode that just plays through your normal feed hands-free and auto-likes everything. You sit there and work, it scrolls in the background.
How we built it
- WXT + TypeScript for the Chrome extension scaffolding
- Content script injected into tiktok.com with a Shadow DOM overlay so the UI doesn't clash with TikTok's CSS
- Vision classifier that captures 3 frames at 400ms, 900ms, and 1400ms into each video and sends them to GPT-4o through a LiteLLM proxy
- Focused per-mode prompts instead of one giant "classify into 15 categories" prompt. One tight "is this baddies yes/no" prompt per mode
- Two-phase matching: broad cluster while the algorithm is still training (matches related content to push TikTok faster), strict matches once it locks in
- Native double-tap gesture dispatched as mousedown/mouseup/click events on the video element. Triggers TikTok's real heart animation and gives a way stronger algo signal than clicking the sidebar like button
- Phone Mode that resizes the Chrome window to a 440px strip on the right edge of the screen and hides every piece of TikTok's UI except the video itself
Challenges we ran into
Loop watchdog. TikTok auto-replays videos that finish, so the naive timeout let videos loop forever. Fixed it by polling currentTime every 250ms and force-advancing if it drops (loop detected) or passes 92% of duration.
Title cards. Most TikToks open with 300 to 800ms of black screen or a title card before the actual content shows up. My first version captured one frame at t=0 and classified the title card as "other" which meant tons of false skips. Fixed by capturing 3 frames starting at 400ms in, past the intro.
Baddies matching shirtless men. Two-phase matching used the "fitness" category as a broad match for Baddies mode to push TikTok faster, but fitness includes shirtless guys doing deadlifts. So Baddies was happily auto-liking dudes for a while. Dropped fitness from the broad cluster.
Classifier model selection. I tried Gemini, Claude Haiku, GPT-4o-mini, and GPT-4o. The cheap models hallucinated badly (a guy in a car got classified as "baddies"). Landed on GPT-4o with focused per-mode prompts for the right balance of speed and accuracy.
Stale content scripts. When you reload the extension at chrome://extensions, Chrome doesn't re-inject content scripts into already-open tabs. The reset button literally couldn't work because the old code was still running. Fixed by auto-reloading any open TikTok tabs on extension update.
Accomplishments that we're proud of
Phone Mode actually works. You click one button and your entire Chrome window snaps to a 440px strip on the right edge of your screen, TikTok's nav and captions and sidebar all disappear, and you have a clean phone-shaped video player to work next to. It was the hardest piece visually and it landed.
The double-tap-to-like gesture. Took a while to figure out that dispatching mousedown, mouseup, click, and dblclick on the video element triggers TikTok's actual heart animation instead of just calling the sidebar like API. Stronger algo signal and it looks legit on screen.
Two-phase training algorithm. The For You page actually retunes in 10 minutes instead of an hour because of the broad-cluster-then-strict approach. You can watch the match rate climb in real time on the overlay.
Reset Algo flow that doesn't half-work. Click Reset, the tab hard-reloads, a fresh banner pops up confirming it, and TikTok's content preferences open in a new tab so you can also tell TikTok directly to refresh the feed. End to end, no stale state.
What we learned
- TikTok's video element is surprisingly accessible. currentTime, currentSrc, and duration are all readable from a content script
- The native double-tap gesture is way more reliable than clicking the sidebar like button. TikTok rate-limits sidebar clicks but not the in-video gesture
- Vision models lie when you give them too much context. Switching from one giant taxonomy prompt to small focused per-mode prompts cut false positives by like 60%
- Two-phase training actually pushes the algorithm faster than going strict from the start. Engaging hard with the broader content cluster for 10 minutes gives TikTok enough signal to retune the FYP
- Reloading a Chrome extension does NOT refresh already-open tabs. The old broken content script keeps running until you manually refresh. Hours of "why isn't this working" later, I added auto-reload on extension update
What's next for Mood Scroll
- Add Instagram Reels and YouTube Shorts. Same vision-classifier infrastructure, different DOM. The hard work is done.
- Mood scheduling. "Cooking videos in the morning, brain rot at night" without having to switch modes manually.
- Negative modes. "Show me anything except politics and engagement bait." Right now you pick what to see, not what to avoid.
- A receipt at the end of every session showing how many minutes you watched and what categories you actually consumed. An honest visual you look at before opening TikTok the next day.
- Submit to the Chrome Web Store as an unlisted extension so I can share it without making people sideload a zip
Built With
- bun
- canvas
- chrome
- gpt-4
- html2canvas
- html5
- javascript
- litellm
- openai
- railway
- shadow-dom
- typescript
- vite
- wxt
Log in or sign up for Devpost to join the conversation.