I’ll fill the official template from the project as it actually runs, and check the challenge page so the prize section only lists categories this build can enter.
Paste this into a DEV post and add the tags devchallenge, weekendchallenge, and hf26challenge. The challenge page says that window closed on October 5, so this is the finished write-up, not a live entry.
This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
Second Plate is a dinner planner for the person I share a kitchen with. On a heavy week, dinner has to come from whatever is already in the house, reheat the next day, and stay inside a short list of allergies and foods they will not eat. I did not want that list sitting in a chat box on a server I do not control.
The page holds one person: their name, allergies, foods they will not eat, foods they love, and a note about how they are eating right now. I type what is in the kitchen and how many minutes I have. An open-weight model names one dish and writes the steps. A checker I can read then scans the draft. If the model mentions a forbidden food, or a food that is not in the kitchen, the steps are hidden and it has to try again.
The repository starts with a sample roommate so the app can be tried before it is handed over: peanuts, shellfish, and lactose, and no cilantro or mushrooms. Peanut oil counts as peanuts. Before I rely on a plan, I replace that profile with the real person. I have not handed it over yet, so I am not going to invent what they said.
Demo
It runs on the laptop. There is no hosted demo, because the point is that their food rules never leave the machine.
npm install
npm start
Open http://127.0.0.1:4317
hosting link:
hackoberfesttest1.vercel.app
The first plan downloads the model. After the weights are cached, starting the app with SECOND_PLATE_OFFLINE=1 keeps it from fetching them again. A plan on this CPU takes about a minute. The green line under the recipe is the checker, not the model's opinion.
On the sample profile, "rice fried in peanut oil" is refused. "Lemon tomato eggs with rice" is cleared. From eggs, rice, onion, tomato, lemon, and chili, the model planned Tomato Rice Salad, and the page stamped it as checked on this laptop against peanuts, shellfish, dairy, cilantro, and mushrooms.
Code
Second Plate
A dinner planner for one person you cook for. Their allergies, the foods they won't eat, and the notes about how they eat this month stay in a file on this laptop. Qwen2.5-1.5B-Instruct, an open-weight model under Apache 2.0, writes the meal. A checker in server/safety.js reads the same food list and hides the recipe if the model slips.
Run it
npm install
npm start
The server listens on 127.0.0.1 only. The first plan downloads the quantized model (a few hundred megabytes) into .cache. Later plans use that copy.
$env:SECOND_PLATE_OFFLINE = "1"
npm start
With that set, Transformers.js will not fetch weights again. Planning still works from the cache.
Hand it to someone
- Open the page and replace the sample roommate with the real person: name, allergies, foods they won't eat, foods they love, and how they eat right now.
- …
https://github.com/sonawanelalit574/Hackoberfest_test1
How I Built It
The open model is Qwen2.5-1.5B-Instruct, Apache 2.0, quantized to q4 and run on the CPU through Transformers.js and ONNX Runtime. The server listens only on 127.0.0.1. The profile, the cook's instructions, and the meal history are files next to the app.
The model does not get the last word. server/safety.js expands an allergy into its family: one shellfish blocks prawns and crab, and lactose blocks ghee, paneer, and butter. A won't-eat word stays literal, with a few obvious aliases, so cilantro also blocks dhaniya and fresh coriander, and it leaves coriander powder alone. The same list is shown to the model and enforced in code. Plant milk, eggplant, and the phrase "peanut-free" are tested so the checker does not become silly.
I tried SmolLM2-360M-Instruct first. It is open and small, and it kept inventing coconut milk and noodles that were not in the kitchen. The runtime takes any Transformers.js text-generation model id, so I switched the default to Qwen2.5-1.5B-Instruct without rewriting the checker. The page also has a box for the cook's job description, which is prompts/cook.txt. The next plan follows whatever is saved there.
The interface is one page. No account, no CDN, no API key.
Why Does Open Innovation Matter?
A closed API would have been the wrong default for this kitchen.
Their allergies and the shape of their week would have left the house with every dinner plan. Here the weights run on this CPU, and the profile stays in a JSON file. After the one-time download, a meal costs electricity, not a request to someone else's server, and there is no usage cap at 11pm.
I can also change the cook. A hosted chat product would have made the model, the tone, and the failure mode someone else's decision. Because the model is a file and the checker is plain code, I could throw out the small model that invented noodles, keep the same food rules, and put a stronger open model in its place. When I learn a new exception they care about, I can change the checker and the tests, and the next plan uses that rule.
My Agent Session
I built this with a coding agent in Cursor. I have not saved that session with DevRelay, so there is no agent-session embed yet.
No prize-category section: the project does not use Render, TabPFN, Tinker, Arduino, DigitalOcean, Gemma, or the other partner tools listed on the challenge page. It is still eligible for the overall prize if the post is accepted.
Top comments (0)