Werk uitsluitend binnen deze projectdirectory
(/home/bob/Projects/ff-app/uitgaanskrant-1qhvtd). Niet daarbuiten
zoeken of scannen (bijvoorbeeld geen find / over het hele
bestandssysteem) — scope alle bestandsoperaties tot dit project.
Bob bespreekt elke taak in een nieuwe, aparte chat. Dit bestand en
TASKS.md zijn daarom het geheugen tussen sessies — er is geen eerdere
conversatie om op terug te vallen.
Vaste afsluitroutine, aan het eind van elke sessie/taak:
TASKS.md bij: een afgeronde taak wordt volledig verwijderd
uit de lijst (niet gearchiveerd in een "Afgerond"-sectie — dat is
onnodige context/kosten voor toekomstige sessies). Zorg dat elke
resterende open taak zelfstandig te begrijpen is (concreet, met
bestandspad/context) zonder de chat gelezen te hebben waarin hij
ontstond.CLAUDE.md) bij: alleen toevoegen als het
een blijvend herbruikbaar inzicht is (een conventie, een
architectuurkeuze, een bekende valkuil/bug-patroon) dat een latere
sessie anders opnieuw zou moeten uitzoeken. Geen sessieverslag,
geen changelog van wat er gedaan is, geen herhaling van
redeneringen. Ruim verouderde/dubbele info op in plaats van
eronder te plakken — dit bestand moet klein en scanbaar blijven..md-bestanden direct (geen
FlutterFlow-export nodig voor pure documentatiewijzigingen — alleen
de export/build-cyclus hieronder draaien als er ook echt
app-code is gewijzigd).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/) — en ook die voert de gebruiker in via de
Custom Code-editor op de FlutterFlow-website, niet door hier
rechtstreeks bestanden te bewerken.lib/flutter_flow/* e.d.)
worden bij de volgende export/sync vanuit FlutterFlow overschreven.
Zulke bestanden hier aanpassen is dus niet duurzaam.flutter analyze) — maar
vertaal het eindresultaat naar concrete, stapsgewijze instructies
voor wat de gebruiker in de FlutterFlow-builder (of de Custom
Code-editor) moet doen, of voer het zelf uit via browser-automation
(zie hieronder). Ga er niet van uit dat een lokale bestandswijziging
behouden blijft.git commit.mcp__claude-in-chrome__* (Bob's eigen, gedeelde Chrome),
niet de in-app Browser pane — dat is de afgesproken tool voor
builder-automation.resize_window e.d.) — dit is
Bob's eigen gedeelde vensters. Als iets buiten beeld valt, meld dat
en vraag het aan Bob i.p.v. zelf te resizen.git
diff ziet van jezelf komt — check eerst of hij iets claimde
("dat regel ik zelf") voordat je het overschrijft.De projectdirectory zelf is een schone git-repo met origin op
ssh://gogs.digitalforce.tv:2222/Uitgaanskrant.com/flutterflow.git,
branch master. Dit is een eigen repo van de gebruiker, los van de
grotere/rommelige repo die hoger in de mappenstructuur staat (die met
AndroidStudioProjects, Flutter-SDK-installaties e.d.) — commits en
pushes horen hier, in de projectdirectory zelf.
Vaste workflow na elke afgeronde taak (staand akkoord, geen aparte
bevestiging per keer nodig): niet los flutterflow export-code
draaien, maar het bestaande script gebruiken:
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. De Bash-tool draait
niet-interactief, dus ~/.bashrc (waar fvm/flutterflow normaal
op PATH komen) wordt niet geladen. Zonder deze prefix faalt het
script stil met "fvm: command not found" / "Prerequisites not met,
skipping execution" — geen harde error, dus makkelijk te missen.run_in_background: true. Volg de output tot minimaal
"All done!" (export gelukt) én idealiter een succesvolle app-launch
op de emulator (Launching lib/main.dart..., geen nieuwe
EXCEPTION CAUGHT BY RENDERING LIBRARY t.o.v. bekende issues in
TASKS.md) voordat je verder gaat.Daarna automatisch:
git status --short bekijken, dan git add — niet blind -A.
Voeg alleen daadwerkelijke FlutterFlow/app-wijzigingen toe (lib/,
android/, ios/, pubspec*, .gitignore e.d.). Sluit .claude/
uit (staat in .gitignore) — dat is sessiestate van Claude Code,
geen app-code. Wijzigingen die niet van jezelf zijn (Bob's eigen
concurrent werk) horen gewoon mee in dezelfde commit — dit is één
gedeeld project.git commit met een duidelijke boodschap.git push (of git push -u origin master als tracking nog niet
staat).Valkuil: flutterflow export-code overschrijft .gitignore bij
elke export terug naar FlutterFlow's eigen standaardversie. Voeg dus
na elke export, vóór je staged, deze regel weer toe aan .gitignore
als hij ontbreekt:
# Claude Code session state (not app code)
.claude/
(CLAUDE.md zelf overleeft een export altijd — alleen bij een volledig
verwijderde en opnieuw gepulde projectmap zou het verdwijnen. Check
voor de zekerheid toch even of het bestand er nog is.)
Voordat je aan een niet-triviale taak begint (een bugfix, een nieuw patroon, een integratie): zoek eerst kort op internet naar bestaande oplossingen/patronen voordat je het zelf helemaal uitvindt via trial-and-error in de builder. Geldt niet voor triviale/mechanische herhaling van een patroon dat al bevestigd werkt (zie hieronder).
Geneste "Set Variable"-dialoog kan lijken vast te zitten. Bij het
instellen van een conditie (ConditionalBuilder, Visibility →
Conditional) op een niet-triviaal type (JSON Path, API-response-veld)
opent een tweede dialoog bovenop de eerste. Confirm/Cancel op die
binnenste dialoog reageren soms niet zichtbaar. Twee bekende oorzaken,
in volgorde van proberen:
navigate naar dezelfde URL); de wrap blijft staan, de
half-ingevulde conditie moet opnieuw.Component Name kan per ongeluk overschreven worden. Vlak na paginanavigatie kan een klik bedoeld voor het "Search properties..." veld in plaats daarvan op het Component Name-veld landen (focus/ z-order race condition), en typen hernoemt dan stilletjes het hele component. Mitigatie: na een click-before-type altijd eerst een screenshot om focus te bevestigen, zeker vlak na navigatie. Herstel: rechtsklik component in de zoekresultatenlijst → "Rename Component".
Rechterpaneel kan te breed zijn voor de viewport. Sommige
controls (Expansion segmented control, Visibility → Conditional
expression builder) renderen soms deels buiten beeld — dit is geen
resize_window-probleem (zie hierboven: niet zelf resizen). Na 1-2
bevestigde pogingen stoppen en aan Bob vragen.
Patroon: lege/ontbrekende afbeeldings-URL laten 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 wordt gedaan, dus errorWidget/
"Show Error Image on Failure" vangt dit niet (dat vangt alleen
échte laadfouten zoals 404's). Werkende fix, toegepast op 9 van de ~10
bekende instanties (zie TASKS.md):
$[0].logo) → operator "Is Set".null als lege string (bevestigd via
in-builder tooltip: "if the resulting value is null or empty") —
géén ConditionalBuilder nodig. Werkt hier alleen niet voor
Image-widgets met Image Type: Network, omdat er nog geen gehoste
fallback-afbeeldings-URL bestaat in dit project. Mocht die er ooit
komen (bv. een default-logo op de FlutterFlow-CDN of Drupal-server):
gebruik dan Default Variable Value + "Show Error Image on Failure"
i.p.v. ConditionalBuilder — sneller te bouwen.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 (zelfde
stijl als de gedeelde header), geen losse styling nodig. Werkt niet op
iconen die embedded zitten als suffixIcon van een TextFormField
(bv. Login-pagina's wis-/toon-wachtwoord-iconen — geen losse
wrapbare tree-node).
API-call headers: check op hardcoded literals i.p.v. [varname]
templates. Als een API-call via curl wél werkt maar vanuit de app/
Response & Test-panel niet, controleer het Headers-tabblad van de
call-configuratie — een handmatig ingeplakte testwaarde (bv. een
Cookie-header) kan per ongeluk blijven staan i.p.v. de
[sessionname]=[sessionid]-template. 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.