<?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: Rafi Bagaskara Halilintar</title>
    <description>The latest articles on DEV Community by Rafi Bagaskara Halilintar (@masitings).</description>
    <link>https://dev.to/masitings</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%2F355442%2F84af0b9d-2cc7-4f18-8712-3be8a9e0e873.png</url>
      <title>DEV Community: Rafi Bagaskara Halilintar</title>
      <link>https://dev.to/masitings</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masitings"/>
    <language>en</language>
    <item>
      <title>Alright my first weekly challenge on Hacktoberfest!</title>
      <dc:creator>Rafi Bagaskara Halilintar</dc:creator>
      <pubDate>Fri, 02 Oct 2026 20:20:47 +0000</pubDate>
      <link>https://dev.to/masitings/alright-my-first-weekly-challenge-on-hacktoberfest-n2c</link>
      <guid>https://dev.to/masitings/alright-my-first-weekly-challenge-on-hacktoberfest-n2c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/masitings/kas-rumah-a-receipt-reading-expense-tracker-for-my-wife-that-never-leaves-our-laptop-28jo" class="crayons-story__hidden-navigation-link"&gt;Kas Rumah: a receipt-reading expense tracker for my wife that never leaves our laptop&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/masitings" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F355442%2F84af0b9d-2cc7-4f18-8712-3be8a9e0e873.png" alt="masitings profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/masitings" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Rafi Bagaskara Halilintar
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Rafi Bagaskara Halilintar
                
                
              
              &lt;div id="story-author-preview-content-4788965" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/masitings" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F355442%2F84af0b9d-2cc7-4f18-8712-3be8a9e0e873.png" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Rafi Bagaskara Halilintar&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/masitings/kas-rumah-a-receipt-reading-expense-tracker-for-my-wife-that-never-leaves-our-laptop-28jo" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 2&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/masitings/kas-rumah-a-receipt-reading-expense-tracker-for-my-wife-that-never-leaves-our-laptop-28jo" id="article-link-4788965"&gt;
          Kas Rumah: a receipt-reading expense tracker for my wife that never leaves our laptop
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/weekendchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;weekendchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hf26challenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hf26challenge&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/masitings/kas-rumah-a-receipt-reading-expense-tracker-for-my-wife-that-never-leaves-our-laptop-28jo#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>devchallenge</category>
      <category>opensource</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Kas Rumah: a receipt-reading expense tracker for my wife that never leaves our laptop</title>
      <dc:creator>Rafi Bagaskara Halilintar</dc:creator>
      <pubDate>Fri, 02 Oct 2026 20:13:35 +0000</pubDate>
      <link>https://dev.to/masitings/kas-rumah-a-receipt-reading-expense-tracker-for-my-wife-that-never-leaves-our-laptop-28jo</link>
      <guid>https://dev.to/masitings/kas-rumah-a-receipt-reading-expense-tracker-for-my-wife-that-never-leaves-our-laptop-28jo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;My wife runs our household money. Groceries, the electricity bill, gas refills, the occasional ShopeeFood order, envelopes for weddings. She has tried expense apps before and every one of them died the same way: typing each purchase by hand is tedious, so after a week the app gets ignored and the receipts pile up in her bag.&lt;/p&gt;

&lt;p&gt;Kas Rumah ("house cash" in Indonesian) removes the typing. She can take a photo of a receipt, upload a bank transfer screenshot, or type something like &lt;code&gt;beli sayur 45rb sama galon 20rb&lt;/code&gt; ("bought vegetables 45k and a water gallon 20k"). A local Gemma model turns it into categorized expenses, she checks them on a review screen, and once a week she gets a short summary in casual Indonesian telling her where the money went and which budget is running hot.&lt;/p&gt;

&lt;p&gt;Everything runs on our laptop at home. Her phone talks to it over our Wi-Fi.&lt;/p&gt;

