SolidDeploy
Kennisbank

Zet je cijfers op een scherm naast je laptop

Een los AMOLED-schermpje van een paar tientjes dat je bol.com-omzet, je Shopify-omzet, je advertentiekosten en je Claude Code-verbruik laat zien. Claude Code bouwt het; jij plakt de prompts.

een avond bouwen · 16 min lezen · voor ondernemers die met Claude Code werken

Geschreven door Job Lenselink Oprichter van SolidDeploy · · bijgewerkt
Wat je hier meekrijgt
  • De complete startprompt waarmee Claude Code de firmware en de service op je Mac bouwt
  • Losse prompts voor je Claude-verbruik, je bol.com-cijfers en je Shopify-cijfers, met periodekiezer
  • Zeven valkuilen die geen foutmelding geven, en wat je eraan doet
  • Het patroon om er in één gesprek je eigen app bij te bouwen

Een los AMOLED-schermpje van een paar tientjes, naast je laptop, dat je bol.com-omzet, je Shopify-omzet, je advertentiekosten en je Claude Code-verbruik laat zien. Je schrijft geen regel code: Claude Code bouwt de firmware en de koppelingen, jij plakt de prompts en zegt wat erop moet.

Dit document is het complete draaiboek. De prompts staan er letterlijk in, inclusief de valkuilen die anders een avond kosten.

Wat er aan het eind op je bureau staat: een schermpje met een menu van apps, dat elke minuut ververst. Vier stuks om mee te beginnen.

  • Claude, met je verbruik van het vijf-uursvenster en het weekvenster
  • bol.com, met omzet, advertentiekosten, TACOS en ROAS per periode
  • Shopify, met dezelfde getallen uit je eigen webshop
  • Eén die jij zelf bedenkt, met het patroon uit dit document

Waar je hem koopt

Twee routes naar hetzelfde schermpje. De eerste is sneller, de tweede staat los van je bureau.

WaarWat je krijgtPrijsLevertijd
AmazonHet bordje zelf. Hangt aan de USB-kabel van je Mac, en die kabel voedt hem ookrond de 40 euroeen paar dagen
AliExpressDe uitvoering met accu erbij, dus draadloos neer te zetten. Wel opladenrond de 50 eurotwee tot drie weken

Waar je op let bij het bestellen: het formaat moet 2.16 zijn en er hoort Touch bij te staan. Waveshare maakt deze reeks in meerdere maten, met en zonder aanraakscherm; de kleinere hebben een andere driver, waardoor de prompts hieronder niet meer kloppen.

Kom je toch uit bij de uitvoering zonder aanraakscherm, dan werkt dit draaiboek nog steeds. De startprompt schrijft voor dat je met de twee knoppen door alle schermen moet kunnen, juist voor het geval aanraken hapert. Je mist alleen het tikken.

De Amazon-link is een affiliate-link: koop je het schermpje daarmee, dan krijgen wij een kleine vergoeding van Amazon. Voor jou verandert de prijs niet, en we raden het ding aan omdat we er zelf mee werken.

Wat er op zit

Het is een Waveshare ESP32-S3-Touch-AMOLED-2.16: een compleet apparaatje waar scherm, aanraakglas, wifi, bluetooth en een accu-aansluiting al op zitten. Geen soldeerwerk, geen losse onderdelen.

OnderdeelWat het is
Scherm2,16 inch AMOLED. Zwart is hier echt zwart, en daarom leest een donkere interface zo rustig
AanraaklaagCST9220. Je tikt en scrolt zoals op een telefoon
Bluetooth LEDe verbinding met je Mac. Geen wifi-netwerk, geen server, geen cloud
KnoppenTwee stuks, altijd de terugval als aanraken hapert. Bewust niet weggelaten

Verder nodig:

  • Een USB-C-kabel die data doorgeeft. Een goedkope laadkabel die alleen stroom geeft is de meest gemaakte fout: je computer ziet het apparaat dan simpelweg niet.
  • Een Mac met Claude Code. Dit draaiboek gaat uit van macOS, omdat de bluetooth-koppeling en het uitlezen van je Claude-verbruik daarop leunen. Op Linux werkt het ook, maar dan wijkt de stap over je Claude-verbruik af.
  • Een accu is optioneel. Bij de AliExpress-uitvoering zit er een bij; koop je het kale bordje, dan kun je er later een klein lipo-accu'tje op prikken. Aan een USB-lader werkt hij trouwens net zo goed los van je Mac, want de data gaat over bluetooth.

