This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
Sloth Digest is a small web app that reads your group chats so you don't have to.
You paste in a noisy chat from WhatsApp, Slack, Telegram or email. A few seconds later you get three things:
- A two-line summary of what actually happened
- What needs you, with the person and the exact deadline
- What you can safely ignore (good-morning messages, stickers, match banter)
It also shows a rough "minutes saved" figure. It divides the words you skipped by an average reading speed of 200 words per minute, so treat it as an estimate.
Anyone who has come back to 200 unread messages and had to scroll for the one line that said "pay by Saturday" gets to be a little lazier. That was the goal.
Demo
Live demo: https://sloth-digest.onrender.com
There is a Try a sample chat button, so you can see a full result without pasting anything private. The sample is a made-up chat about a trip and a deadline.
Code
https://github.com/ypunit757-prog/Sloth-Digest
How I Built It
The stack is deliberately small: a Node + Express server and a plain JavaScript frontend, with no framework and no build step.
The open-source AI piece is Gemma, Google's open-weight model. The server has one switch, AI_PROVIDER, that decides how Gemma is run:
-
On my laptop: Gemma runs through Ollama (
gemma3:4b). Inference is fully local. - In the deployed demo: The same Gemma family is served through the Gemini API, and the app is hosted on Render.
The route handler is the same either way. Only the model call changes:
const text = PROVIDER === "gemini"
? await askGemini(model, buildPrompt(chat))
: await askOllama(model, buildPrompt(chat));
const digest = extractJson(text);
A few things I learned along the way:
- Gemma on the Gemini API takes no system instruction. I put the rules in the prompt itself instead, and used one prompt for both providers.
- Small models don't always return clean JSON. The server strips markdown fences, pulls out the JSON object, and validates the shape before it reaches the UI.
-
The browser never sees a key. It only talks to
/api/*, so the Gemini key lives in a Render environment variable. The server also rate-limits requests and caps input at 12,000 characters. - Slowness is a feature. The loader is a slow-moving bar, in keeping with the sloth theme.
Why Does Open Innovation Matter?
Group chats are some of the most private text we have. They hold family plans, money, health news and gossip. Pasting that into a closed API means trusting a company with it.
Because Gemma has open weights, I could build the same app so it runs entirely on my own machine. With Ollama it works offline, costs nothing per run, and sends nothing anywhere. A closed API wouldn't let me make that promise.
Open weights also gave me freedom to move. The same model family runs locally and on a hosted API, and I switched between them with one environment variable. If a model improves or a price changes, I can swap it without rewriting the app.
I'll be honest about the trade-off: my hosted demo calls Gemma through an API, so the demo is not private the way local mode is. The local mode is the privacy-first version, and the hosted one is there so you can try it quickly.
The Lazy Payoff
The app's own estimate for the sample chat (about 120 words) is roughly half a minute of reading saved. That's small for one chat, but it adds up over a busy week of active group chats.
[
Prize Categories
- Best Use of Gemma: Gemma is the core of the app. It runs locally through Ollama and is served through the Gemini API for the hosted demo.
-
Best Use of Render: The app is deployed on Render with a
render.yamlblueprint, so the whole deploy is one click plus an API key.
Top comments (0)