This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

Sloth Reads: while you slept, the sloth read your pile

What I Built

Sloth Reads reads your read-it-later pile overnight, so you don't have to.

I bookmark DEV posts all the time. I almost never go back to them. My reading list had posts from 2022 in it, still waiting for a "later" that was never coming.

So I built a sloth to read them for me:

  1. You save things the way you already do: bookmark a post on DEV (it syncs every night), paste any link, or share it from your phone's share sheet (it installs as an app).
  2. Overnight, the sloth reads them, slowly and steadily. DigitalOcean Functions wake it every hour from 1 to 5 AM. Each time it reads a few articles with Gemma 4 and writes a short summary, three takeaways, and a verdict: worth reading, skim it, or skip it, with one honest reason written for me, not a generic reader.
  3. At 6 AM it writes a one-minute morning brief of everything it read.
  4. The good ones, it reads to me. "Read & listen" opens the article in a clean reader and an ElevenLabs voice reads it out, highlighting each word as it's spoken. I can tap any word to jump there, pick from five voices (switching mid-sentence carries on from the same sentence), and it remembers where I stopped, so tomorrow it picks up from that sentence.
  5. It counts the minutes I got back. A skipped article saves its whole reading time; a skimmed one saves all but a minute.

Who gets to be lazier? Anyone with a bookmarks folder they feel guilty about.

The reader: the spoken word is highlighted as Matilda reads

Demo

Try it: slothreads.souvikbiswas.com (no sign-up). Open the morning brief or any article with "Read & listen".

Sloth Reads on a phone The reader on a phone, dark mode

Code

GitHub logo sbis04 / sloth-reads

Overnight, an open model reads everything you saved to read later, decides what's worth your time, and briefs you in a minute the next morning. Then it reads the good ones to you, word by word.

Sloth Reads

Save it. Sleep on it.
Overnight, an open model reads everything you saved to read later, decides what's worth your time,
and briefs you in a minute the next morning. Then it reads the good ones to you, word by word

Live: slothreads.souvikbiswas.com · Demo video

Sloth Reads demo video

Sloth Reads: the morning brief, minutes saved, and today's verdicts

What it does

  1. You save things to read later: bookmark posts on DEV (synced every night), paste any link, or share it from your phone (it installs as an app with a share target).
  2. Overnight, the sloth reads them. DigitalOcean Functions wake it every hour from 1 to 5 AM; each time it reads a few articles with Gemma 4 and writes
    • a 2 to 3 sentence summary and three takeaways,
    • a verdict, worth reading, skim it, or skip it, with one honest reason aimed at you,
    • an embedding for search.
  3. At 6 AM it writes your morning brief…

MIT licensed, including the DigitalOcean deploy files.

How I Built It

Gemma 4 does the reading. In production it's gemma-4-31B-it on DigitalOcean's serverless inference; while building, it was gemma4 on Ollama on my Mac, with exactly the same code (one environment variable switches between them). For each article Gemma writes the summary, takeaways and verdict as JSON, and I give it a one-line profile of me, so "worth reading" means worth my time. It correctly skipped four 2022 hackathon announcements still sitting in my list: "The hackathon dates have passed, making the announcement irrelevant for current development."

bge-m3 does the remembering. Every article gets an embedding (the same open model locally and on DigitalOcean), so I can search my pile by meaning: "transcribing audio with flutter" finds my old Decifer post without those exact words.

DigitalOcean runs the night shift:

  • Functions with scheduled triggers are the sloth's alarm clock: 30 19-23 * * * (1 to 5 AM where I live) reads a few articles each hour; 30 0 * * * (6 AM) writes the brief. The function just pings the app, which does the slow work, so the function stays tiny.
  • App Platform runs the app from the Container Registry (free tier), on my own domain with HTTPS.
  • Serverless inference runs Gemma 4 and bge-m3.

