DEV Community

Yavuz Utku Varol
Yavuz Utku Varol

Posted on

How I Built a Free German Learning App with Firebase + Vanilla JS (No Framework)

I've been learning German for a while and couldn't find a tool that fit my workflow — most apps are either too gamified or locked behind paywalls. So I built my own: AlmancaPratik, a free web app for Turkish speakers learning German.
Here's the stack I used and what I learned along the way.

Stack

Vanilla JS (ES Modules, no React/Vue)
Firebase Auth (Google Sign-In)
Firestore (user data — words, texts)
GitHub Pages (hosting — completely free)

Zero server costs. Zero monthly fees.

Architecture
Every user's data lives under their own Firestore path:
users/{userId}/words/{wordId}
users/{userId}/texts/{textId}
Firestore Security Rules handle authorization — only the authenticated user can read/write their own data:
jsmatch /users/{userId}/{document=**} {
allow read, write: if request.auth.uid == userId;
}
No backend needed. The rules ARE the backend.

The Interesting Part — Example Sentences
When a user saves a German word, they can click it to see real usage examples. I pull these from two public APIs in sequence:

Wiktionary API — parses the "Beispiele" (examples) section from the German Wiktionary entry
Tatoeba API — fallback if Wiktionary returns nothing

jsasync function fetchExampleSentences(word) {
let sentences = await fetchFromWiktionary(word);
if (sentences.length < 2) {
const tatoeba = await fetchFromTatoeba(word);
sentences = [...sentences, ...tatoeba.slice(0, 2 - sentences.length)];
}
return sentences;
}
Both APIs are free, no auth required. The results are cached in a Map() so the same word is never fetched twice in a session.

What the App Does

Text Analysis — paste German text, click any word to look it up
Quiz — multiple choice + typing mode from your saved words
Artikel Finder — der / die / das lookup
Sentence Examples — Wiktionary + Tatoeba
Word List — save, tag, filter, edit your vocabulary

Lighthouse Scores

Performance: 99
Accessibility: 100
Best Practices: 100
SEO: 100

Getting accessibility to 100 required fixing contrast ratios, adding landmarks, and making sure all buttons had proper aria-label attributes.

What I'd Do Differently
Vanilla JS was a deliberate choice — I wanted zero build tooling. But as the app grew, managing state across pages without a framework got messy. If I started today I'd probably use a lightweight option like Preact.

Try it: almancapratik.com
GitHub feedback welcome in the comments.

Top comments (0)