DEV Community

Meena
Meena

Posted on Edited on

The email she never saw: Missing deadlines kept my friend out of open source, so I built her a reminder that explains the rules too.

Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝

At the start of this year, my friend decided she wanted to get into open source. She read up, found the programs, GSoC, Outreachy and others, and made a plan.

Then the dates started slipping past her.

The programs do send emails. Hers sat in spam, or under everything else in her inboxes. By the time she noticed, the application window had closed, and the next one was six months or a year away. Each miss made the next one feel heavier.

And the date was only half of it. Even when she caught one, she wasn't sure what to prepare, whether she was eligible, or where to start.

I looked at her situation and thought: another calendar reminder won't fix this. A reminder is a cron job. What she was missing was everything around the date.

So I built oss-reminder.

What I built

oss-reminder reads the official pages of open-source programs and sends push notifications to her phone:

An oss-reminder push notification displaying GSoC eligibility criteria, listing requirements to apply and disqualifications such as residing in an embargoed country.

An oss-reminder push notification showing GSoC disqualifiers continued, along with a prompt to open the full message in the ntfy app.

An oss-reminder push notification showing typical GSoC timeline dates from February through May, with a link to the official source page.

  • A summary: the open dates, who can apply, who can't, and what to prepare (documents, essays, limits).
  • Countdown reminders: 7 days and 1 day before each date, at a time of day she chooses. I set hers to 5:30 PM, inside the 5 to 7 PM window when she checks her phone.
  • A source on every message: the date I read the page, and a button that opens the official page.

A local Gemma 3 4B model, running through Ollama, reads the pages. Plain Python does everything where a mistake could cost her a deadline.

Demo

Right now neither GSoC nor Outreachy has open application dates, so a real run correctly sends nothing. For the demo I pretended it was March 24, 2026, a week before the GSoC 2026 contributor deadline. The page says "March 31, 18:00 UTC", and the reminder shows it as 23:30 IST. The next day it sends the "tomorrow" one. Demo reminders are marked DEMO and only go to my own phone.

A demo notification titled

A demo notification titled

How it works

saved page text -> Gemma 3 4B (local) -> eligibility, disqualifiers, what to prepare
                         |
plain Python: dates, "is it in the future?", UTC to IST, month patterns, no duplicates
                         |
                   ntfy -> her phone
Enter fullscreen mode Exit fullscreen mode

The model only reads. Code decides what counts as an upcoming date, so the model can't invent a deadline that then triggers a reminder.

The model got things wrong. Here is what I measured

Small models are confident when they're wrong, so I compared every output with the official pages, line by line.

Check (against the official page) Result
GSoC dates, first version 14 of 18 right, 3 wrong, 1 missing
GSoC rules, first version 4 of 6 found
GSoC rules, after splitting "can apply" and "cannot apply" 9 of 10 found, none flipped
Outreachy rules (16 on the page) 11 right, 1 garbled, 4 missing, so they are hand-checked
Outreachy upcoming dates 4 of 4 right, read by plain code

My weekend, step by step

Every version is in the repo's NOTES.md and in the commit history.

Friday: the idea. The AI had to do something a scheduler couldn't, and reading messy pages was that job.

Saturday: Gemma on my laptop. I installed Ollama, pulled gemma3:4b (3.3 GB), saved the GSoC pages as text and wrote the extractor.

  • v1, one prompt for everything: the wrong dates were all near the end of the list. It also ignored my "only future dates" rule: 16 of the 18 dates were already past.
  • v2 to v4: one job per prompt, and "is it in the future?" moved to plain code. In v3 the model flipped a rule. The page says you can't apply if you've done GSoC two or more times, and it wrote that as a requirement. In v4 I asked for two separate lists, "you can apply if" and "you cannot apply if".
  • 7:58 PM: the first notification buzzed my phone.
  • Reading it on the phone changed things. Android cut the message off, so I moved "To apply" to the top. I strip "(...)" asides with code instead of cutting at a length, because a cut could remove "two or more times" and flip the rule again.
  • v5, a prompt change that backfired: I asked the model for full sentences, and it found fewer rules (7 of 10). I went back to v4 and let code fix the grammar.

Sunday: Outreachy, and where I almost fooled myself.

  • I edited the shared prompt for Outreachy, and GSoC quietly went from finding 9 dates to 0. The output still looked right, because a program with no open dates is supposed to show nothing. I only caught it by comparing against the output I'd saved. Now each program has its own rules, and code counts the date lines on a page and warns if the model finds far fewer.
  • Outreachy's timeline is a clean table, so plain code reads it. No model needed.
  • I tried splitting the Outreachy rules into smaller chunks, and it got worse. In one run the model said "you cannot apply if you are not a student". The page says the opposite: non-students are welcome and can apply to either round.
  • So Outreachy's rules are checked by hand. I drafted them from the official pages with Claude's help and checked every line myself, and the message says "Rules checked by hand". The raw model output stays in the repo so the numbers stay honest.
  • The phone again: the long Outreachy message was cut off in the app, right in the middle of the cohort rules, which are the lines my friend needs most. Messages are now packed into pieces under 900 bytes.

An oss-reminder notification displaying hand-checked Outreachy eligibility rules for non-students and university students by hemisphere, followed by a status update that the current round is closed.

  • The scheduler: one run a day at 5:30 PM IST, reminders at 7 days and 1 day, a file that stops duplicates, and a catch-up if the laptop was off on day 7.

Why open mattered

Here is where being open helped this project:

  • It runs on my laptop and costs nothing. No API key, no per-call fee, for a tool that has to keep working for months.
  • The page text stays on my machine. Only the notification text goes out, through ntfy, which is open source and can be self-hosted.
  • It's repeatable. At temperature 0 the same page gives the same answer. That let me save every version's output and compare them line by line, which is how I caught a bug that looked like success.
  • I can change it. The model is one line in the code. Adding a program is one new text file.

Challenge submission

Best Use of Gemma. Gemma 3 4B runs locally through Ollama and does the reading, and the whole pipeline is built around where it fails.

Try it

git clone https://github.com/meenanoolu/oss-reminder
cd oss-reminder
pip install -r requirements.txt
ollama pull gemma3:4b
copy config.example.json config.json
python remind.py --today 2026-03-24 --dry-run
Enter fullscreen mode Exit fullscreen mode

(copy is Windows. On Mac or Linux use cp.) The README explains how to save the program pages and send reminders to your own phone.

Code: oss-reminder on GitHub (MIT)

What it can't do yet

  • Only GSoC and Outreachy so far. Other programs can be added as new page sources.
  • Dates change only when I refresh the saved pages by hand, so a "dates changed" alert is next.
  • The laptop must be on at reminder time. Hosting it somewhere always on is the real fix.
  • No "how to get started" steps yet, only dates, eligibility and what to prepare.
  • Rules change every season, so every message tells her to check the official page.

What I took away

The question I kept asking wasn't "does the model score well". It was "will she trust a wrong answer and miss her chance?" That question is why the model only reads, why code decides the dates, and why a person checks the rules.

Top comments (0)