Voorbereiden

Twee dingen moeten kloppen voordat Claude Code aan de slag kan: een plek voor het project, en een bouwomgeving voor het schermpje. Die laatste heeft een eigen Python nodig, want de toolchain voor deze chip draait niet op de Python die standaard op je Mac staat.

mkdir -p ~/projects/bureaumonitor && cd ~/projects/bureaumonitor

brew install python@3.12
python3.12 -m venv ~/.pio-venv312
~/.pio-venv312/bin/pip install platformio

node -v   # 20 of hoger; anders: brew install node

Sluit het schermpje met de USB-kabel aan en controleer dat je Mac hem ziet. Verschijnt er niets, probeer dan een andere kabel voordat je verder gaat.

ls /dev/cu.usbmodem*
/dev/cu.usbmodem21101

Start daarna Claude Code in die map met claude.

De startprompt

Dit is de belangrijkste stap. De prompt hieronder beschrijft het apparaat, de architectuur en de valkuilen. Plak hem in Claude Code en laat hem lopen. Hij bouwt de firmware, de achtergrondservice op je Mac en de bluetooth-koppeling ertussen.

Ik heb een Waveshare ESP32-S3-Touch-AMOLED-2.16 op USB aangesloten. Bouw hiervoor
een bureaumonitor: een schermpje met een menu van apps, gevoed door een klein
Node-programma op deze Mac dat elke minuut data over Bluetooth LE stuurt.

Hardware (staat in de Waveshare-documentatie, verifieer het daar):
- CO5300 AMOLED 480x480 via QSPI, touch CST9220 op I2C, twee knoppen.
- Gebruik alleen Waveshare's eigen documentatie en voorbeelden voor de pinout en
  de drivers. Zoek de juiste GPIO-nummers daar op, gok ze niet.

Firmware:
- PlatformIO met het pioarduino-platform (arduino-esp32 core 3.x). Dat vereist
  Python >= 3.10, dus gebruik ~/.pio-venv312/bin/pio. Zoek de actuele
  platform-release op en zet die in platformio.ini.
- Arduino_GFX voor het scherm, LVGL 9 voor de interface.
- Een BLE GATT-peripheral met een eigen service-UUID en een schrijfbare
  characteristic die platte JSON ontvangt.
- Een startscherm met app-iconen (rooster van tegels, label eronder, home-balk
  onderin), en per app een eigen scherm met een titelbalk en een terugknop.
  Tikken opent een app; de home-balk en de BOOT-knop gaan terug; de andere knop
  stapt door naar het volgende scherm. Navigatie moet altijd ook zonder
  aanraakscherm werken.
- Donkere interface: zwarte achtergrond, inhoud in afgeronde kaarten, per rij
  label links en waarde rechts. Bak een eigen lettertype in via lv_font_conv;
  de ingebouwde LVGL-fonts kennen geen euroteken.

Node-service op de Mac:
- TypeScript, draait onder pm2, pusht elke 60 seconden.
- Bluetooth via @abandonware/noble. macOS vraagt eenmalig toestemming voor
  Bluetooth; leg in de README uit waar je die aanzet.
- Elke databron is een eigen module met een simpele functie die getallen
  teruggeeft. Faalt een bron, dan stuur je -1, nooit 0.

Vier dingen die je moet respecteren, ze zijn duur betaald:
1. Een BLE write-without-response wordt op macOS rond 182 bytes STIL afgekapt.
   Splits de data daarom in meerdere kleine frames en parse in de firmware per
   sleutel, zodat elk frame op zichzelf geldig is. Een scherm erbij = een frame
   erbij, nooit een frame groter maken.
2. Zet de BLE-init in setup() VOOR de LVGL-init. LVGL's geheugenpool is
   statisch; is die te groot of te vroeg, dan start de radio niet meer op
   ("nimble host init failed") terwijl al het andere normaal lijkt. Houd de pool
   klein (rond 72 kB) en bouw maar EEN scherm tegelijk: bouw een scherm bij het
   openen en gooi het vorige weg.
3. Gebruik geen clip_corner en geen transform of opacity op een container.
   LVGL rendert die dan via een tussenlaag die hier niet in het geheugen past;
   het scherm blijft dan stil hangen. Zet LV_USE_LOG op warn zodat zulke
   fouten zichtbaar zijn.
