DEV Community

Mudit Palvadi
Mudit Palvadi

Posted on

I built an app that reads my dyslexic friend's email for him

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

What I Built

Heads Up — an Android home-screen widget that shows at most three emails that actually matter, as three short plain lines, each with a play button so it can be listened to instead of read.

I built it for a friend of mine.

He is dyslexic. He is smart and entirely capable of running his own inbox, he just doesn't, because the inbox is a wall of text and the wall costs him more than the contents are worth. So important things sit there. A college form with a deadline. A question from a friend he wanted to answer. Things that would have taken four minutes, if he'd seen them on the day they arrived.

The insight

The usual advice for "I can't keep up with email" is filters, rules, priority inboxes, muting senders. All of it still leaves him doing the reading.

His problem isn't that the inbox is too noisy. It's that the inbox is somewhere he has to go. Nobody walks past their own front door. You have to make a decision, and deciding is the expensive part.

So: don't make him check it. Bring it to him. Three things on the screen he already looks at forty times a day, written in the fewest words that still mean something, and a button instead of a paragraph.

Three items maximum, ever. And when there's nothing, it says Nothing needs you today ✓ rather than showing an empty box — an empty widget gets deleted, and a deleted widget gets missed.

Demo

Code

Heads Up

MIT licensed — see LICENSE. That covers this source code only; the Gemma weights are downloaded at runtime under Google's Gemma Terms of Use.

The three things that need you today, on your home screen.

Built for a friend who is dyslexic, rarely opens his email, and misses the things that matter. Heads Up puts at most three flagged emails on his Android home screen as short plain lines, each with a ▶ button so he can listen instead of read.

The widget is the product. The app is only setup and a control panel.


Status — what is actually verified

This is the honest picture, because "it works" is not a useful claim.

Area State Evidence
Rules engine + cleaner Verified 20 hand-written fixtures; every pass/fail row in rules.md §8 asserted. Pure logic, no device needed.
On-device inference Verified on hardware Gemma 3 1B-IT via LiteRT-LM
…

MIT licensed. 32 commits, 277 tests, flutter analyze clean under
strict-casts / strict-inference / strict-raw-types.

flowchart TD
    A["Gmail (IMAP)<br/>EXAMINE + BODY.PEEK"] --> B["Cleaner<br/>HTML to text, strip quotes and signatures"]
    B --> C["RulesEngine<br/>VIP, keywords, deadlines, bulk"]
    C -->|not important| X["dropped"]
    C -->|important| D["Gemma 3 1B-IT<br/>on-device via LiteRT-LM"]
    D --> E["Validator<br/>shape and deadline match"]
    E -->|rejected| F["Template fallback"]
    E -->|accepted| G["ElevenLabs<br/>summary to mp3"]
    F --> H["WidgetSync"]
    G --> H
    H --> I["Home screen widget<br/>max 3 rows"]

How I Built It

Two decisions that mattered more than the model

Importance is never inferred by the AI. A 1B model asked "is this
important?" will confidently declare a shopping newsletter urgent. So the rules
engine decides — with auditable regex you can read and argue with — and the
model's only job is rewriting text already judged worth showing. If the rules
engine can explain why an email is on the widget, that explanation survives.

The model is never allowed to invent a date. The rules engine extracts
deadlines by regex and hands the value to the prompt. If the model's BY:
doesn't match, the entire output is rejected and a template is used instead.
For someone who might act on a wrong date, a dull correct line beats a fluent
wrong one every time.

Gemma running on his phone isn't a nice-to-have. It's the whole
architecture.

His inbox has personal things in it — medical, family, college. A cloud LLM
would mean every one of those emails crosses a network to be read, and I'd have
to tell him so. Running a 557 MB open-weight model locally means the most
sensitive step never leaves the device. It also means $0 per email, so
there's no meter quietly encouraging him to read fewer of his own messages.

The interesting part is what a small model forces you to build. A frontier
model could probably judge importance on its own. A 1B model can't — so the
architecture gets organised around what the model can't do: decide what
matters, and invent a date. Those two jobs are pushed into a deterministic,
readable, unit-tested layer, and the model is left doing the one thing it's
good at, rewriting text into plainer text.

That's a better shape regardless of model size: the parts that must be right are
verifiable, and the part that's good at pattern-matching prose is allowed to be
fuzzy because a validator stands behind it.

Where I wasn't open, said plainly: ElevenLabs is a proprietary cloud API.
It's the voice — the part he actually experiences — and a synthetic voice that
sounds like a robot would undercut the whole point. It's switchable off, and
when it's off his phone's own TTS reads the line. The network call carries a
~30-word summary, never an email, but it is still the one place content leaves
the device.

Prize Categories

  • Best Use of Gemma — Gemma 3 1B-IT runs fully on-device via LiteRT-LM and rewrites every flagged email, with each output validated against a rules-engine-extracted deadline before it's allowed to reach the screen.
  • Best Use of ElevenLabs — summaries are voiced with ElevenLabs and cached as mp3s on the device so play is instant and works offline.

Built with

Gemma 3 1B-IT ·
ElevenLabs · OpenCode ·
Flutter · enough_mail ·
home_widget ·
just_audio ·
flutter_tts ·
flutter_secure_storage

Top comments (3)

Collapse
 
arckydevindamaking profile image
Arcky-dev-in-da-making •

Thank you so much, mudit!!

Collapse
 
humaira_aishau25brs1319 profile image
Humaira Aisha U 25BRS1319 •

wow this is genuinely so cool!

Collapse
 
humaira_aishau25brs1319 profile image
Humaira Aisha U 25BRS1319 •

id totally use this