This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
StockPile is a desktop inventory manager I built for my dad. It tracks batches of perishable goods - medicines, spices, or anything with an expiry date - entirely on his laptop. Nothing leaves his machine: no cloud, no API keys, no telemetry. Data lives in a single SQLite file tucked away in his home folder.
Demo
Code
How I Built It
I built this app using opencode in a single night .
Architecture
flowchart TD
subgraph Renderer["Webview renderer (React 19 + TypeScript)"]
UI["UI: Dashboard, Inventory, Sell, History, Agent"]
Search[Full-text search, typeahead]
end
subgraph Rust["Tauri v2 (Rust core)"]
IPC["Tauri commands (IPC API)"]
DB[SQLite via rusqlite]
Ollama[Ollama HTTP client]
end
subgraph LLM["Local LLM (Ollama)"]
FG[Function Gemma - tool calls only]
G4E["Gemma-4-e2b - reasoning & chat"]
end
UI -->|"invoke()"| IPC
IPC -->|read/write| DB
IPC -->|prompt| Ollama
Ollama -->|FG| FG
Ollama -->|G4E| G4E
DB -->|answer rows| Ollama
style Renderer fill:#f0f9ff,stroke:#3366cc,stroke-width:1px,color:#0b3a75
style Rust fill:#e8f5e9,stroke:#2e7d32,stroke-width:1px,color:#1b5e20
style LLM fill:#fafafa,stroke:#9e9e9e,stroke-width:1px,color:#212121
style FG fill:#fff3e0,stroke:#bf360c,stroke-width:1px,color:#3e2723
style G4E fill:#fff3e0,stroke:#bf360c,stroke-width:1px,color:#3e2723
Agentic layer
For natural‑language queries the app routes the request through two tiny open‑source models hosted by Ollama:
- Function Gemma (gemma3:270m) - a ultra‑light model that only generates a small JSON payload describing which tool to call and its arguments. It never returns free‑form text. The Rust backend validates the payload against a closed enum of allowed commands (add_batch, record_sale, query_stock, etc.) and then executes the command against SQLite. Because the model never sees raw stock numbers, it cannot hallucinate quantities.
- Gemma‑4‑e2b (gemma4:e2b) - a slightly larger model that receives the retrieved database rows as context and produces a conversational response sent back to the user through the agent chat panel. It runs only when the user asks a “why” or “what‑if” question; after it finishes the model is evicted immediately, keeping RSS under 400 MB.
The flow is:
- User types a sentence in the agent panel (e.g., “Sold 5 Panadol to Mr Sharma”).
- The Rust side sends a concise prompt to Function Gemma, which returns a JSON like
{ "tool": "record_sale", "args": { "buyer": "Mr Sharma", "qty": 5, "product": "Panadol" } }. - The backend validates and runs the tool, writes the ledger row, and returns a short confirmation.
- If the user asks “What’s expiring this month?” the prompt is sent to Gemma‑4‑e2b, which looks at the rows returned from SQLite and drafts a natural‑language answer such as “Three batches of amoxicillin expire within 30 days.”
- The answer streams into the chat panel. The model is then unloaded, and the next request starts fresh.
How it flows
- User interaction - clicking a button or typing in the React UI.
- IPC call - the renderer sends a request through Tauri’s Rust‑exposed command surface.
- Rust backend - the command reads or writes the local SQLite database (append‑only ledger, batch table, product table).
-
LLM involvement -
- For intent parsing or tool‑call generation, the prompt is forwarded to Function Gemma, which returns a minimal JSON payload. The backend validates and executes the command.
- For explanatory answers, the prompt is forwarded to Gemma‑4‑e2b, which receives the retrieved rows and produces a short narrative.
- Result back - the response travels back through IPC to the UI, which updates the view (e.g., new ledger row, formatted answer in the chat panel).
Both models run locally on Ollama and are evicted after each request.Everything runs on the user’s machine, there’s no network dependency .
Why Does Open Innovation Matter?
Using a local LLM keeps everything on the user’s machine, which matters for an app built for dad:
- Privacy – no data leaves the laptop, so personal inventory details never travel over the internet.
- Offline first – the app works without an internet connection, so stock can be added or queried even when the network is down.
- No API keys or subscriptions – there are no monthly fees or secret tokens to manage, making the app simpler to set up and maintain.
- Cost‑free – running a small model locally costs nothing compared with per‑token pricing from a cloud service.
- Reliability – the app isn’t dependent on a third‑party service being up; if the LLM process stops the deterministic rule‑based parser takes over instantly.
- Full control – the model, its size, and the keep‑alive behaviour can be tuned to keep RAM usage low (under 400 MB) and ensure the UI stays responsive.
Prize Categories
Gemma

Top comments (3)
"Nothing leaves his machine: no cloud, no API keys, no telemetry" — this is the whole philosophy in one line, and the single SQLite file as the entire database is such an underrated choice for software for our parents (backup = email them one file). Genuine question about the human side: what does your dad actually do in the app on a normal day? Does he open the dashboard and type questions, or did you have to design the flow around one or two habits he already had?
He already had to manually write all the inventory stocks and sale records so I designed the app around that , First i made sure the agent only has read access so getting info on inventory /sale/history data in natural language makes it easy for him to operate the app, for updating/adding new stocks the app follows double verification pattern where if my dad directs the agent to add new stock to inventory, the app has a verification layer built on top that verifies agent actions with a confirmation and what would it look like after the change so hallucinations don't destroy inventory records.
Read-only by default plus a confirmation layer for writes is exactly the right trust model — your dad gets the benefits of the agent without it ever being wrong at his expense. The 'here is what it will look like after the change' preview is the killer detail: for non-technical users, a visible before/after beats any permission system.
Question: does the verification step show a structured diff (field, old value, new value) or a natural-language summary? And has your dad actually caught the agent making a mistake at that step yet, or is it mostly a safety net so far?