<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: TaseenTariq</title>
    <description>The latest articles on DEV Community by TaseenTariq (@taseen_tariq_).</description>
    <link>https://dev.to/taseen_tariq_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F702231%2F8cdee4a5-3ff4-426f-809e-4c275a855c29.png</url>
      <title>DEV Community: TaseenTariq</title>
      <link>https://dev.to/taseen_tariq_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/taseen_tariq_"/>
    <language>en</language>
    <item>
      <title>I built a Gemma 4 medicine reminder in 100 minutes at a hackathon</title>
      <dc:creator>TaseenTariq</dc:creator>
      <pubDate>Tue, 27 Oct 2026 19:31:06 +0000</pubDate>
      <link>https://dev.to/taseen_tariq_/i-built-a-gemma-4-medicine-reminder-in-100-minutes-at-a-hackathon-2kf2</link>
      <guid>https://dev.to/taseen_tariq_/i-built-a-gemma-4-medicine-reminder-in-100-minutes-at-a-hackathon-2kf2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/mlh-hackathon"&gt;MLH x DEV Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anatono&lt;/strong&gt; is a medicine reminder that starts from a photo. Snap a medicine strip, a box, or a whole handwritten&lt;br&gt;
prescription. Type or say how you take it, in English, Urdu or Roman Urdu. Anatono turns that into reminders, and it&lt;br&gt;
checks every medicine for warning signs before you take it. It's made for elders and the people who look after them.&lt;/p&gt;

&lt;p&gt;I built it at MLH's &lt;strong&gt;Hacktoberfest Hack Day in Faisalabad on 23 October 2026&lt;/strong&gt;. It's live at&lt;br&gt;
&lt;a href="https://anatono.site" rel="noopener noreferrer"&gt;anatono.site&lt;/a&gt;, and the code is open source (MIT).&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/taseen-t" rel="noopener noreferrer"&gt;
        taseen-t
      &lt;/a&gt; / &lt;a href="https://github.com/taseen-t/anatono-meds" rel="noopener noreferrer"&gt;
        anatono-meds
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Anatono: snap a medicine or prescription, Gemma 4 reads and checks it, say how you take it, get reminders. Hack Day Faisalabad 2026.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Anatono&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Never miss a dose again.&lt;/strong&gt; Snap a medicine strip, a box or a whole handwritten prescription. Say or type how you
take it, in English, Urdu or Roman Urdu. Anatono turns it into reminders, and checks every medicine for warning signs
before you take it. Made for elders and the people who look after them.&lt;/p&gt;
&lt;p&gt;Made by &lt;strong&gt;Taseen Tariq&lt;/strong&gt; at Hack Day Faisalabad, 23 October 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://anatono.site" rel="nofollow noopener noreferrer"&gt;anatono.site&lt;/a&gt; (landing page) · &lt;a href="https://anatono.site/app.html" rel="nofollow noopener noreferrer"&gt;anatono.site/app.html&lt;/a&gt;
(the app) · &lt;a href="https://anatono.site/anatono.apk" rel="nofollow noopener noreferrer"&gt;Android app (APK)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://anatono.site/demo.mp4" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftaseen-t%2Fanatono-meds%2FHEAD%2Fdemo.gif" alt="Anatono in 30 seconds: a real run of the app"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;▶ &lt;a href="https://anatono.site/demo.mp4" rel="nofollow noopener noreferrer"&gt;Watch the 30-second demo&lt;/a&gt;&lt;/strong&gt;: a real run of the app (Gemma 4's waits shown sped up), with captions.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verify in 30 seconds&lt;/strong&gt;&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Gemma 4&lt;/strong&gt; (&lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt;; &lt;code&gt;gemma-4-31b-it&lt;/code&gt; only as a fallback) through the &lt;strong&gt;Gemini API&lt;/strong&gt; (&lt;code&gt;google-genai&lt;/code&gt;). Licence: &lt;a href="https://ai.google.dev/gemma/apache_2" rel="nofollow noopener noreferrer"&gt;Apache 2.0&lt;/a&gt;. &lt;a href="https://github.com/taseen-t/anatono-meds/anatono.py#L24" rel="noopener noreferrer"&gt;&lt;code&gt;anatono.py&lt;/code&gt; line 24&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Where Gemma is called&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ask()&lt;/code&gt; in &lt;a href="https://github.com/taseen-t/anatono-meds/anatono.py#L69" rel="noopener noreferrer"&gt;&lt;code&gt;anatono.py&lt;/code&gt; line 69&lt;/a&gt; → &lt;code&gt;ask_gemma()&lt;/code&gt; (&lt;a href="https://github.com/taseen-t/anatono-meds/anatono.py#L85" rel="noopener noreferrer"&gt;line 85&lt;/a&gt;). It reads every photo (&lt;code&gt;read_photo&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/blockquote&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/taseen-t/anatono-meds" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Why medicines
&lt;/h3&gt;