&lt;p&gt;To be upfront: she hasn't used it yet. I built it over this weekend, and everything in this post was tested with sample receipts and screenshots, not ours. Handing it to her is the next step, and her first week with it will tell me more than any test set did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&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%2Fticanh509mkp3qugdui9.png" 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%2Fticanh509mkp3qugdui9.png" alt="Expenses screen for October showing a monthly total of Rp1,094,856, a per-category breakdown, and five receipts saved on 3 October" width="800" height="1738"&gt;&lt;/a&gt;&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%2F577os9c5segdsls3wxbm.png" 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%2F577os9c5segdsls3wxbm.png" alt="Review screen with a clinic receipt read as Rp765,000 under Health, with editable date, merchant, category and notes" width="800" height="1738"&gt;&lt;/a&gt;&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%2Fqhp9mxl5yj14hcgzpmge.png" 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%2Fqhp9mxl5yj14hcgzpmge.png" alt="Weekly summary screen with a short paragraph written by Gemma, the week's total, and this week compared to the 4-week average" width="800" height="1738"&gt;&lt;/a&gt;&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%2Fc9fbdvh8ji8gdg9buyvv.png" 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%2Fc9fbdvh8ji8gdg9buyvv.png" alt="Review screen with an Indomaret receipt that has a voucher, a cancelled item and a discount, read correctly as Rp183,200" width="800" height="1738"&gt;&lt;/a&gt;&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%2F1merwvy8w46kbr9z3ktj.png" 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%2F1merwvy8w46kbr9z3ktj.png" alt="Expenses screen earlier in the day with three saved receipts totalling Rp146,656" width="800" height="1738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&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/masitings" rel="noopener noreferrer"&gt;
        masitings
      &lt;/a&gt; / &lt;a href="https://github.com/masitings/kasrumah" rel="noopener noreferrer"&gt;
        kasrumah
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Kas Rumah — household expense tracker. Local Gemma 3 (Ollama) reads receipts / transfer screenshots / typed notes. Laravel 13 + Inertia + React, 100% offline AI.
    &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;Kas Rumah&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A household expense tracker for a spouse managing the family's budget. Snap a photo of a receipt or bank transfer screenshot, or type a casual note like "beli sayur 45rb" — a &lt;strong&gt;local Gemma 3 model via Ollama&lt;/strong&gt; parses it into a categorized expense. Nothing ever leaves this laptop: zero cloud AI, zero third-party expense APIs.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Stack&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Laravel 13 + Inertia (React, TypeScript) with the official starter kit&lt;/li&gt;
&lt;li&gt;SQLite or MySQL database&lt;/li&gt;
&lt;li&gt;Ollama running &lt;code&gt;gemma3:4b&lt;/code&gt; (vision-capable) at &lt;code&gt;http://127.0.0.1:11434&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Money is stored as &lt;strong&gt;integer rupiah&lt;/strong&gt; (no decimals)&lt;/li&gt;
&lt;li&gt;UI copy is casual Indonesian; code, comments, and commit messages are English&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;One-time Setup&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;composer install
npm install
cp .env.example .env
php artisan key:generate
php artisan migrate&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Make sure Ollama is installed and the model is downloaded:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;ollama pull gemma3:4b   &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; ~3.3 GB&lt;/span&gt;
ollama serve&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Optional overrides in &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-dotenv notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-v"&gt;OLLAMA_URL&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;http://127.0.0.1:11434&lt;/span&gt;
&lt;span class="pl-v"&gt;OLLAMA_MODEL&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-s"&gt;gemma3:4b&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Development&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;composer run dev   &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; sail-style:&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/masitings/kasrumah" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; Laravel with the React starter kit (Inertia), MySQL, and &lt;a href="https://deepmind.google/models/gemma/" rel="noopener noreferrer"&gt;Gemma 3 4B&lt;/a&gt; running through &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; on an M5 MacBook with 16 GB of RAM.&lt;/p&gt;

&lt;p&gt;The app has five screens: Catat (record), Review, Pengeluaran (expenses), Ringkasan (summary), and Budget. The interesting part is how little I ask the model to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading receipts
&lt;/h3&gt;

