{"slug": "ofrenda", "title": "OFRENDA", "summary": "A developer built Ofrenda, an open-source, local-first memory altar for Día de los Muertos that stores a family's stories, foods and songs as plain JSON and uses a locally served open-weight Gemma model via Ollama to write grounded remembrances and answer questions with citations. The app is instructed never to invent details or impersonate the deceased, falls back to a labeled rule-based mode when Ollama is unavailable, and exports each altar as a single offline HTML file with no server or JavaScript.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine](https://dev.to/challenges/hacktoberfest-week4-2026-10-26)*\n\n## \n  \n  \n  What I Built\n\n**Ofrenda** is a memory altar that never leaves your computer.\n\nOn Día de los Muertos, families build an *ofrenda* for the people they miss: a photo, a candle, their favorite food, their song. The idea is that someone is only truly gone when nobody says their name anymore. I read the \"Ghost in the Machine\" prompt as: *what is the ghost, and who gets to keep it?* My answer is that the ghost is a person's stories, and a family, not a company, should be the one keeping them.\n\nYou light a candle for someone, then add stories, foods, songs and sayings, in any language. A local open-weight model then does two jobs:\n\n- \n**Writes a remembrance** from*only* what you shared. It is told never to invent names, places or events.\n- \n**The Memory Keeper** : ask \"what did she cook on Sundays?\" and it answers from your memories, with citations like`[2]` . It speaks*about* the person and never in their voice. If nobody has shared the answer, it says:*\"No one has shared a memory of that yet.\"* I did not want a chatbot pretending to be someone's grandmother. I wanted something that helps you remember, not something that fakes a séance.\n\nWhen you're done, **export the altar as a single HTML file**: no server, no JavaScript, no fonts to download. It opens offline in any browser, in any year.\n\n## \n  \n  \n  Demo\n\n## \n  \n  \n  Code\n\n### \n       Offline, private memory altar for Día de los Muertos, powered by a local Gemma model via Ollama. Hacktoberfest 2026 “Ghost in the Machine”.\n    \n\n \n\n# 🕯️ Ofrenda\n\n**A memory altar that never leaves your machine.**\n\nAdd the stories, foods and songs of someone you miss. A local open-weight model helps you remember them, and only from what *you* shared.\n\n*Built for the Hacktoberfest Open-Source AI Challenge, Week 4: **Ghost in the Machine***\n\n \n\n## The idea\n\nOn Día de los Muertos, families build an *ofrenda* for the people they miss: a photo, a candle, their favorite food, their song. Someone is only truly gone when nobody says their name anymore.\n\nA family's grief archive is some of the most private data they own, so it should not live on a server they don't control. Ofrenda keeps everything on your computer and uses an **open-weight model running locally** to help you remember.\n\n## Features\n\n- 🕯️ **Light a candle** : create an altar with a name, years, relationship and photo.\n- 📖 **Add memories** in any language: stories, favorite foods, songs…\n\n \n \nStack: Python + Flask, vanilla JS (no build step), JSON files for storage, Ollama for local inference. Tests use only the standard library.\n\n## \n  \n  \n  How I Built It\n\n- \n**Model:** an open-weight**Gemma** model served locally by**Ollama** (`gemma3:4b` by default;`OFRENDA_MODEL` swaps it, and the app auto-detects what you have installed).\n- \n**Grounding over cleverness:** every memory is numbered and passed to the model with strict instructions: use only these, cite them, never impersonate, and treat memory text as data, not instructions. A small keyword retriever picks the most relevant memories for each question (it splits on whitespace, so it works for scripts like Telugu and Devanagari too, not just English).\n- \n**Graceful ghosts:** if Ollama isn't running, the app drops to a labelled rule-based`offline-fallback` instead of failing, so the altar always opens.\n- \n**Local-first by construction:** the server binds to`127.0.0.1` , storage is plain JSON in`./data` with atomic writes, and the UI makes zero external requests.\n- \n**Safety details:** text is rendered with`textContent` , the exported HTML is escaped, IDs are validated against path traversal, and photo uploads are extension-checked and size-capped.\n\n## \n  \n  \n  Why Does Open Innovation Matter?\n\nA grief archive is about the most private dataset a family has. Stories about a parent's last year, a grandmother's recipes, the thing a friend always said.\n\n- \n**Privacy:** with an open-weight model running locally, those stories are never uploaded to a server we don't control, and never become someone else's training data.\n- \n**It works with the lights (and the internet) off:** the model, the app and the exported altar all run offline.\n- \n**Not locked inside a service that might disappear:** closed memorial apps shut down, change pricing, or change terms. Here the data is plain JSON, the model is a file on your disk, and the export is one HTML page. A family can still open it in twenty years.\n- \n**Control over behavior:** because I own the model's instructions, I could enforce the rule that matters most emotionally:*never speak in the voice of the dead.* I could also tune it to cite sources and to refuse to guess, which is hard to guarantee with a hosted model whose behavior changes between versions.\n- \n**Cost:** it costs nothing to run per question, which matters for something people might come back to every November.\n\n## \n  \n  \n  My Agent Session\n\n## \n  \n  \n  The Spirit of It\n\n## \n  \n  \n  Prize Categories\n\n- \n**Best Use of Gemma** : the core model is Gemma, run locally through Ollama.\n- \n**Best Use of GitHub Copilot** : <!-- keep only if you really used Copilot to build it, and say how -->\n- \n**Best Use of Entire** : <!-- keep only if you share the agent sessions behind the project -->", "url": "https://wpnews.pro/news/ofrenda", "canonical_source": "https://dev.to/noor_ulhuda_67fbcf3d4b66/ofrenda-468b", "published_at": "2026-10-28 21:22:34+00:00", "updated_at": "2026-10-28 21:41:29.254126+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "generative-ai", "ai-tools", "ai-safety"], "entities": ["Ofrenda", "Ollama", "Gemma", "Hacktoberfest", "Flask", "Python"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/ofrenda", "markdown": "https://wpnews.pro/news/ofrenda.md", "text": "https://wpnews.pro/news/ofrenda.txt", "jsonld": "https://wpnews.pro/news/ofrenda.jsonld"}}