4. Het paneel adresseert kolommen per twee. Snap elk te hertekenen gebied naar
   de volle schermbreedte en een even hoogte, anders staat de tekst scheef en
   trilt hij bij elke update.

Bouw daarnaast twee hulpmiddelen:
- Seriële commando's over USB (115200) om te navigeren en te testen: home, next,
  app <n>, info. Een regel met JSON wordt als datapakket verwerkt.
- Een "shot"-commando dat het scherm als base64 over serieel dumpt, plus een
  Python-scriptje dat daar een PNG van maakt. Het paneel is niet uit te lezen,
  dus dit is de enige manier om te controleren hoe het er echt uitziet.

Begin met een leeg scherm dat "hallo" toont en flash dat eerst, zodat we weten
dat de toolchain klopt. Daarna pas de rest.

Wat je daarna hebt

Een schermpje met een leeg menu en een service op je Mac die nog niets zinnigs stuurt. De drie stappen hierna vullen dat. Elke app is steeds dezelfde drie onderdelen: een bron die getallen ophaalt, een frame dat ze verstuurt, en een scherm dat ze toont.

Je Claude-verbruik op het scherm

Claude Code werkt met twee vensters: een van vijf uur en een van zeven dagen. Hoe vol die zitten staat niet in een dashboard, maar in de antwoord-headers van een gewone API-aanroep. Eén minimale aanroep per minuut is genoeg om te weten waar je staat.

Dit werkt alleen met het token van je eigen Claude Code-installatie. Dat staat in je macOS-sleutelhanger en wordt door Claude Code zelf ververst. Met een losse API-sleutel krijg je andere limieten te zien, niet die van je abonnement.
Voeg een Claude-app toe aan de bureaumonitor.

De data: doe elke minuut de kleinst mogelijke /v1/messages-aanroep (max_tokens 1)
en lees het verbruik uit de ANTWOORD-HEADERS, niet uit de body. De headers
beginnen met anthropic-ratelimit-unified-: er zit een 5-uurs en een 7-daagse
benutting in, plus wanneer elk venster reset. Dump eerst eenmalig alle headers
van een echte aanroep en laat me zien welke je gaat gebruiken - namen kunnen
veranderen, dus baseer je op wat er echt terugkomt.

Voor de authenticatie: lees het OAuth-token uit de macOS-sleutelhanger
(het item dat Claude Code zelf aanmaakt) en lees het elke ronde opnieuw, zodat
een verversing vanzelf meekomt. Zet het token nergens in een bestand.
Is het token verlopen, log dan een duidelijke melding en sla die ronde over -
de andere apps moeten gewoon door blijven lopen.

Op het scherm: het percentage van beide vensters met een balk eronder, en hoe
lang het nog duurt tot elk venster reset. Daaronder het tempo: hoeveel procent
per uur je er nu doorheen gaat en hoe lang je op dat tempo nog hebt. Bereken dat
uit een klein rollend geheugen van de laatste twintig minuten; daalt het
percentage, dan is het venster gereset en begin je opnieuw.

bol.com-omzet en advertentiekosten, per periode

bol heeft twee gescheiden koppelingen: één voor je verkopen en één voor je advertenties. Je maakt de sleutels aan in je verkoopaccount, onder de instellingen voor API's. Je hebt er twee nodig: een voor de Retailer API (bestellingen) en een voor de Advertiser API (kosten en toegeschreven omzet).

GetalWat het isWaar het vandaan komt
OmzetWat je in de periode verkocht hebtRetailer API, bestellingen optellen
AdvertentiekostenWat je in dezelfde periode uitgafAdvertiser API, kosten per dag
TACOSKosten gedeeld door je totale omzet. Zegt hoeveel van alles wat je verkocht naar advertenties gingRekensom
ROASOmzet die aan advertenties toegeschreven is, gedeeld door de kostenRekensom

Stuur de periodes alle drie mee. Het scherm kan niets terugvragen aan je Mac; het ontvangt alleen. Wil je kunnen wisselen tussen vandaag, deze week en deze maand, stuur dan alle drie de sets in aparte frames. Het schermpje bewaart ze en wisselt bij een tik direct, zonder te wachten op de volgende ronde.

Voeg een bol.com-app toe aan de bureaumonitor, met een periodekiezer.