&lt;p&gt;My sister is a doctor. With a doctor in the family, I learned that writing the prescription is the&lt;br&gt;
easy part. The hard part happens at home: the right medicine, at the right time, every day, with no doctor in the room.&lt;/p&gt;

&lt;p&gt;This is the kind of paper that goes home. It's a sample I made for the demo, not a real patient:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ip6ilzjustpo7rqsgr6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ip6ilzjustpo7rqsgr6.jpg" alt="A sample handwritten prescription: Amoxil 500mg 1+0+1 for 5 days after meals, Omez 20mg 1+0+0 before breakfast for 14 days, Brufen syrup 2 tsp TDS if fever" width="800" height="1018"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three medicines, three schedules, all in shorthand: &lt;code&gt;1+0+1&lt;/code&gt;, &lt;code&gt;TDS&lt;/code&gt;, &lt;code&gt;x 14 days&lt;/code&gt;. Easy for a doctor, hard for a&lt;br&gt;
patient. Then you're supposed to type it all into a reminder app yourself, in English. That's where people give up.&lt;/p&gt;

&lt;p&gt;And it isn't just one family. The WHO says about &lt;strong&gt;1 in 2&lt;/strong&gt; people on long-term medicines don't take them as&lt;br&gt;
prescribed (&lt;a href="https://iris.who.int/handle/10665/42682" rel="noopener noreferrer"&gt;Adherence to Long-Term Therapies, 2003&lt;/a&gt;), and &lt;strong&gt;1 in 10&lt;/strong&gt;&lt;br&gt;
medical products in low- and middle-income countries is substandard or falsified&lt;br&gt;
(&lt;a href="https://www.who.int/news/item/28-11-2017-1-in-10-medical-products-in-developing-countries-is-substandard-or-falsified" rel="noopener noreferrer"&gt;WHO, 2017&lt;/a&gt;).&lt;br&gt;
So Anatono does two things: it reminds you, and it checks the medicine.&lt;/p&gt;
&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read.&lt;/strong&gt; Gemma 4 reads the photo: name, salt, strength, maker, batch number, dates, registration number, and the
dose as the doctor wrote it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check.&lt;/strong&gt; Plain code, not the model, decides whether each medicine is &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;careful&lt;/code&gt; or &lt;code&gt;stop&lt;/code&gt;. An expired
medicine gets no reminders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand the dose.&lt;/strong&gt; Type or say it any way you like. "ek goli subah aur raat khane ke baad paanch din" (one
tablet morning and night, after food, five days) becomes 1 tablet at 8:00 AM and 9:00 PM, after food, for 5 days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirm and remind.&lt;/strong&gt; Nothing is saved until you tap "Add to my routine". Reminders show in the app and go into
your phone's own calendar as alarms, so they ring even when the app is closed.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  The one rule: Gemma 4 reads, code decides
&lt;/h3&gt;

&lt;p&gt;The model is good at reading messy handwriting and messy sentences. It shouldn't be the one deciding whether you take a&lt;br&gt;
pill. So Gemma 4 only turns a photo or a sentence into JSON, and plain Python makes every decision after that.&lt;/p&gt;

&lt;p&gt;Each medicine collects flags: expired (stop), expiring soon, a made-on date after the expiry date, a missing batch&lt;br&gt;
number, expiry, maker or registration number ("Genuine packs print it."), the same ingredient as something already in&lt;br&gt;
your routine, or a warning sign Gemma spotted on the pack. Then one line decides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;careful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;careful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;stop&lt;/code&gt; card says "Don't take this one. Show it to your pharmacist." and has no dose form at all.&lt;/p&gt;

&lt;p&gt;Doses work the same way. Gemma 4 turns your words into &lt;code&gt;amount&lt;/code&gt;, &lt;code&gt;times&lt;/code&gt; ("morning", "night"…), &lt;code&gt;food&lt;/code&gt;, &lt;code&gt;days&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;as_needed&lt;/code&gt; and anything it was &lt;code&gt;unclear&lt;/code&gt; about. Code turns that into clock times (morning 8:00, afternoon 2:00 PM,&lt;br&gt;
evening 6:00 PM, night 9:00 PM), only accepts 1 to 365 days, flags more than 6 doses a day, and reads prescription&lt;br&gt;
shorthand on its own so it can check Gemma's answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pattern_slots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""'&lt;/span&gt;&lt;span class="s"&gt;1+0+1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; / &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1-1-1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; / &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0+0+1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; the slots it means, or None. Code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s own reading, to cross-check Gemma.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?&amp;lt;![\d/])([\d½]+)\s*[+\-]\s*([\d½]+)\s*[+\-]\s*([\d½]+)(?:\s*[+\-]\s*([\d½]+))?(?![\d/])&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;morning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;afternoon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;night&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;morning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;afternoon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evening&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;night&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Gemma's times don't match, you see a note like "'1+0+1' usually means morning and night. Please check the times."&lt;br&gt;
You always see what was understood and can change the times before anything is saved. Anatono never changes a dose.&lt;/p&gt;