&lt;p&gt;One &lt;code&gt;ExpenseExtractor&lt;/code&gt; service sends either an image or a line of text to Ollama's &lt;code&gt;/api/chat&lt;/code&gt;. Two things made the 4B model usable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Structured outputs.&lt;/strong&gt; Instead of asking nicely for JSON, I pass a JSON schema in Ollama's &lt;code&gt;format&lt;/code&gt; field, with the category list as an &lt;code&gt;enum&lt;/code&gt;. The model cannot invent a category, and I never parse broken JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate prompts for images and text.&lt;/strong&gt; My first version used one prompt for both and said "one receipt is one expense, don't split items." That rule made the model return nothing for &lt;code&gt;sayur 45rb sama galon 20rb&lt;/code&gt;, because the text clearly has two expenses. Splitting the prompts fixed it. The image prompt also tells the model to ignore payment lines like TUNAI (cash), KEMBALI (change) and QRIS, because on the first run it logged the cash handed to the cashier as a second expense.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Images are downscaled to 1600px before they go to the model, which keeps each receipt at about 4 seconds.&lt;/p&gt;

&lt;p&gt;Nothing the model returns is saved directly. Every result lands on the Review screen as a draft, and rows with low confidence are highlighted. She fixes what is wrong and taps Simpan.&lt;/p&gt;

&lt;h3&gt;
  
  
  The weekly summary
&lt;/h3&gt;

&lt;p&gt;I don't let the model do math. PHP computes this week's total per category, the 4-week average, and budget usage, then hands Gemma those numbers with a prompt that says to use only them. Gemma's job is just to turn a small JSON object into three to five friendly sentences. A 4B model is good at that and bad at arithmetic, so that is the split.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice input and iPhone photos for free
&lt;/h3&gt;

&lt;p&gt;I planned to add Whisper for voice notes. Then I realized the iPhone keyboard already has a dictation button, so the text field is the voice input. Same story with HEIC photos: setting &lt;code&gt;accept="image/jpeg,image/png"&lt;/code&gt; on the file input makes iOS Safari convert to JPEG before upload, so the server never sees a HEIC file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where my AI coding agent cheated, and the honest numbers
&lt;/h3&gt;

&lt;p&gt;I used an AI coding agent for a lot of the build and gave it a regression test: three receipt photos and four text samples with known answers. It came back with 7/7 passing. Then I read the prompt. It had written the expected totals and store names from the test receipts straight into the instructions. The tests passed because the answers were in the question.&lt;/p&gt;

&lt;p&gt;I made it remove every value from the test set, split the fixtures into a tuning set and a holdout set it was only allowed to run once, and run every case three times. These are the real numbers for &lt;code&gt;gemma3:4b&lt;/code&gt; on that small set of sample receipts and screenshots:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Correct&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Amount (images)&lt;/td&gt;
&lt;td&gt;4 of 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Category (images)&lt;/td&gt;
&lt;td&gt;5 of 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Merchant name (images)&lt;/td&gt;
&lt;td&gt;2 of 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text input&lt;/td&gt;
&lt;td&gt;4 of 4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Amounts and categories, the fields that matter for a household budget, are solid. Merchant names are weak: it could not read a stylized store logo, and for a transfer screenshot it picked the payment app instead of the person receiving the money. One pharmacy receipt read 23,000 instead of 25,000, the same way every time. Those are all things the Review screen catches in a second, so I stopped tuning there instead of chasing a nicer number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;This app reads my family's receipts and bank transfer screenshots. Those show what we buy, where we shop, who we send money to, and sometimes account details. I was not willing to send that to a third-party API, and I don't think my wife would have agreed to use it if I had. With Gemma running locally, the photos and the numbers stay on a laptop in our house.&lt;/p&gt;

&lt;p&gt;It also costs nothing to run. A cloud vision API would be cheap per call, but it would still be a monthly bill for a tool whose whole point is helping us spend less.&lt;/p&gt;

&lt;p&gt;And because the model is open, I could pick the size that fits the job. A 4B model on a laptop is fast enough for a person waiting with their phone in hand, and the design (strict schema, PHP does the math, a human confirms) makes up for what a small model gets wrong. If it ever falls short, I can swap the model with one line in &lt;code&gt;.env&lt;/code&gt; without touching the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;Best Use of Gemma&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Adding server monitoring to my SSH manager without opening a second connection</title>
      <dc:creator>Rafi Bagaskara Halilintar</dc:creator>
      <pubDate>Mon, 29 Jun 2026 03:20:16 +0000</pubDate>
      <link>https://dev.to/masitings/adding-server-monitoring-to-my-ssh-manager-without-opening-a-second-connection-3gp2</link>
      <guid>https://dev.to/masitings/adding-server-monitoring-to-my-ssh-manager-without-opening-a-second-connection-3gp2</guid>
      <description>&lt;p&gt;I use my SSH manager every day. I also use a separate monitoring tool every day. For a long time I just accepted that these were two different things.&lt;/p&gt;

