This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
My friend is learning Spanish. She's not afraid of grammar drills β she's
afraid of speaking. Every app she tried sent her halting, half-wrong sentences
to some company's server, and every time she got something wrong she felt like
she was being graded. She told me: "I want to practice without feeling watched."
So I built LinguaPal for her. It's a tiny practice partner that runs on her
own laptop. It:
- holds a conversation in Spanish at her level, and never gets tired or impatient;
- corrects her gently, right inside the reply β "you wrote
yo soy cansado; for a state like this,estoy cansado" β with a one-line reason, never a red mark; - turns every new word it introduces into a flashcard automatically;
- brings those words back later with a small spaced-repetition scheduler, so they actually stick;
- remembers the words she keeps forgetting and quietly weaves them into the next conversation;
- reacts as she practises: a little companion orb shows the tutor's mood (thinking, happy, gently-correcting) with a sprinkling of emoji, so it feels like a pal rather than a grader β a small thing that turned out to matter most.
The whole thing is one FastAPI app and a page of plain JavaScript. No account, no
signup, no analytics.
Her Reaction
"I can finally practice without feeling watched or graded. The gentle corrections and the little orb make it feel like a patient friend is right there with me instead of an app testing me."
Demo
Deployed app: https://linguapal.onrender.com β live on Render. You don't need a local
GPU to try it: the hosted app points LLM_BASE_URL at Google AI Studio's
OpenAI-compatible endpoint, serving Gemma open weights β so the live demo runs on
Gemma with no credit card and no local GPU. The same app runs fully offline on
my friend's laptop with LM Studio or Ollama. One variable, two deployments.
Code
surajns0033-collab
/
linguapal
A tiny offline language tutor built for one friend. Open-weight Gemma runs locally; her practice never leaves her laptop.
LinguaPal
A small, patient language tutor that runs on your own machine β built for one friend.
Built for the Hacktoberfest Weekend Challenge: Build for a Friend (Oct 2β5, 2026).
Live Demo: https://linguapal.onrender.com
LinguaPal is a language-practice partner for one real person β my friend, who is learning a new language and gets nervous about making mistakes. It chats with her at her level, corrects her gently with a short explanation, turns new words into flashcards automatically, and schedules those cards for review. Everything runs on a local open-weight model, and her practice never leaves her machine.
Contents
- The idea
- Features
- How it works
- Tech stack
- Getting started
- Configuration
- Project structure
- HTTP API
- Deployment
- Why open weights
- License
The idea
Most practice apps send every half-wrong sentence to a company's server, and grade it For a shy learner that is the worst possible design: the fear of being watchedβ¦
github.com/surajns0033-collab/linguapal β MIT licensed.
The interesting bits:
-
app/llm.pyβ talks to a local, OpenAI-compatible open-weight server (LM Studio or Ollama). -
app/prompts.pyβ a strictREPLY / CORRECTIONS / VOCABcontract so one local call yields the reply and the feedback. -
app/srs.pyβ a dependency-free small spaced-repetition scheduler. -
app/store.pyβ everything (learner, history, cards) in a single local SQLite file.
How I Built It
The core of LinguaPal is an open-weight model β during the challenge the tutor
ran on Gemma 3n E2B (2.79 GB, quantised), loaded in LM Studio on my own laptop.
app/llm.py speaks the OpenAI-compatible chat API, so the model is a swappable
part of the stack β not a hard dependency on anyone's cloud. Pinning it to Gemma,
or moving it from a laptop to a hosted endpoint, is one line in .env.
That last point matters for the deployed demo: an open-weight model is normally
served the same way everywhere, so the identical app talks to a laptop LM Studio
server or to a remote OpenAI-compatible open-weight endpoint (LLM_BASE_URL +
optional LLM_API_KEY). The hosted link and the offline laptop build are the same
code β only the endpoint differs. There is no closed API anywhere in the loop.
The one design constraint that shaped everything: a small local model is slower
and less chatty than a frontier API. So I stopped treating the model as an
oracle and treated it as a component. The prompt asks for a strict three-part
reply β the conversation, a list of corrections, and any new vocabulary β and
app/llm.py parses that into structured data. One local inference gives me the
reply and the feedback and the flashcards. The spaced-repetition scheduler
lives in plain Python (app/srs.py), not in the model, so the learner's progress
is deterministic and instant. The result feels responsive even on a 4B model
running on a laptop.
Open-source AI is the point, not a garnish: the model is the tutor. Everything
around it just makes a small local model feel like a patient friend.
Why Does Open Innovation Matter?
For this project, running on an open-weight model locally isn't a nice-to-have β it
is the feature. My friend's exact fear was being watched while practicing, and the
open approach removes that fear at the root:
- Her practice never leaves her laptop. Not "we don't log it" β it simply can't leave, because there's no remote API in the loop. That's the difference between a privacy policy and a privacy guarantee.
- It works with no internet. She practices Spanish on the metro, offline.
- It costs nothing to run, so she never feels she's "using up" someone's tokens and can't afford to make a hundred mistakes. For a shy learner, that changes everything.
- The model is swappable β and so is where it runs. Gemma today, Llama or Qwen tomorrow; on her laptop tonight, on a small hosted open-weight endpoint when she wants a public link. One env var, same app. A closed endpoint would lock her progress behind one vendor's pricing and one vendor's model.
- No GPU required to try it. The deployed demo uses an open-weight endpoint, so anyone can open a link and practise β then run the exact same code fully offline. Open weights make the offline build and the hosted build the same program.
- She can own it. It's MIT-licensed. If she wants to change the tone, the corrections, the scheduler, she just edits it. A gift you can open the hood on.
A closed API would have made this an app about a subscription. Open weights made it
a gift.
Deployment (Best Use of Render): the FastAPI app and front end are deployed on
Render on the free plan, with no credit card and no GPU. The always-on part β
the web app, the spaced-repetition scheduler, the SQLite store β lives on Render,
while the model stays swappable behind one env var: Google AI Studio's
OpenAI-compatible endpoint serves Gemma for the public demo, and the same build
points at LM Studio / Ollama for a fully offline setup on my friend's laptop. That split
is deliberate: the always-on, low-sensitivity part lives in the cloud; the private
part β her conversations β can stay entirely local.
My Agent Session
Prize Categories
-
Best Use of Gemma β Gemma is the tutor's core. Two of the three allowed paths
need no code change and both are wired in:
(a) run it locally β during the challenge the tutor ran on Gemma 3n E2B in
LM Studio on my laptop; (b) serve it through a provider β the live demo points
LLM_BASE_URLat Google AI Studio's OpenAI-compatible endpoint serving Gemma 4 (LLM_MODEL=gemma-4-26b-a4b-it), the same app with one env var. (c) fine-tune it β because the model sits behind the singleapp/llm.pyseam, a Gemma fine-tuned to my friend's level drops in as just anotherLLM_MODEL, with nothing else touched. - Best Use of Render β the app/front end is deployed on Render and Gemma is served remotely, so the whole thing runs with no credit card and no GPU.
Built solo during the Hacktoberfest Weekend Challenge window, Oct 2β5, 2026.
Open-source AI at the core; MIT licensed; no data leaves the learner's machine.
Top comments (0)