&lt;p&gt;There's also an &lt;strong&gt;agent skill&lt;/strong&gt;, &lt;a href="https://github.com/taseen-t/anatono-meds/tree/main/skills/anatono-nuskha" rel="noopener noreferrer"&gt;&lt;code&gt;anatono-nuskha&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
("nuskha" is Urdu for prescription), built to the Agent Skills open standard. Any skills-compatible agent can run the&lt;br&gt;
same pipeline from the command line: photo in, checks and a calendar file out. Its rules tell the agent to read the&lt;br&gt;
flags back and get a yes before saving, to never change or round a dose, and to say "warning signs", never "fake".&lt;/p&gt;
&lt;h3&gt;
  
  
  What I learned
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Put the safety rules in code, not in the prompt.&lt;/strong&gt; Then the model can't talk its way around them, and I can test
them. &lt;code&gt;python3 anatono.py&lt;/code&gt; runs a self-check of the rules with no API call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design around a slow model.&lt;/strong&gt; On the night, one read of the sample prescription took about a minute and another
took three. More on what I did about it under Partner Technologies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be honest about limits.&lt;/strong&gt; A photo can't prove a medicine is genuine. So Anatono only ever says "warning signs",
the FAQ says why, and the README has a "Limits, honestly" section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dropping an idea late can be the right call.&lt;/strong&gt; The organisers' guide said to stop adding features 90 minutes
before the deadline. I started a whole new project with 100 minutes left. It worked out because I picked a problem I
already knew from home.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A small one from the last minutes.&lt;/strong&gt; Two minutes before the deadline, the calendar buttons were showing on an empty
routine even though they had the &lt;code&gt;hidden&lt;/code&gt; attribute. A &lt;code&gt;.stack { display: grid }&lt;/code&gt; rule was beating &lt;code&gt;hidden&lt;/code&gt;. One line
fixed it: &lt;code&gt;[hidden] { display: none !important; }&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/28Ysk18Aheg" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;A one-minute run of the web app. Gemma 4 reads the prescription (Amoxil 500mg and Omez 20mg, both OK), understands&lt;br&gt;
"ek goli subah aur raat, khane ke baad, 5 din" as 8:00 AM and 9:00 PM for 5 days, and plain code stops an expired&lt;br&gt;
pack. The app has changed a little since this was recorded, and the live app now runs on Gemma 4 only.&lt;/p&gt;

&lt;p&gt;Try it yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The app:&lt;/strong&gt; &lt;a href="https://anatono.site/app.html" rel="noopener noreferrer"&gt;anatono.site/app.html&lt;/a&gt;. Tap &lt;strong&gt;Try a sample&lt;/strong&gt; to read the prescription
above. Reading can take a minute or more (see below). Works in any phone browser and installs as an app on Android.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The landing page:&lt;/strong&gt; &lt;a href="https://anatono.site" rel="noopener noreferrer"&gt;anatono.site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Android:&lt;/strong&gt; &lt;a href="https://anatono.site/anatono.apk" rel="noopener noreferrer"&gt;anatono.apk&lt;/a&gt;, the same web app wrapped to open full screen like any
app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The code:&lt;/strong&gt; &lt;a href="https://github.com/taseen-t/anatono-meds" rel="noopener noreferrer"&gt;github.com/taseen-t/anatono-meds&lt;/a&gt;, MIT. The README has a
"Verify in 30 seconds" box with the model, the exact lines that call it, the licence and the key dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Partner Technologies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Gemma 4, through the Gemini API.&lt;/strong&gt; Gemma 4 is the centre of Anatono: it reads every photo and understands every&lt;br&gt;
dose. I use &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; through the &lt;code&gt;google-genai&lt;/code&gt; Python SDK, with &lt;code&gt;gemma-4-31b-it&lt;/code&gt; only as a fallback. Both&lt;br&gt;
are Gemma 4, under the &lt;a href="https://ai.google.dev/gemma/apache_2" rel="noopener noreferrer"&gt;Apache 2.0&lt;/a&gt; licence. The key stays on the server, so the&lt;br&gt;
browser never sees it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What working with it was like:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It sometimes answers with a 500, or with JSON wrapped in extra text.&lt;/strong&gt; So every call pulls the JSON object out of
the reply, and if anything fails it tries the 26B model twice, then the 31B one:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ask_gemma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Gemma 4 through the Gemini API. It sometimes answers 500 or loose JSON: try the 26B model twice, then the 31B
      one (both Gemma 4).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                       &lt;span class="c1"&gt;# keep a reference: a dropped client closes its connection