&lt;p&gt;Then one day I was SSH'd into a server that was behaving weird. I wanted to check if it was CPU or memory, but I had to open a different app, find the server in there, and wait for the dashboard to load. It took maybe 15 seconds. Not a huge deal. But it broke my flow every single time.&lt;/p&gt;

&lt;p&gt;I already had an SSH connection open to that server. Why was I opening a second thing just to see what was happening to it?&lt;br&gt;
That's what pushed me to build server monitoring directly into Termique, the SSH manager I've been working on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interesting part: reusing the existing SSH connection
&lt;/h2&gt;

&lt;p&gt;SSH connections aren't just for terminals. The protocol supports multiple channels over a single TCP connection. You can have a terminal session running in one channel while sending short exec commands through another channel on the same connection.&lt;/p&gt;

&lt;p&gt;That's how the monitoring feature works. When you open the metrics panel for a server, Termique creates a separate exec channel on the existing SSH connection and polls /proc/stat for CPU, /proc/meminfo for RAM, and /proc/loadavg for system load. Short-lived commands, called on an interval, over the connection you already have open.&lt;br&gt;
No second SSH handshake. No separate auth. Just another channel on the same pipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tradeoff: you do need an agent
&lt;/h2&gt;

&lt;p&gt;I want to be upfront about this. The monitoring feature requires a small agent installed on each server. It's not agentless.&lt;/p&gt;

&lt;p&gt;I considered going agentless, relying entirely on /proc reads through exec channels. That works fine on most Linux servers. But the agent makes it easier to handle edge cases properly and opens the door for future features like alerts and longer history retention. Without it, I'd be fighting a lot of fragile shell parsing.&lt;/p&gt;

&lt;p&gt;If you're managing Linux servers, it's a one-command install. Non-Linux systems aren't supported yet. That's a real limitation and something I'm still working through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it fits
&lt;/h2&gt;

&lt;p&gt;The goal isn't to replace something like Netdata or Grafana. Those are great for what they do. The monitoring in Termique is specifically for the moment you're already in your terminal and just want to know if the server is struggling. CPU, RAM, disk. At a glance. Without switching apps.&lt;/p&gt;

&lt;p&gt;It's a consolidation thing, not a monitoring platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;p&gt;The feature is still in development. I'm targeting a release in the next Termique update. If you want to try it when it's out, or just poke around the existing SSH manager in the meantime, it's at termique.app. Free tier available, Pro is $5/month.&lt;/p&gt;

&lt;p&gt;If you've built something similar or have opinions on how you handle server monitoring in your day-to-day, I'd love to hear it in the comments.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ssh</category>
      <category>devops</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Submitting to App Store and Play Store as a solo developer - what actually happened</title>
      <dc:creator>Rafi Bagaskara Halilintar</dc:creator>
      <pubDate>Sat, 06 Jun 2026 11:14:04 +0000</pubDate>
      <link>https://dev.to/masitings/submitting-to-app-store-and-play-store-as-a-solo-developer-what-actually-happened-5g68</link>
      <guid>https://dev.to/masitings/submitting-to-app-store-and-play-store-as-a-solo-developer-what-actually-happened-5g68</guid>
      <description>&lt;p&gt;I submitted Termique to the App Store and Play Store three days ago. It's live now. Here's what the process actually looked like, because most guides make it sound cleaner than it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part nobody talks about - the assets
&lt;/h2&gt;

&lt;p&gt;Before you even think about submitting, you need screenshots. Not just any screenshots, specific sizes for specific devices. App Store wants iPhone screenshots, iPad screenshots, and if you support Mac, Mac screenshots too.&lt;/p&gt;

&lt;p&gt;The iPad one caught me off guard. Termique is an iPhone app. I don't have an iPad. But Apple requires iPad screenshots anyway. So I ran the simulator, took the screenshots, and moved on. It's annoying but it takes maybe 30 minutes once you know it's coming.&lt;/p&gt;

&lt;p&gt;For the actual design I used Figma templates from the community, there are free ones that handle all the sizing automatically. That part wasn't bad. The bad part was not knowing I needed it until I was already mid-submission.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rejection
&lt;/h2&gt;

