This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
What I Built
Ofrenda is a tool for remembering someone you miss, made for Día de los Muertos.
You enter a loved one's name and a photo, then tell their stories by typing or by speaking. A local language model asks one gentle question at a time ("What did their kitchen smell like on Sundays?"), and Whisper transcribes anything you say out loud. Then you add the things they loved: a food, a song, something they always said, a flower, a place.
From only what you told it, the model writes a short remembrance that you can edit. The tool then builds a candlelit ofrenda page with flickering candles, marigolds, papel picado, and their photo in a frame. You download it as a single HTML file that opens anywhere, with no account, server, or service behind it.
I read "Ghost in the Machine" as the people who live on in the stories we carry. It is easy to get lost in the world of codes and machines, but we must not forget the eyes that see it, and the souls shared between those eyes.
Two rules shaped the design. The guide never speaks as the person who died; it only asks questions. And the writing prompt forbids invented facts, so the remembrance contains only what you said.
Demo
Code
Ofrenda
A local-first ofrenda builder for Día de los Muertos. You tell the stories of someone you miss (typed or spoken) a local LLM asks gentle follow-up questions and writes a remembrance from only what you said, and you get a candlelit ofrenda page you can keep as one HTML file. No cloud, no accounts, no API keys.
Run it
# 1. Inference: https://ollama.com
ollama pull qwen2.5:7b # fits 16 GB RAM; try llama3.1:8b or gemma2:9b too
# 2. Transcription (optional, enables the Record button)
pip install -r requirements.txt # first run downloads Whisper "small" once
# 3. Go
python3 server.py # open http://127.0.0.1:8765
Swap models: OFRENDA_MODEL=llama3.1:8b python3 server.py. Smaller Whisper: OFRENDA_WHISPER=base.
Prove it's offline
After the one-time downloads, turn Wi-Fi off and run it again. The server binds to 127.0.0.1 only, the page loads no fonts, scripts or images from the web, and photos are resized in…
How I Built It
-
Inference: Ollama running
qwen2.5:7b, an open-weight model that fits in 16 GB of RAM. The model is one environment variable:OFRENDA_MODEL=llama3.1:8b python3 server.py. - Speech to text: faster-whisper, running Whisper locally.
-
Backend: a small Python standard-library server, bound to
127.0.0.1only. It serves the page, streams model output from Ollama, and handles transcription. - Frontend: one HTML file with no frameworks, no CDN, and no web fonts. Photos are resized in the browser and embedded straight into the exported file.
- Prompts: one prompt for the question-asking guide and one for the remembrance. The remembrance prompt requires using only the user's notes and keeping their own phrases.
Why Does Open Innovation Matter?
A remembrance of someone who has died is some of the most private writing a person does. The photos, the voice recordings and the stories shouldn't have to be uploaded to a company's servers to be turned into something beautiful.
- It works offline. I turned Wi-Fi off, restarted the server, and built a full ofrenda.
- Nothing leaves the machine. The server binds to localhost, and the page loads nothing from the web. Photos and voice recordings stay local.
- I could swap the model. I compared qwen2.5:7b and llama3.1:8b; former wrote more plainly, latter kept my phrases better. With a closed API, the model could change underneath me or be retired.
- It costs nothing to run. No API keys, no per-request fees.
- It can't disappear. The output is a plain HTML file. If I stopped maintaining this project, every ofrenda ever made with it would still open.
Top comments (1)
The constraint that the guide asks questions but never speaks as the person is what gives the project its integrity. Local-first storage and the self-contained HTML export make that boundary practical as well as poetic. I would keep an optional source view beside the generated remembrance, so an editor can trace each line back to the story or transcription that supported it before sharing the final page.