&lt;/span&gt;      &lt;span class="n"&gt;tries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MODEL_BACKUP&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tries&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
          &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;as_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# noqa: BLE001
&lt;/span&gt;              &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                  &lt;span class="k"&gt;raise&lt;/span&gt;
              &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 on the API doesn't take audio.&lt;/strong&gt; So when you tap the mic, &lt;code&gt;gemini-3.5-flash-lite&lt;/code&gt; only writes down the
words you said, and Gemma 4 does all the understanding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other surprises:&lt;/strong&gt; asking for a thinking level gave a 400, and &lt;code&gt;gemma-4-e4b-it&lt;/code&gt; gave a 404 on the API, so I stuck
with the 26B model.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The hosted model can be slow.&lt;/strong&gt; On the night, the sample prescription took anywhere from about a minute to three.&lt;br&gt;
At a live demo that's a long time. After the deadline I made three changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ask less first.&lt;/strong&gt; The first call only reads the medicines. "What is it for", in English and Urdu, comes from a
second, shorter call that fills in after the cards are already on screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read a tall page in two parts.&lt;/strong&gt; A full prescription is cut into two overlapping halves. The app reads part 1,
shows those medicines, and offers "Read the remaining medicines". A medicine that shows up in both halves is kept
once (matched by name and strength).
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pieces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
     &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;A tall page (a full prescription) is cut into two overlapping halves, because Gemma 4 on the API is slow and
     two short answers come back sooner than one long one. The overlap keeps a line cut in half readable in one piece.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
     &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read once, not twice&lt;/strong&gt; (the next day). The phone and the server both keep what was read, keyed by a SHA-256 of
 the photo. On a repeat only the code checks run again, because they depend on today's date and on what's already
 in your routine.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Hackathon Experience
&lt;/h2&gt;

&lt;p&gt;I went to MLH's &lt;strong&gt;Hacktoberfest Hack Day in Faisalabad&lt;/strong&gt; on 23 October 2026.&lt;/p&gt;

&lt;p&gt;The organisers sent a "before you arrive" list: accounts on GitHub, DEV and Google, a Gemini API key from Google AI&lt;br&gt;
Studio, and one line: "Do this at home, not on venue Wi-Fi." The rule was that setup before the day is fine,&lt;br&gt;
but project code isn't. So I came with a ready laptop and no code.&lt;/p&gt;

&lt;p&gt;Honestly, I started with a different idea. In the afternoon I built a karaoke vocal coach and called it Anatono: it&lt;br&gt;
split a song into music and voice, showed the lyrics in time with the song, and Gemma 4 gave you a score and tips on&lt;br&gt;
your singing. It worked, but I didn't like it. At 7:20 PM, with 100 minutes to go, I dropped it. I kept the name and&lt;br&gt;
picked the problem I already knew from home.&lt;/p&gt;

&lt;p&gt;The new project's first commit went in at 8:21 PM. The repo went public on GitHub at 8:50 PM, and at 8:52 PM Gemma 4&lt;br&gt;
was answering on anatono.site, a domain I'd bought that same day.&lt;/p&gt;

&lt;h3&gt;
  
  
  Since the deadline
&lt;/h3&gt;

&lt;p&gt;I kept building overnight. All of these use the same Gemma 4 reading and the same code checks behind anatono.site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scroll and page-change animations on the landing page&lt;/li&gt;
&lt;li&gt;the Android download, which opens full screen with no browser bar&lt;/li&gt;
&lt;li&gt;a native iPhone app (SwiftUI, with real iOS reminders that ring with the app closed), running in the simulator&lt;/li&gt;
&lt;li&gt;a native Android app (Kotlin, reminders in the phone's calendar, Urdu in Nastaliq script), in testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 on the phone&lt;/strong&gt;, so it reads offline in seconds instead of waiting on the hosted model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Family mode&lt;/strong&gt;: remind a parent's phone from yours, and see when a dose is taken.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Doctors first&lt;/strong&gt;: put it in front of the people who write these prescriptions, starting with my sister.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the limits, honestly: a photo can't prove a medicine is genuine, so Anatono only shows warning signs. It's a&lt;br&gt;
reminder, not medical advice, and it never changes a dose. Photos are sent to Google's Gemini API to be read; your&lt;br&gt;
routine stays on your phone.&lt;/p&gt;

&lt;p&gt;Thanks to MLH and the Faisalabad organisers for the day.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An AI assistant wrote this post from my build notes and the repo's history.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mlhacks</category>
      <category>devchallenge</category>
      <category>hackathon</category>
      <category>gemma</category>
    </item>
  </channel>
</rss>
