Desktop companion · Open source

Speak German every day.

Fluentoo floats on your desktop, hands you a two-minute speaking mission, listens, answers in German, and corrects you the way a friend would.

The product

Small enough to keep open. Friendly enough to come back to.

A frameless, always-on-top window. Pick today's mission, hit Sprechen, and talk. The character reacts to how it went, the streak keeps you honest, and corrections show up as “Man sagt besser …” instead of red ink.

Fluentoo window showing the avatar, three daily missions, the Sprechen button and a five-stage progress track
Daily missions. Three short speaking prompts, rotated each day.
Fluentoo after a completed mission: emoji confetti, a 'Mission geschafft' banner and a correction card reading 'Ich habe Kaffee getrunken.'
Gentle corrections. Mistakes become a “Besser gesagt” card, not a failure.
How it works

One loop, tuned for speaking.

The whole design goal is latency: if a reply takes too long, speaking stops feeling like a conversation.

Speak

Talk into the mic, or type if you're on a train.

MediaRecorder · Web Speech

Transcribe

Fast hosted Whisper first; on-device Whisper when you're offline or keyless.

Groq · transformers.js

Coach

An LLM tutor replies in simple A2–B1 German and judges the mission.

Featherless · Obsidian notes

Reply

The answer is spoken in a natural German voice, with browser speech as fallback.

CambAI TTS
🎯

Daily missions

Morgen-Check, Restaurant, Wochenende, Mini-Story. Any genuine attempt counts.

🌱

Five fluency stages

XP, a streak multiplier and level-up moments from Schüchtern to Fluentoo Level.

😄

A character with moods

The avatar laughs, smiles or looks a little sad depending on how the round went.

📓

Your own vocabulary

Point it at an Obsidian vault and your word lists flow into the tutor's context.

⏰

Habit nudges

A gentle reminder every 45 minutes keeps the streak alive.

🔒

Local first

Progress and settings stay on your machine. Bring your own API keys.

Engineering

Decisions worth explaining.

  • Graceful degradation everywhere. Hosted STT → local Whisper; CambAI voice → browser speech. With zero keys besides the LLM, it still works end to end.
  • Structured output from a chatty model. The tutor ends mission replies with a MISSION_RESULT: PASS|FAIL line that's parsed and stripped; a local heuristic covers the case where the model forgets.
  • Secure Electron defaults. Context isolation on, no Node in the renderer, a narrow preload bridge and a strict Content-Security-Policy.
  • No UI framework. The avatar, emotions and confetti are plain CSS (conic gradients and keyframes), so the window idles at near-zero cost.

Built as a hackathon project and kept small on purpose: about 2,300 lines of vanilla JavaScript, HTML and CSS.

Electron 31Node.jsOpenAI-compatible SDKFeatherlessGroq Whispertransformers.jsCambAIelectron-storeVanilla JS/CSS
Architecture overview: Speak, Transcribe, Coach, Reply, with the Electron screen, preload bridge, speech, teacher and storage layers

Try it locally.

macOS tested. You need a Featherless key for the tutor; voice keys are optional.

git clone https://github.com/kaiser-data/fluento
cd fluento && npm install
cp .env.example .env   # add your keys
npm start