Tiger Data is the memory. TimescaleDB on Tiger Cloud holds:

  • items with a pgvector embedding and a full-text index; search is hybrid (vector and keyword results merged with reciprocal rank fusion);
  • runs and saved as hypertables (every overnight run, every minute saved);
  • saved_daily, a continuous aggregate behind the "minutes saved per day" chart.

ElevenLabs is the voice, with word timings. The stream/with-timestamps endpoint returns audio and the start time of every character, which is what makes the live highlight possible. I stream it in paragraph-sized pieces, so:

  • audio starts in about a second;
  • generation stops the moment you stop listening (no paying for a whole article you abandoned);
  • every piece is cached with its timings, per voice, so replays are free and still highlight;
  • resuming or switching voice starts a new piece at the current sentence, which is cached too.

Visitors share a small daily voice budget, checked before every piece, so a busy day on the live site can't drain my credits. Everyone can always read.

Why Does Open Innovation Matter?

Because the sloth has to read everything, including the stuff I'll never read. Most of a reading pile isn't worth your time; that's the point. So the model reads far more than I ever will. With an open model at DigitalOcean's Gemma 4 price ($0.18 per million input tokens, $0.50 per million output), reading and judging an average article costs about a tenth of a cent. A whole night's pile costs less than a cent. That's what lets it read everything, every night, without me thinking about it.

Because what you read is personal. Your reading list says a lot about you. With open weights, the same Gemma and the same bge-m3 run on my own laptop through Ollama; I built and tested the entire thing that way, offline, for free. Anyone who wants their pile to stay on their machine can run it there.

Because the model is a setting, not a contract. Swapping Gemma for a bigger open model, or for one fine-tuned on my own "read / skip" choices, is an environment variable.

Where closed won: the voice. Open text-to-speech is getting good, but ElevenLabs gives me natural voices and character-level timestamps in one streaming call, and that's the feature people actually notice.

My Agent Session

I built Sloth Reads with Claude Code in a day: from reading 481 Week 3 posts to pick a category, to the overnight pipeline, the word highlight, the voice switching and this video.

Building Sloth Reads: an overnight reader with Gemma 4, DigitalOcean, Tiger Data and ElevenLabs
You

hi, new week now and new chanllenge

https://dev.to/challenges/hacktoberfest-week3-2026-10-19

do the same research we did for the last challenge, check all the elligible submission, which category would be best to target for better chance of winning, etc

This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation.

Summary:

Context

