Werk uitsluitend binnen deze projectdirectory
(/home/bob/Projects/ff-app/uitgaanskrant-1qhvtd). Niet daarbuiten
zoeken of scannen — scope alle bestandsoperaties tot dit project.
CLAUDE.md + TASKS.md
zijn samen het volledige geheugen tussen sessies.TASKS.md-status kan achterlopen op de echte code (Bob werkt
gelijktijdig, en documentatie-updates lopen niet altijd synchroon
met de export). Check een taak die er al even staat met
git log --oneline -S"<kenmerkende string/tekst>" of een gerichte
grep vóórdat je 'm oppakt — niet blind vertrouwen dat "open"
betekent "nog niet gefixt". (Precedent: 2026-08-04 bleken 2 "open"
P0-taken al op 2026-08-02 gefixt te zijn, git-bevestigd.)TASKS.md heeft een stabiel ID (bv. P0-1) en een
Eigenaar:-regel — Bob (sneller/simpeler voor hem zelf, meestal
builder-UI met een bekend fragiele dialoog, zie hieronder), Claude
(onbeklaimd, vrij op te pakken), of ... — bezig (iemand is er
nu actief mee bezig). Vuistregel voor wie een nieuwe taak zou
moeten doen: een kort, mechanisch herhaald patroon zonder geneste
dialogen → Claude; ConditionalBuilder/JSON-Path-condities,
List-typed function-argumenten, of iets dat eerder al vastliep →
Bob.Aan het eind van elke sessie/taak:
TASKS.md: een afgeronde taak wordt volledig verwijderd
(niet gearchiveerd — onnodige context/kosten voor latere sessies).
Elke resterende open taak moet zelfstandig te begrijpen zijn
(concreet, met bestandspad) zonder de ontstaanschat gelezen te
hebben.CLAUDE.md: alleen aanvullen met blijvend herbruikbare inzichten
(conventie, architectuurkeuze, bekend valkuil-patroon) die een
latere sessie anders opnieuw zou moeten uitzoeken. Geen
sessieverslag/changelog. Ruim verouderde info op i.p.v. eronder te
plakken — dit bestand moet klein en scanbaar blijven..md-bestanden direct (geen
FlutterFlow-export nodig voor pure documentatiewijzigingen).Geen apart memory-systeem meer nodig voor projectfeiten — die
staan allemaal hier en in TASKS.md, wat al elke sessie automatisch
geladen wordt. (Auto-memory-bestanden zijn per 2026-08-04
opgeschoond omdat ze dit bestand 1-op-1 dupliceerden.)
Dit project wordt gebouwd via FlutterFlow (app.flutterflow.io). De FlutterFlow-cloudomgeving is de bron van waarheid, niet deze lokale code-export.
lib/custom_code/) — ook die voert Bob in via de Custom
Code-editor op de website, niet hier lokaal.flutter
analyze), maar voer het eindresultaat uit via de builder (zelf via
browser-automation, of als instructie aan Bob). Ga nooit uit van
behoud van een lokale bestandswijziging.git commit.mcp__claude-in-chrome__* (Bob's gedeelde Chrome), niet
de in-app Browser pane.Projectdirectory = eigen schone git-repo, origin
ssh://gogs.digitalforce.tv:2222/Uitgaanskrant.com/flutterflow.git,
branch master. Los van de grotere/rommelige repo hoger in de
mappenstructuur (AndroidStudioProjects, Flutter-SDK e.d.) — commits en
pushes horen hier.
Vaste workflow na elke afgeronde taak (staand akkoord, geen aparte
bevestiging nodig): niet los flutterflow export-code, maar:
export PATH="/home/bob/fvm/bin:$HOME/.pub-cache/bin:$PATH" && /home/bob/Projects/ff-run-fvm.sh emulator-5554 uitgaanskrant-1qhvtd -s
export PATH=... prefix is verplicht — Bash draait
niet-interactief, ~/.bashrc wordt niet geladen. Zonder prefix
faalt het script stil ("fvm: command not found" — geen harde error).run_in_background: true. Volg tot minimaal "All done!" én
idealiter een succesvolle app-launch (Launching lib/main.dart...,
geen nieuwe EXCEPTION CAUGHT BY RENDERING LIBRARY).Daarna automatisch:
git status --short, dan git add — niet blind -A. Alleen
echte FlutterFlow/app-wijzigingen (lib/, android/, ios/,
pubspec*, .gitignore). .claude/ blijft uitgesloten
(sessiestate, geen app-code). Bob's eigen concurrente wijzigingen
horen gewoon mee in dezelfde commit.git commit met duidelijke boodschap.git push (-u origin master als tracking nog niet staat).Valkuil: flutterflow export-code overschrijft .gitignore bij
elke export terug naar FlutterFlow's standaardversie. Voeg na elke
export, vóór staging, deze regel weer toe als hij ontbreekt:
# Claude Code session state (not app code)
.claude/
(CLAUDE.md zelf overleeft een export altijd — check voor de
zekerheid toch even.)
Vóór een niet-triviale taak (bugfix, nieuw patroon, integratie): kort online zoeken naar bestaande oplossingen i.p.v. zelf trial-and-error in de builder. Geldt niet voor mechanische herhaling van een patroon dat al bevestigd werkt.
Geneste "Set Variable"-dialoog lijkt vast te zitten. Bij een
conditie (ConditionalBuilder, Visibility → Conditional) op een
niet-triviaal type (JSON Path, API-response-veld, List<DataType>
function-argument) opent een tweede dialoog bovenop de eerste;
Confirm/Cancel reageren soms niet zichtbaar. Twee oorzaken, in
volgorde van proberen:
navigate naar dezelfde URL); wrap blijft staan, conditie moet
opnieuw.Component Name kan per ongeluk overschreven worden. Vlak na paginanavigatie kan een klik bedoeld voor "Search properties..." op het Component Name-veld landen (focus/z-order race), en typen hernoemt dan stilletjes het component. Zelfde risico bij een widget-tree zoekactie die per ongeluk double-click-to-rename triggert i.p.v. navigeren — druk direct Escape om te herstellen. Mitigatie: na elke click-before-type eerst een screenshot om focus te bevestigen, zeker vlak na navigatie. Herstel: rechtsklik component in zoekresultaten → "Rename Component".
Rechterpaneel kan te breed zijn voor de viewport. Sommige controls
(Expansion segmented control, Visibility → Conditional
expression-builder, maar ook simpele checkboxen zoals "Show Empty List
Widget" op een Carousel/ListView) renderen soms deels buiten beeld —
geen resize_window-probleem (niet zelf resizen, zie boven).
Bevestigd 2026-08-04: dit blijft optreden zelfs nadat Bob zijn eigen
venster al vergroot had — de FlutterFlow-app zelf lijkt de extra
breedte niet te gebruiken (real window 1970px, maar bruikbare
schermafbeelding/klikbare ruimte bleef begrensd tot ~1176px; de
JS-laag rapporteert wel de volle vensterbreedte, dus dit zit in hoe
Flutter Web rendert/schaalt, niet in het venster zelf). Geen
DOM/accessibility tree beschikbaar (canvas-rendering) — find en
read_page werken hier niet, alleen coördinaat-gebaseerd klikken.
Geprobeerd en zonder succes: direct klikken op meerdere
x-posities, klikken + Space-toets, horizontaal scrollen. Na 1-2
bevestigde pogingen stoppen en aan Bob vragen — geef het exacte pad
(component, tree-node, veldnaam) zodat hij het in seconden kan doen.
Patroon: lege/ontbrekende afbeeldings-URL laat de app crashen.
CachedNetworkImage gooit een synchrone ArgumentError bij het
bouwen van de widget als imageUrl een lege string is — dit gebeurt
vóórdat er ooit een netwerkverzoek is, dus errorWidget/"Show Error
Image on Failure" vangt dit niet (dat vangt alleen échte
laadfouten zoals 404's). Werkende fix:
null als lege string (in-builder tooltip: "if the resulting
value is null or empty") — géén ConditionalBuilder nodig. Werkt hier
niet voor Image-widgets met Image Type: Network zolang er geen
gehoste fallback-afbeeldings-URL bestaat in dit project. Komt die er
ooit (bv. default-logo op FlutterFlow-CDN/Drupal-server): gebruik
dan Default Variable Value + "Show Error Image on Failure" — sneller
te bouwen dan ConditionalBuilder.Tooltip toevoegen aan een icon-only widget: rechtsklik → Wrap
Widget (Ctrl+B) → 4e rij van de grid (kan geclipt lijken) → 1e icoon
(spraakwolkje) = "Tooltip". Genereert een AlignedTooltip, geen losse
styling nodig. Werkt niet op iconen embedded als suffixIcon van een
TextFormField (bv. Login-pagina wis-/toon-wachtwoord-iconen — geen
losse wrapbare tree-node).
API-call headers: check op hardcoded literals i.p.v. [varname]
templates. Werkt een call via curl wél maar vanuit de app/Response &
Test-panel niet: check het Headers-tabblad — een handmatig ingeplakte
testwaarde (bv. Cookie-header) kan per ongeluk blijven staan i.p.v.
[sessionname]=[sessionid]. Check ook het per-variabele
"Include"-vinkje in Response & Test — staat die uit, dan wordt de
letterlijke [varname]-tekst meegestuurd i.p.v. de testwaarde.
sessid + session_name (uit
LoginCall's response) vormen samen de sessie-cookie:
Cookie: <session_name>=<sessid>. token is een los CSRF-token,
alleen nodig bij schrijf-requests (POST/PUT/DELETE), nooit bij GET.$view->filter['uid']->value moet
array('value' => $uid) zijn, niet array($uid) — de foute vorm
faalt stil (geen filter toegepast) i.p.v. een error te geven.Home-prefixed componenten (HomeUitgaantabelKaartComponent
e.d.) zijn een bewuste kopie van PUitgaanSliderComponent/
UitgaantabelKaartComponent + een eigen cityid-loze API-call — geen
dode code, niet meenemen in opschoonacties.lib/ doorzocht) — elke
FutureBuilder die alleen op !snapshot.hasData checkt, blijft bij
een mislukte call voor altijd op de laadspinner hangen. Ga er dus
niet van uit dat er ergens al een werkend voorbeeldpatroon staat om
te kopiëren — dit moet nog van de grond af ontworpen worden (zie
P0-taak in TASKS.md).