Databron 1 - Retailer API (bestellingen): som van de verkopen per periode.
Databron 2 - Advertiser API (advertenties): kosten en toegeschreven omzet per dag.
Ik zet de client id en secret van beide in ~/.bureaumonitor/bol.json. Lees ze
daaruit, nooit uit de code. Haal eerst de officiële documentatie van beide API's
op, laat me zien welke endpoints je gaat gebruiken, en doe pas daarna een echte
aanroep waarvan je de ruwe uitvoer aan mij laat zien. Verzin geen veldnamen.

Bereken per periode (vandaag / 7 dagen / 30 dagen):
- omzet in hele euro's
- advertentiekosten in hele euro's
- TACOS = kosten / omzet, in tienden van een procent
- ROAS = toegeschreven omzet / kosten, in tienden. Reken die ALTIJD over
  afgeronde dagen (dus zonder vandaag), want bol schrijft verkopen pas dagen
  later aan een advertentie toe. Zet op het scherm bij welke periode het hoort.
- de verandering ten opzichte van dezelfde periode ervoor, in hele procenten.
  Vergelijk vandaag met gisteren tot HETZELFDE tijdstip, anders staat de hele
  ochtend in het rood zonder dat dat iets zegt.

Stuur elke periode als een eigen frame (denk aan de bytegrens per write).
Op het scherm: bovenaan de omzet groot met een gekleurd label voor de
verandering, daaronder drie rijen: advertentiekosten, TACOS, ROAS. Bovenin de
app een keuze tussen Vandaag / 7 dagen / 30 dagen; die wisselt lokaal tussen de
al ontvangen frames, dus zonder te wachten op de volgende ronde.

Lukt een aanroep niet, stuur dan -1 en toon een streepje. Een storing mag er
nooit uitzien als een omzet van nul.

Shopify-omzet en advertentiekosten, per periode

Shopify is eenvoudiger dan bol: je maakt in je eigen winkelbeheer een custom app aan, geeft die leesrechten op bestellingen, en krijgt een token. Verder heb je niets nodig.

  1. Ga in je Shopify-beheer naar Settings, Apps and sales channels, Develop apps.
  2. Maak een app en geef hem de rechten om bestellingen te lezen.
  3. Installeer hem in je eigen winkel en kopieer het toegangstoken.
  4. Zet dat token in een bestand buiten je project, bijvoorbeeld ~/.bureaumonitor/shopify.json.

Advertentiekosten kent Shopify niet, dus daar zijn twee werkbare routes voor. De Meta Marketing API of Google Ads API is het meeste werk, maar loopt daarna vanzelf en per dag exact. Eén regel in een bestandje met je budget per dag is verrassend goed genoeg zolang je budget stabiel is, en in vijf minuten geregeld.

Voeg een Shopify-app toe aan de bureaumonitor, met dezelfde periodekiezer als
bol.com (vandaag / 7 dagen / 30 dagen).

Omzet: via de Shopify Admin API, bestellingen per periode optellen. Shop-domein
en token staan in ~/.bureaumonitor/shopify.json; lees ze daaruit. Let op de
paginering van de API - haal alle pagina's op, niet alleen de eerste, anders
klopt de omzet stilletjes niet op een drukke dag.

Advertentiekosten: die kent Shopify niet. Maak er een aparte bron van met
dezelfde vorm als de andere, en lees hem uit ~/.bureaumonitor/adspend.json
(bedrag per dag). Staat dat bestand er niet, stuur dan -1 en laat TACOS en ROAS
een streepje zijn met de tekst "geen advertentiebron gekoppeld". Bouw het zo dat
ik die bron later kan vervangen door de Meta- of Google-Ads-API zonder de app of
het scherm aan te passen.

Hergebruik alles wat de bol-app al heeft: dezelfde berekeningen, dezelfde
schermopbouw, dezelfde omgang met ontbrekende data. Als er code te delen valt
tussen de twee verkoopkanalen, deel die dan echt in plaats van te kopiëren.

Je eigen idee erop zetten

Hier wordt het leuk. Elke app is dezelfde drie stappen, en die zijn zo klein dat je in één gesprek van idee naar scherm gaat.

StapWat het isWat jij zegt
BronEen functie op je Mac die getallen teruggeeft. Een API, een database, een bestand, een script"Haal X op uit Y"
FrameEen eigen klein JSON-pakketje met korte sleutels dat over bluetooth gaat"Stuur ze mee in een eigen frame"
AppEen scherm met een icoon in het menu, dat die getallen toont"Toon het zo..."