The user is Souvik Biswas (GitHub sbis04, DEV sbis04). We built Leaf Peep for the DEV "Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass" (event #79). The deadline was Oct 11, 11:59 PM PDT, and the post is already published. Today is 2026-10-10.

User-stated rules and preferences (keep applying)

  • Commits: "in the commit author just mention me and not claude please anywhere". Never add Co-Authored-By or Claude attribution, and commit as you go. This is saved in memory at ~/.claude/projects/-Users-souvikbiswas-MobileDev/memory/no-claude-commit-attribution.md, indexed in MEMORY.md.
  • No em dashes in the post.
  • Location privacy: "set my current location to somewhere in manhattan don …
Show more
Agent

Here's a LinkedIn version in plain language. LinkedIn suits a slightly longer story with a personal angle:

I spent this weekend building a little app for leaf peepers 🍁 Every October I end up asking the same question: are the leaves actually turning yet, and where should I go to see them? Foliage reports are weekly and vague, and they never cover the trees on my own street. So I built Leaf Peep. 📸 Point your phone at a tree and take one photo 🎨 AI gives it a fall colour score, from still green to peak 🗺️ It lands on a shared map, so everyone can see where the colour is right now 📅 Each spot gets a simple forecast, like "peak in about a week" ❤️ You can like other people's trees and climb a friendly leaderboard No account, no email. Pick any name and start walking. Photos are stripped of location data, and spots are rounded to about a kilometre, so nobody can track your walks. It started with my own October stroll around Manhattan, but anyone, anywhere can add the trees near them. The best part for me: it's meant to be ten seconds on your phone, then back outside 🌳 Try it: https://leafpeep.souvikbiswas.com How I built it: https://dev.to/sbis04/leaf-peep-an-open-model-rea … 
Show more
You

I just won the DigitalOcean challenge!

Agent

Congratulations, Souvik! 🎉 That's a great result for a weekend project, and it fits: the DigitalOcean side carried the whole live app, with the Droplet, the Gemma 4 scoring through their serverless inference, and the custom domain.

A few things worth doing now:

  • Keep the Droplet up for now. Taking it down after judging was the plan, but the winners announcement will likely bring visitors. It costs $12/mo, scoring stays within the daily budget of 500, and your $10 alert on that DigitalOcean account will flag anything unusual. I can check the live site and admin stats whenever you want.
  • Approve new photos. Visitors' photos stay private until you approve them at /admin, so check the "Photos to review" tile over the next few days.
  • Celebration posts. I can draft a short X post and a LinkedIn post that thank DEV and DigitalOcean and link the winners announcement, the app and the DEV post. Send me the announcement link and I'll write them.
  • README and landing page. I can add a "🏆 Winner, DigitalOcean prize" line to the README and the GitHub Pages site, and commit it under your name only.

Want me to go ahead with any of these?

Show more
You

can you open the leaf peep admin once

Agent
▸ ToolSearch select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__navigat...
select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__computer,mcp__claude-in-chrome__read_p …
▸ mcp__claude-in-chrome__tabs_context_mcp
{"availableTabs":[{"tabId":822617426,"title":"New Tab","url":"chrome://newtab/"}],"tabGroupId":13586
▸ mcp__claude-in-chrome__navigate https://leafpeep.souvikbiswas.com/admin
https://leafpeep.souvikbiswas.com/admin
Navigated to https://leafpeep.souvikbiswas.com/admin Tab Context: - Executed on tabId: 822617426 -
▸ mcp__claude-in-chrome__computer
Can't interact with browser-internal or unparseable URLs. Navigate to a web page first.
▸ mcp__claude-in-chrome__computer
Waited for 3 seconds Tab Context: - Executed on tabId: 822617426 - Available tabs: • tabId 82261
▸ mcp__claude-in-chrome__computer
Successfully captured screenshot (784x382, jpeg) - ID: ss_28579e31j — 0.5-scale view; coordinate fra

I've opened the admin page in Chrome: https://leafpeep.souvikbiswas.com/admin

It's asking for the admin token, because this Chrome tab hasn't saved it. I can't type the token in myself since this is the live site, not a local copy. Paste ADMIN_TOKEN from leaf-peep/.env into the field and click Open dashboard. The browser remembers it after that, so you only need to do this once.

Once you're in, check the Photos to review tile for new photos from visitors. If you'd rather not paste it, I can pull the same numbers (photos, walkers, likes, photos waiting for review) here in the terminal, using the token from .env without displaying it.

Show more
You

lert's stop the digital ocean droplet now, so that it doesn't charge me

Agent
▸ Bash Inspect teardown script, storage, and DO resources
$ Inspect teardown script, storage, and DO resources
#!/usr/bin/env bash # Destroys the leaf-peep Droplet so billing stops. Data and photos on it are del
You

The user sent a new message while you were working:
I don't need to keep the webpage active

This is how Claude Code surfaces messages the user sends mid-turn — within the running turn, often alongside the next tool result, rather than as a separate conversation turn. Address the message above as you continue this turn.

Agent
▸ Bash Find where photos live on the Droplet
$ Find where photos live on the Droplet
5:# and SPACES_* to store photos in DigitalOcean Spaces instead of the uploads volume. 6-services: 7
You

The user sent a new message while you were working:
it was mainly for the hackathon

This is how Claude Code surfaces messages the user sends mid-turn — within the running turn, often alongside the next tool result, rather than as a separate conversation turn. Address the message above as you continue this turn.

Agent
▸ Bash Back up Droplet photo uploads locally
$ Back up Droplet photo uploads locally
Unable to find image 'alpine:latest' locally latest: Pulling from library/alpine e2de96513ba9: Pulli

The photos are backed up (54 files, 13 MB). Now destroying the Droplet:

▸ Bash Destroy the Droplet and verify nothing billable remains
$ Destroy the Droplet and verify nothing billable remains
Name Status Destroyed. Billing for the Droplet has stopped. --- ID Name Status ID Name 
▸ Bash Commit the gitignore change
$ Commit the gitignore change
58a7c76 Souvik Biswas Ignore local backups folder

I destroyed the Droplet, so it won't charge you anything more. A powered-off Droplet keeps billing, which is why I deleted it instead of stopping it.

  • Nothing billable is left: doctl shows no Droplets, volumes, snapshots or reserved IPs on the leafpeep2 account.
  • Photos are saved: before deleting it I copied all 54 photos from the Droplet to leaf-peep/backups/droplet-uploads/ (13 MB). That folder is ignored by git, and I committed that change under your name only.
  • The database is unaffected. It lives on Tiger Cloud, so all photo records, walkers and likes are still there.
  • What's offline: https://leafpeep.souvikbiswas.com no longer loads. The landing page on GitHub Pages, the repo, the DEV post and the YouTube video are all still up.

Optional cleanup you can do later:
- Delete the leafpeep DNS record (it now points at a deleted server) in Cloudflare.
- Revoke the DigitalOcean inference key (MODEL_KEY) in the DO console. It only costs money when it's used, so this isn't urgent.

If you ever want the app back, ./deploy/up.sh recreates the Droplet. You'd then copy the photos from the backup into it.

Show more
You

but this doesn't load: https://leafpeep.souvikbiswas.com

beacuse we stopped digital ocean I though it was just for the ai aprt?

Agent

No, the Droplet was more than the AI part. It ran the whole live app:

  • the website itself (the map, camera, leaderboard and admin pages);
  • the server behind it, handling uploads, likes and search;
  • the stored photos.

The AI scoring was the only piece that ran separately, on DigitalOcean's pay-per-use inference. The database lives on Tiger Cloud, so all the data is safe. When you said you didn't need to keep the webpage active, I took that as fine to take the site offline, but I should have spelled out that deleting the Droplet means exactly that.

Your options:

  1. Leave it offline (free). The GitHub Pages landing page, the repo, the DEV post and the video all still work. I can change the "Open the app" button and the README link so people don't land on a dead page.
  2. Bring it back as it was (about $12/month). I run ./deploy/up.sh and copy the 54 backed-up photos in, which takes about 10 minutes. You'd destroy it again whenever you like; billing is by the hour, so a few days costs well under $1.
  3. Bring it back for less (about $6/month). Same thing on the smaller 1 GB Droplet. The content-checking models are tight in that much memory, so it could be unstable. I …
 </div> <button class="agent-session-expand-btn" type="button">Show more</button> </div> </div> </div> <div class="agent-session-message agent-session-user"> <div class="agent-session-role-badge agent-session-role-user"> You </div> <div class="agent-session-content"> <div class="agent-session-text"> <p>ok fine keep it offline</p> 

now, a new week hackathon is happening: https://dev.to/challenges/hacktoberfest-week2-2026-10-12

let's participate in this with a competely new project

read all the details from tje webpage

I think the prizes and the categories are the same

let me know what ideas are you thinking of?

 </div> </div> </div> <div class="agent-session-message agent-session-assistant"> <div class="agent-session-role-badge agent-session-role-assistant"> Agent </div> <div class="agent-session-content"> <div class="agent-session-tool-call"> <button class="agent-session-tool-toggle" aria-expanded="false" type="button"> <span class="agent-session-chevron">&#x25B8;</span> <span class="tool-name tool-name-toolsearch">ToolSearch</span> <span class="tool-input-preview">select:mcp__devrelay-gateway__get_challenges,mcp__devrelay-gateway__get_chall...</span> </button> <div class="agent-session-tool-detail" style="display:none"> <div class="tool-section"> <div class="tool-section-label">Input</div> <pre class="agent-session-pre"><code>select:mcp__devrelay-gateway__get_challenges,mcp__devrelay-gateway__get_challenge_details</code></pre> </div> <div class="tool-section"> <div class="tool-section-label">Output</div> </div> </div> </div> <div class="agent-session-tool-call"> <button class="agent-session-tool-toggle" aria-expanded="false" type="button"> <span class="agent-session-chevron">&#x25B8;</span> <span class="tool-name tool-name-mcpdevrelaygatewaygetchallenges">mcp__devrelay-gateway__get_challenges</span> <span class="tool-input-preview"></span> </button> <div class="agent-session-tool-detail" style="display:none"> <div class="tool-section"> <div class="tool-section-label">Input</div> </div> <div class="tool-section"> <div class="tool-section-label">Output</div> <pre class="agent-session-pre"><code>{&quot;Ok&quot;:[{&quot;id&quot;:82,&quot;title&quot;:&quot;Hacktoberfest Open-Source AI Challenge: Week 4&quot;,&quot;slug&quot;:&quot;hacktoberfest-week4</code></pre> </div> </div> </div> <div data-collapsible> <div class="agent-session-text agent-session-text-collapse"> <p>I read the full details through DEV's challenge API. First, the timing:</p> 

Week 2 closes tonight at 11:59 PM PDT (06:59 UTC Oct 19). Assuming you're on India time, that's about 17 hours from now. It's doable, but only with a tight, small project. Week 3 starts tomorrow (Oct 19, 16:00 UTC) and gives a full week, but its theme isn't announced yet.

Week 2 in short. The theme is Side Hustle: build something with open-weight models or open-source AI that someone would actually pay for. The open part has to be what makes it work. The post should explain why open matters here: cost, privacy, fine-tuning for a niche, or avoiding lock-in. There are bonus points for landing a first user and telling them whether that person paid, would pay, or what they asked for next.
- Judging: writing counts most, then fit with the theme, creativity, technical execution, and use of a partner's tech.
- Prizes: the same as last week. $250 overall, six featured categories at $200 (Gemma, DigitalOcean, Render, TabPFN, Tinker, Arduino), and eleven partner categories at $100, now including a .tech domain. One win per person per challenge.
- To enter: use the Side Hustle submission temp …

Show more
You

her's the post template:

<pasted_content id="dd41">
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle

What I Built

<!-- What does it do, and who would pay for it? What problem does it solve for them? -->

Demo

<!-- Share a deployed link or a video demo. -->

Code

<!-- Show us the code! You can embed a GitHub repo directly into your post. -->

How I Built It

<!-- Which open-source AI did you use (open-weight models, agent harnesses, frameworks, local inference), and how is your project built around it? -->

Why Does Open Innovation Matter?

<!-- Why does open innovation matter for what you built? What did it make possible that a closed API wouldn't? -->

My Agent Session

<!-- Optional, but judges love it. Save your session with DevRelay and embed it with the agent_s …

Show more
Agent
▸ AskUserQuestion
Your questions have been answered: "Which idea should we build for tonight's Week 2 deadline (11:59 

Going with the shoot culler, and you'll be the first user. I'll check the local setup first.

▸ Bash Check Ollama models, Node, time, and folders
$ Check Ollama models, Node, time, and folders
NAME ID SIZE MODIFIED gemma4:e2b b37049369adf 4.6 GB 2

I'll build it as Keeper, a local app you start with a folder of photos. Everything runs on the laptop with Gemma 4 through Ollama.

▸ Bash Scaffold the Keeper project and install deps
$ Scaffold the Keeper project and install deps
found 0 vulnerabilities repo name free
You

The user sent a new message while you were working:
what categories would this qualify in>

This is how Claude Code surfaces messages the user sends mid-turn — within the running turn, often alongside the next tool result, rather than as a separate conversation turn. Address the message above as you continue this turn.

[Request interrupted by user]

first allow do an assessment of which categories would be the easiest to win based on all th submission yet and from the last few weeks ones

based on that we might decide to change the prject idea

Agent
▸ ToolSearch select:mcp__devrelay-gateway__get_articles,mcp__devrelay-gateway__execute_dev...
select:mcp__devrelay-gateway__get_articles,mcp__devrelay-gateway__execute_dev_api_request,mcp__devrelay-gateway__get_article_content
▸ Bash Fetch all #hf26challenge posts from the DEV API
$ Fetch all #hf26challenge posts from the DEV API
page 1: 100 page 2: 100 page 3: 100 page 4: 100 page 5: 100 page 6: 100 600 [{"d":"2026-10-15","n":1
▸ Bash Fetch remaining pages and count posts by date
$ Fetch remaining pages and count posts by date
2904 2026-10-01 2 2026-10-02 40 2026-10-03 122 2026-10-04 429 2026-10-05 337 2026-10-06 82 2026-10-0
▸ Bash Download bodies of recent posts and list devteam announcements
$ Download bodies of recent posts and list devteam announcements
The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file
You

[Request interrupted by user for tool use]

have youn stared the assessment yet??

Agent
▸ Bash Count partner mentions per week from tags and titles
$ Count partner mentions per week from tags and titles
week1: 1210 posts week2: 852 posts weekend: 842 posts category 

I counted mentions of each partner in the tags, titles and summaries of all 2,904 #hf26challenge posts:

Category (prize) Weekend Week 1 Week 2 so far
Gemma ($200) 107 194 151
TabPFN ($200) 9 16 19
GitHub Copilot ($100) 6 2 18
Render ($200) 4 5 10
Sentry ($100) 2 0 6
ElevenLabs, Entire ($100) 6 / 2 4 / 4 4 / 4
Tinker ($200) 1 2 3
DigitalOcean ($200) 0 1 2
Tiger Data ($100) 0 0 2
Temporal, MongoDB, SerpApi, .tech ($100) 1 / 3 / 0 / 0 5 / 3 / 1 / 0 2 / 2 / 2 / 2
Arduino ($200) 0 1 1

Week 2 has 852 posts so far, against 1,210 for Week 1.

Caveat: this undercounts, because most people list categories only in the post body, which I didn't download. The proportions are what matter, and they're very lopsided.

What this means:
- Gemma is crowded. About one in six posts mentions it, so it's the hardest category to win despite paying $200.
- DigitalOcean, Tinker and Arduino pay $200 and have almost no competition. Last week you won DigitalOcean against probably one or two other entries, likely inc …

Show more
You

prioritize the ones those qualify for this week first

Agent

Here are the Week 2 categories ranked by how winnable they are tonight. That weighs how many entries mention each so far, the prize, and whether we can use it properly in about 16 hours.

# Category Prize Week 2 entries so far Can we do it tonight?
1 DigitalOcean $200 2 ✅ Yes. Same setup as your win: Gemma on DigitalOcean's inference plus a Droplet
2 Tiger Data $100 2 ✅ Yes. Reuse the Leaf Peep account and setup
3 .tech domain $100 2 ⚠️ Possibly. It needs a .tech domain, which may come free through hacktoberfest.com/my. Worth checking
4 SerpApi $100 2 ⚠️ Only if search fits the idea. A listing writer could use it to look up competing apps' keywords
5 Arduino $200 1 ❌ Only if you have a board at home
6 Tinker $200 3 ❌ Fine-tuning takes too long for tonight
7 Temporal / MongoDB / Mastra / Backboard $100 1–2 each ⚠️ Possible, but each adds new setup work
8 ElevenLabs / Entire $100 4 each ⚠️ Moderate competition
9 Sentry / Render $100 / $200 6 / 10 ⚠️ More crowded
10 GitHub Copilot / TabPFN $100 / $200 18 / 19 ❌ …
Show more
You

can you actually check all the project body for the category they are participating for the ones those qualify for this week>

Agent

I'll download the full text of the 852 Week 2 posts, fairly slowly so DEV doesn't block us. Then I'll read each post's "Prize Categories" section.

Related posts