&lt;p&gt;I got rejected. It happens. The reasons were straightforward, a missing screenshot size and something about content rights information that I hadn't filled in. Both fixable in under an hour.&lt;/p&gt;

&lt;p&gt;The thing about App Store rejection is it's not as dramatic as it sounds. They tell you exactly what's wrong. You fix it. You resubmit. That's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three days from submission to live
&lt;/h2&gt;

&lt;p&gt;I submitted on day one. Got feedback the same day. Fixed everything, resubmitted on day two. Approved and live on day three.&lt;/p&gt;

&lt;p&gt;I was expecting weeks. I got three days. That was the biggest surprise of the whole process.&lt;/p&gt;

&lt;p&gt;Play Store was similar, faster review, slightly different requirements, but nothing that required starting over.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell myself before starting
&lt;/h2&gt;

&lt;p&gt;Make sure your legal pages are ready before you submit. Privacy policy, terms of use, all of it. Both stores will ask for links during submission and you can't just skip them. Having those ready saved me a round trip.&lt;/p&gt;

&lt;p&gt;The other thing, your app doesn't have to be perfect. It has to work. There's a difference. Some things weren't fully polished when I submitted Termique. But nothing was broken in a way users would notice. That's the bar. Don't wait for perfect, you'll never ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual hard part
&lt;/h2&gt;

&lt;p&gt;Honestly the submission process itself wasn't the hard part. The hard part was building something worth submitting in the first place.&lt;/p&gt;

&lt;p&gt;Termique is available on the App Store and Play Store now. If you manage servers and want an SSH manager that actually syncs across all your devices, give it a try.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://termique.app" rel="noopener noreferrer"&gt;termique.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>mobile</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Why I chose Tauri over Electron for my SSH manager</title>
      <dc:creator>Rafi Bagaskara Halilintar</dc:creator>
      <pubDate>Wed, 03 Jun 2026 11:33:54 +0000</pubDate>
      <link>https://dev.to/masitings/why-i-chose-tauri-over-electron-for-my-ssh-manager-a4a</link>
      <guid>https://dev.to/masitings/why-i-chose-tauri-over-electron-for-my-ssh-manager-a4a</guid>
      <description>&lt;p&gt;When I started building Termique, I knew one thing for sure: it had to feel fast.&lt;/p&gt;

&lt;p&gt;An SSH manager is a tool you open constantly. You switch between servers, you check logs, you run commands. The last thing you want is to wait for your app to load. So when I started evaluating my options for building a cross-platform desktop app, Electron was the obvious first choice, but it didn't take long for me to realize it wasn't the right one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Electron problem
&lt;/h2&gt;

&lt;p&gt;Electron is everywhere. VS Code, Slack, Discord, all built on Electron. And for good reason: it's mature, well-documented, and lets you build desktop apps with web technologies.&lt;/p&gt;

&lt;p&gt;But the tradeoff is real. Electron ships with its own copy of Chromium and Node.js. Every Electron app is essentially a browser running your app inside it. The result? My early build was hitting around 100MB just for the installer. For an SSH manager, that felt absurd.&lt;/p&gt;

&lt;p&gt;And it wasn't just the bundle size. The app felt heavy. Not broken, not unusable, just heavy. That sluggish feeling every time you open it, that half-second delay before things respond. For a tool you open dozens of times a day, that adds up fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering Tauri
&lt;/h2&gt;

&lt;p&gt;Tauri takes a different approach entirely. Instead of bundling its own browser engine, it uses the OS's native webview, WebKit on macOS, WebView2 on Windows, WebKitGTK on Linux. The result is dramatically smaller bundle sizes and native performance.&lt;/p&gt;

&lt;p&gt;When I switched Termique to Tauri, the Windows installer went from ~100MB down to 12MB. That's not a small improvement, that's a completely different category of app.&lt;/p&gt;

&lt;p&gt;But what surprised me more was the performance difference. Tauri just feels fast in a way that's hard to explain. Snappier startup, smoother interactions. I'm not sure exactly what's happening under the hood, but the difference is noticeable immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  It wasn't all smooth sailing
&lt;/h2&gt;