Ideeën die goed werken op zo'n schermpje:

  • Openstaande facturen en wie er te laat is.
  • Voorraad die deze week op gaat.
  • Reviews of tickets die nog een antwoord van jou wachten.
  • Je omzetdoel van de maand als balk.
  • Wie er in je agenda staat en over hoeveel minuten.
  • Het aantal bezoekers dat nu op je site is.

De vuistregel: getallen waar je iets mee doet, niet getallen die je alleen leuk vindt. Een scherm dat je na een week niet meer aankijkt, heeft de verkeerde dingen erop staan.

Voeg een nieuwe app toe aan de bureaumonitor.

Naam: [bijvoorbeeld: Facturen]
Wat ik wil zien: [bijvoorbeeld: hoeveel er openstaat, hoeveel daarvan te laat
is, en het aantal facturen dat wacht]
Waar het vandaan komt: [bijvoorbeeld: de API van mijn boekhoudpakket / een CSV
in map X / een SQLite-database]
Het belangrijkste getal, dat groot bovenaan moet: [bijvoorbeeld: bedrag te laat]

Volg exact het patroon van de bestaande apps: een aparte bronmodule, een eigen
frame met korte sleutels binnen de bytegrens, en een app-bestand met een build-
en een tick-functie. Gebruik de bestaande bouwstenen voor kaarten en rijen, zodat
het scherm bij de rest past. Maak een icoon in dezelfde stijl als de andere.

Bij een storing -1 sturen en een streepje tonen, nooit een nul.
Laat me na het flashen een screenshot van het nieuwe scherm zien.

Zeven valkuilen die tijd kosten

Deze staan ook in de startprompt, maar het helpt als jij ze herkent wanneer het misgaat. Ze hebben allemaal gemeen dat er geen foutmelding komt.

SymptoomWat er aan de hand is
De helft van je data komt niet aan, of het scherm toont onzinJe pakketje is te groot. macOS kapt een bluetooth-write rond 182 bytes af zonder iets te zeggen. Splitsen in kleinere frames
Bluetooth start niet op, de rest werkt primaDe interfacebibliotheek heeft het geheugen ingepikt dat de radio nodig had. Kleinere geheugenpool, en de radio eerst starten
Het scherm bevriest halverwege een nieuw schermEr zit een afgeronde clipping of een transformatie op een container. De grafische laag probeert dan een tussenbuffer die niet past
Tekst staat scheef en trilt bij elke updateDit paneel adresseert kolommen per twee. Elk te hertekenen gebied moet op even pixels beginnen en eindigen
Losse tekens zijn lege blokjesHet lettertype op het apparaat kent alleen de tekens die je erin bakt. Een euroteken moet je expliciet meenemen
Alles werkt, maar er komt nooit data aanBluetooth-toestemming in de systeeminstellingen van je Mac. Je ziet er niets van; het blijft gewoon stil
Je Mac ziet het apparaat niet op USBNegen van de tien keer een laadkabel zonder datadraden

Draaiend houden

De service op je Mac moet blijven lopen, ook na een herstart. Daar is pm2 voor: die start hem opnieuw als hij omvalt en na het opstarten van je Mac.

npm install -g pm2
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup            # volg de regel die hij teruggeeft

pm2 logs bureaumonitor   # meekijken

Twee dingen om te weten voor later. Staat op je Mac de schijfversleuteling aan zonder automatisch inloggen, dan draait er na een herstart niets tot iemand inlogt; het schermpje staat dan op "wachten op host". En verander je later iets aan de interface, laat Claude Code dan altijd een screenshot maken na het flashen. Het is de goedkoopste manier om te zien of het klopt.

Wat het uiteindelijk is

Geen dashboard dat je moet openen, en geen melding die je stoort. Een klokje dat toevallig je bedrijf laat zien. Je kijkt ernaar als je toch al opkijkt, en de rest van de dag staat het er gewoon.

Loop je vast, of wil je dit met je eigen systemen doen in plaats van met de vier hierboven? Plan een gesprek; dan kijken we mee.

← Terug naar de kennisbank
Job Lenselink

Benieuwd of ons Automation Eco-System bij jouw bedrijf past?

In een vrijblijvend gesprek brengen we in kaart welke systemen jouw business nodig heeft.

Gratis 1-op-1 call met Job Lenselink