Appel is de eigen studie- en stem-bot van Dani (Jamals zoon, 13 jaar, 1 havo/vwo, Stanislas Westplantsoen Delft).
Appel draait volledig op de VPS (149.210.171.174, user jamalhaarvisie).
Appel bestaat uit één frontend (de webpagina) + twee back-end services (relays).
De stem hergebruikt de Jarvis-api (poort 8748). De toets-nakijker is een eigen service.
| Onderdeel | Wat | Poort | systemd-service | Hoe nginx het stuurt |
|---|---|---|---|---|
| Frontend | index.html (versie v9.10) |
β (statisch via nginx) | β | location / β bestanden |
| Stem-api | Jarvis-api (gedeeld) | 8748 | (jarvis-service) | /api/ β 8748 |
| Live relay | appel-live.py (stem-WebSocket) |
8751 | appel-live.service |
/live β 8751 (wss) |
| Toets-backend | appel-toets-api.py (nakijker) |
8753 | appel-toets.service |
/toets/ β 8753 |
nginx-config: /etc/nginx/sites-enabled/appel.haartips.nl
- client_max_body_size 12M
- / heeft Cache-Control: no-store, no-cache, must-revalidate β altijd verse versie.
- /live heeft Upgrade-headers + proxy_read_timeout 600s (lange stem-sessies).
- HTTP (poort 80) β 301 redirect naar HTTPS.
SSL: certbot/Let's Encrypt. Verloopt 21 september 2026 (Sep 21 17:54:28 2026 GMT). Vernieuwt automatisch.
Status nu: appel-live = active, appel-toets = active.
| Pad | Inhoud |
|---|---|
/var/www/appel-haartips/index.html |
De frontend (v9.10). Eigenaar: root:root β bewerken met sudo. |
/var/www/appel-haartips/va/ |
De podcast/video-bestanden (zie hieronder). |
/opt/jarvis/appel-live.py |
Stem-relay (poort 8751). |
/opt/jarvis/appel-toets-api.py |
Toets-nakijker (poort 8753). |
/opt/jarvis/env |
API-keys (o.a. GEMINI_KEY) β door beide services geladen via EnvironmentFile. |
/opt/jarvis/toets-attempts.jsonl |
Logboek van alle nagekeken toetsen. |
/etc/nginx/sites-enabled/appel.haartips.nl |
nginx-routes + SSL. |
Media in /var/www/appel-haartips/va/:
- les-geschiedenis.mp3
- les-aardrijkskunde.mp3
- les-frans.mp3
- les-biologie.mp3
- les-levensbeschouwing.mp3
- les-geschiedenis-video.mp4 (~100 MB)
Alleen de Appel-services aanraken. NOOIT breed killen (geen brede pkill).
Stem-relay herstarten:
sudo systemctl restart appel-live
Toets-nakijker herstarten:
sudo systemctl restart appel-toets
Status checken:
systemctl is-active appel-live appel-toets
Logs bekijken bij een storing:
sudo journalctl -u appel-live -n 50 --no-pager
sudo journalctl -u appel-toets -n 50 --no-pager
nginx herladen na een config-wijziging:
sudo nginx -t && sudo systemctl reload nginx
Let op: raak NOOIT de jarvis-service (8748) aan zonder reden β die wordt door Jarvis Γ©n Appel (stem) gedeeld.
Stem-bot (praten met Appel)
- Mannelijke stem Puck, Gemini Live, camera aan.
- Overhoort Dani op alle schoolvakken + educatie + denkpuzzels.
- Gedragsregels: kort antwoorden, luisteren naar de echte vraag, bij correctie direct stoppen + sorry, niet over-vragen.
- Pauzeknop in de footer (audio stopt, WebSocket blijft open).
- Tools: zoek_internet, onthoud_dit, vraag_aan_papa (β Conductor β Jamal), lees_verslagen. GEEN huisbediening/berichten (bewust eruit).
Mijn lesstof β lespanel met de stof per vak (geschiedenis, aardrijkskunde, Frans, biologie, levensbeschouwing) + een podcast-speler per vak.
Flashcards β per vak, tabs voor geschiedenis / aardrijkskunde / Frans / biologie / levensbeschouwing. Twee modi: Bekijken (flip) en Oefenen (multiple choice met plausibele afleiders, geluid, XP, combo's, streak, voortgangsbalk via localStorage).
Toets levensbeschouwing + nakijker β 20 open vragen, Dani typt antwoorden, "Nakijken" stuurt ze naar de toets-backend (Gemini). Verslag: score + per vraag goed/fout + modelantwoord + warme feedback.
Hertoets β doet de toets opnieuw met alleen de fout beantwoorde vragen.
Oefen mijn fouten (v9.10) β maakt flashcards van de fout beantwoorde toetsvragen om ze te oefenen.
Podcasts β eigen paneel met ingesproken lessen per vak (stem Sulafat, Gemini TTS).
IQ-test β visuele oefentest met SVG-figuren (Raven-style matrices, getallenreeksen, logica), timer, score + niveau-band. Eerlijk gelabeld: oefentest, geen officiΓ«le IQ-meting.
Typcursus β 9 oplopende lessen (blind typen), live feedback, WPM + nauwkeurigheid, on-screen toetsenbord met vinger-hint, lessen worden vrijgespeeld (localStorage).
Bestand: /opt/jarvis/appel-toets-api.py β Python stdlib http.server (ThreadingHTTPServer), draait op 127.0.0.1:8753, service appel-toets.service.
Endpoints:
- POST /grade β body: {"items":[{"q":"vraag","model":"modelantwoord","given":"leerling-antwoord"}, ...]}
- GET /health β ok
Gemini:
- Model: gemini-2.5-flash (via HTTP, geen SDK).
- Key uit /opt/jarvis/env (GEMINI_KEY).
- temperature: 0.1, responseMimeType: application/json, maxOutputTokens: 8192.
De rubric (eerlijk + educatief):
- Beoordeelt alleen de betekenis, niet de formulering. Eigen woorden / synoniemen / voorbeelden = goed.
- Spelfouten en hoofdletters tellen NIET mee.
- Fout = leeg antwoord, verkeerde betekenis, of bluf/nietszeggend ("weet ik niet", vraag herhalen).
- In twijfel mild: klopt de strekking β goed.
- Geeft per vraag warme, behulpzame feedback (1-2 zinnen) met een weetje, hint of ezelsbruggetje.
Batches: vragen worden nagekeken in batches van 8 (BATCH = 8) β kleine, betrouwbare JSON per call, voorkomt afkappen bij veel vragen. Robuuste JSON-parse (strip markdown-fences, pakt het [..]-deel, verwijdert trailing comma's). Resultaten uitgelijnd op positie via "n".
Logging: elke nagekeken toets wordt als één regel weggeschreven naar /opt/jarvis/toets-attempts.jsonl (timestamp, score, total, alle items met vraag/antwoord/ok/feedback).
| Probleem | Oorzaak | Fix |
|---|---|---|
Kan index.html niet bewerken |
Bestand is root:root | Bewerk met sudo: sudo cp naar /tmp, chown, edit, scp/sudo cp terug |
| Toets-nakijken gaf 500 | maxOutputTokens stond op 2048 β te klein voor 20 items |
Op 8192 gezet + nakijken in batches van 8 |
| Dani ziet oude versie | Browser-cache | nginx stuurt al no-store; bij twijfel tab echt sluiten + heropenen (verse page-load nodig voor nieuwe stem-persona) |
| Gesprek valt kort weg | Gemini-key gedeeld met Jarvis β daglimiet | Spreid gebruik; oortje helpt tegen echo |
| Stem-persona/versie laadt niet | Persona laadt alleen bij verse page-load, niet na pauze | Appel afsluiten + heropenen |
Pagina laadt niet / wit scherm
1. systemctl is-active appel-live appel-toets β beide moeten active zijn.
2. sudo nginx -t β config OK? Zo nee, fout in /etc/nginx/sites-enabled/appel.haartips.nl.
3. Check of /var/www/appel-haartips/index.html bestaat en niet leeg is. (Let op: een niet-gesloten HTML-comment geeft een blanco pagina.)
Stem werkt niet (geen antwoord / verbinding valt weg)
1. sudo systemctl restart appel-live.
2. sudo journalctl -u appel-live -n 50 --no-pager β kijk naar fouten.
3. Check /api/ β poort 8748 (jarvis-api) draait? De stem hergebruikt die.
4. Daglimiet Gemini? (gedeeld met Jarvis.)
Toets nakijken faalt (500 / geen verslag)
1. sudo systemctl restart appel-toets.
2. sudo journalctl -u appel-toets -n 50 --no-pager.
3. Check GEMINI_KEY in /opt/jarvis/env (bij start logt de service key=ja of key=NEE).
4. GET https://appel.haartips.nl/toets/health β moet ok geven.
5. Te veel vragen ineens? Backend doet al batches van 8 β bij JSON-fouten check de Gemini-respons in de log.
Geen geluid bij podcasts
1. Check of de mp3's bestaan in /var/www/appel-haartips/va/.
2. Test rechtstreeks: https://appel.haartips.nl/va/les-<vak>.mp3 β moet 200/206 geven.
SSL-waarschuwing / certificaat verlopen
- Verloopt 21-09-2026, vernieuwt automatisch (certbot). Forceren: sudo certbot renew + sudo systemctl reload nginx.
Algemeen: raak alleen de Appel-services aan. NOOIT breed killen β dat raakt Jarvis en andere bots.
ποΈ Bespreek met Jarvis