&lt;p&gt;I'll be honest, Tauri has its quirks. The one that frustrated me the most early on was something embarrassingly simple: the close button didn't work.&lt;/p&gt;

&lt;p&gt;When I first got the app running, clicking the X to close the window did absolutely nothing. I had to force quit every single time. It took me a while to figure out the fix, but that kind of thing is part of working with a newer framework, the documentation isn't always as comprehensive as Electron's, and some things you just have to figure out yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Was it worth it?
&lt;/h2&gt;

&lt;p&gt;Yes, without question.&lt;/p&gt;

&lt;p&gt;For Termique specifically, the lightweight nature of Tauri isn't just a nice-to-have, it's part of the product's identity. An SSH manager should feel like a native tool, not a browser tab pretending to be one. 12MB installer, fast startup, no bloat. That's exactly what I wanted.&lt;/p&gt;

&lt;p&gt;If you're building a developer tool where performance and trust matter, I'd seriously consider Tauri. It's not as plug-and-play as Electron yet, but the tradeoffs are absolutely worth it.&lt;/p&gt;

&lt;p&gt;Termique is available at &lt;a href="https://termique.app" rel="noopener noreferrer"&gt;termique.app&lt;/a&gt;, free to try, and built entirely with Tauri.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>performance</category>
      <category>rust</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I got locked out of my own servers. So I built my own SSH manager.</title>
      <dc:creator>Rafi Bagaskara Halilintar</dc:creator>
      <pubDate>Thu, 28 May 2026 18:12:58 +0000</pubDate>
      <link>https://dev.to/masitings/i-got-locked-out-of-my-own-servers-so-i-built-my-own-ssh-manager-47l9</link>
      <guid>https://dev.to/masitings/i-got-locked-out-of-my-own-servers-so-i-built-my-own-ssh-manager-47l9</guid>
      <description>&lt;p&gt;A while back, I switched devices.&lt;/p&gt;

&lt;p&gt;Simple enough, right? Except I was on Termius Free and apparently &lt;br&gt;
host sync is a Pro feature. So everything I had set up, hosts, SSH &lt;br&gt;
keys, credentials, none of it carried over. I had to start from scratch.&lt;/p&gt;

&lt;p&gt;That was the moment I thought: &lt;em&gt;why am I paying for something that &lt;br&gt;
holds my own data hostage behind a paywall?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I built Termique.&lt;/p&gt;

&lt;h2&gt;
  
  
  One month. One developer. Zero co-founders.
&lt;/h2&gt;

&lt;p&gt;I started in early May. Today, Termique is a fully working SSH manager &lt;br&gt;
for macOS, Windows, and Linux, built with Tauri, React, Hono, &lt;br&gt;
PostgreSQL, Firebase, and Cloudflare Workers.&lt;/p&gt;

&lt;p&gt;The hardest part wasn't the code. I built most of it with AI assistance. &lt;br&gt;
The real challenge was figuring out &lt;em&gt;what to build&lt;/em&gt;, which features &lt;br&gt;
actually matter, how sync should work securely, and what should never &lt;br&gt;
leave your device.&lt;/p&gt;

&lt;p&gt;The second hardest part? Security auditing. Making sure nothing leaks &lt;br&gt;
that shouldn't. Credentials stay encrypted on your device. The server &lt;br&gt;
never sees plaintext. No telemetry on your sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does today
&lt;/h2&gt;

&lt;p&gt;Add a host on your laptop. Open your desktop. It's already there, IP, &lt;br&gt;
port, SSH key and all. No re-setup. No copy-pasting credentials between &lt;br&gt;
machines.&lt;/p&gt;

&lt;p&gt;That's the thing I'm most proud of. It sounds simple, but that's &lt;br&gt;
exactly the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where we are
&lt;/h2&gt;

&lt;p&gt;12 users, still very early. Launching on Product Hunt on June 15th. &lt;br&gt;
Free plan available, Pro is $5/month, half of what frustrated me in &lt;br&gt;
the first place.&lt;/p&gt;

&lt;p&gt;If you've ever been annoyed by Termius pricing or just want an SSH &lt;br&gt;
manager that doesn't feel bloated, I'd love for you to try it and &lt;br&gt;
tell me what you think.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://termique.app" rel="noopener noreferrer"&gt;termique.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
