Website van Edano
  • Astro 45.2%
  • TypeScript 39.6%
  • JavaScript 10.6%
  • CSS 3.2%
  • Shell 1%
  • Other 0.4%
Find a file
Bram Buijs 807a63818e
Some checks are pending
build-and-push / check (push) Waiting to run
build-and-push / image (push) Blocked by required conditions
Het cijfer terug op de homepage, zonder de onderbouwing
Het hele blok was naar /about verhuisd en daarmee raakte de homepage
haar hardste argument kwijt. Dat argument is het getal, niet de drie
alinea's eronder.

Dus hier het getal, de conclusie erbij ("niet een revolutie, een grotere
kaart") en een link naar de cijfers erachter. De onderbouwing en de bron
blijven op /about, want dezelfde zinnen op twee pagina's is precies wat
we niet doen. De slotregel over de grotere kaart staat nu alleen nog
hier, niet meer daar.

432px in plaats van de 729px die het blok eerst was.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014d9igBWXLHnf4tgYJ5cuFw
2026-08-25 00:08:45 +02:00
.forgejo/workflows docs: de dev-omgeving is weg, lokaal draaien is de controlestap 2026-08-21 00:19:19 +02:00
public Sextant in de logorij 2026-08-24 22:53:56 +02:00
scripts /how-it-works gaat op in /governance 2026-08-24 18:46:08 +02:00
src Het cijfer terug op de homepage, zonder de onderbouwing 2026-08-25 00:08:45 +02:00
.dockerignore feat: eerste versie van de edano-wervingssite 2026-08-18 23:57:20 +02:00
.gitignore feat: eerste versie van de edano-wervingssite 2026-08-18 23:57:20 +02:00
astro.config.mjs Ritme op de pagina's, en de SEO die bij een open site hoort 2026-08-21 15:59:44 +02:00
BEELD.md Een positieve kop op /customers, en een lijst met het beeld dat ontbreekt 2026-08-24 17:08:43 +02:00
Dockerfile feat: een inschrijving kan niet meer verloren gaan 2026-08-19 22:06:24 +02:00
package-lock.json chore: ongebruikt lettertype eruit 2026-08-20 15:33:33 +02:00
package.json Mist is een kaartkleur, geen bandkleur 2026-08-21 17:44:23 +02:00
README.md Een positieve kop op /customers, en een lijst met het beeld dat ontbreekt 2026-08-24 17:08:43 +02:00
tsconfig.json feat: eerste versie van de edano-wervingssite 2026-08-18 23:57:20 +02:00

edano.eu

De website van edano (European Digital Autonomy Network), een Europese IT-cooperatie in oprichting.

Doel van de site: leden werven. Daarnaast drie nevenpaden: klanten, partners en investeerders. Alles wat niet bijdraagt aan een ingevulde inschrijving is bijzaak.

Meedoen

Je hebt Node 22 nodig. Verder niets: geen database, geen externe dienst.

git clone https://forgejo.bb-open.com/bb-open/edano-web.git
cd edano-web
npm install
npm run dev            # http://localhost:4321

Dat is genoeg om de hele site te zien, in beide talen, inclusief het inschrijfformulier. Zonder Odoo-configuratie komt een inschrijving in .dev-leads.jsonl in de projectmap terecht; die staat in .gitignore.

Voordat je iets voorstelt

npm run check          # types in .astro EN .ts, plus de contrastcontrole
npm run build          # dezelfde build als de CI draait
npm run check-promises # tegen een draaiende server; zie hieronder

npm run check is geen formaliteit. npm run build compileert .astro- bestanden wel maar rendert ze niet, en tsc kijkt alleen in .ts. Een verwijzing naar een contentveld dat niet meer bestaat viel daardoor door beide mazen heen en gaf pas in de browser een serverfout. astro check kijkt wel in de expressies binnen .astro en vangt dat. De CI draait het en blokkeert de build erop.

Een wijziging voorstellen

  1. Vertak van dev, niet van main.
  2. Push je branch en open een pull request naar dev.
  3. Bekijk het lokaal met npm run dev. Dat is de plek waar we ernaar kijken.
  4. Van dev naar main gaat naar edano.eu. Dat is een aparte, bewuste stap.

main krijgt nooit rechtstreeks een commit. Alles gaat eerst naar dev; pas als het daar goed is gaat het via een merge naar main en dus naar productie. Ook kleine wijzigingen, ook als het duidelijk klopt: een uitzondering maken haalt de hele reden weg dat die scheiding er is.

De volgorde bij een uitrol:

git switch dev
# werken, committen, lokaal nakijken
git push origin dev
git switch main && git merge --ff-only dev && git push origin main
# scripts/release.sh <versie>, image bumpen in de platform-repo

Er stond een ontwikkelomgeving op demo.website.edano.eu. Die is weggehaald: iedereen draait de site lokaal, dus hij voegde niets toe en kostte wel een pod. De controlestap is daarmee npm run dev op je eigen machine.

Kleine tekstwijzigingen hoeven geen uitleg. Voor alles wat kleur, contrast of opmaak raakt: lees eerst de kop van src/styles/global.css. Daar staat per kleur waarvoor hij is en wat hij meet, en die afspraken worden bewaakt door scripts/check-contrast.mjs.

De omgeving

edano.eu is de enige draaiende omgeving; hij volgt main. Wat hij doet hangt volledig aan een handvol variabelen, en dat is bewust: zo kan er een tweede omgeving naast zonder dat er een regel code verandert.

SITE_URL              waar de site zichzelf canoniek verklaart
SITE_INDEXABLE        noindex-meta, robots.txt en X-Robots-Tag tegelijk
PLAUSIBLE_SCRIPT_URL  meting; niet gezet is niet meten
LEADS_DIR             waar inschrijvingen worden weggeschreven
ODOO_URL/DB/USER/API_KEY

Zo hoort het te gaan: een push bouwt een image (.forgejo/workflows/build.yml), Flux ziet de nieuwe tag en zet hem in de platform-repo. main levert main-<run>, dev levert dev-<run>; twee prefixen zodat een dev-image nooit op productie kan belanden.

Dat werkt nu nog niet, maar anders dan hier eerder stond. Er IS een runner met het label nixos: op 21 augustus 2026 zijn zestien runs opgepakt. De job check slaagde elke keer, dus de runner haalt de repo op, draait nix en voert npm run check uit. De job image faalde elke keer.

Gemeten aan de registry: er staat geen enkele tag met de prefix main- of dev-. Alle zeventien tags zijn met de hand gepusht via scripts/release.sh. Hetzelfde geldt voor bb-open/sextantfleet.com, waar deze workflow vandaan komt: ook daar nul CI-tags. Deze workflow heeft dus in geen enkele repo ooit een image gepusht.

De waarschijnlijke oorzaak staat in de kop van het workflowbestand zelf: inloggen op de registry gaat met het token dat Forgejo per run meegeeft, en dat token mag daar kennelijk niet pushen. De uitweg die er ook al staat is REGISTRY_USER en REGISTRY_TOKEN als repo-secrets zetten; die krijgen voorrang. Zonder de logs van een run is dat een vermoeden en geen diagnose.

Sinds 21 augustus 16:17 is er niets meer gedraaid, terwijl er daarna tientallen keren is gepusht. Ook de job die het wel deed staat dus stil.

Tot dit klopt gaat uitrollen met de hand, en dat werkt.

Tot er een runner is, gaat uitrollen met de hand:

scripts/release.sh 0.5.2

Dat draait de controle, bouwt, doet een rooktest over alle routes, pusht, en drukt de regel af die in de platform-repo moet. De digest komt daarbij uit de registry en niet uit podman: die twee wijken van elkaar af, en met de verkeerde waarde blijft de pod in ImagePullBackOff hangen zonder dat er iets mis lijkt.

Wat waar staat

src/content/            teksten. en.ts en nl.ts, met de gedeelde vorm in types.ts
src/lib/nav.ts          de navigatie, gedeeld door kop en voet
src/lib/site.ts         SITE_URL en de indexeringsschakelaar
src/lib/analytics.ts    Plausible via onze eigen herkomst
src/lib/leads.ts        waar een inschrijving landt: eerst schijf, dan Odoo
src/lib/signup.ts       validatie en verwerking van de POST
src/lib/odoo.ts         JSON-RPC-client voor Odoo CRM
src/components/         Header, Footer, HomePage, InfoPage, TrackPage, Logo
src/middleware.js       CSP, securityheaders, rem op POST, canonieke host
src/styles/global.css   de kleurtokens, met de gemeten contrasten erbij
scripts/check-contrast.mjs  rekent elke kleurcombinatie na
scripts/check-promises.mjs  toetst wat de site over zichzelf belooft
scripts/check-style.mjs     meet de stijlgids na op de gerenderde pagina's
scripts/release.sh          bouwen, testen, pushen zolang er geen CI-runner is
scripts/replay-leads.mjs    inschrijvingen die Odoo niet haalden alsnog aanbieden
scripts/build-press-logos.mjs  de logobestanden voor de persmap
scripts/build-images.mjs    de beeldvarianten: drie formaten, vijf breedtes
scripts/build-stats.mjs     haalt het Plausible-script op naar public/js
BEELD.md                    welk beeld er nog ontbreekt, met de opdracht erbij

Vier sporen

members, partners, customers en investors. De sleutels staan in TRACK_KEYS (src/content/types.ts) en sturen de routes, de navigatie, de kaarten op de homepage en het formulier tegelijk. Eén sleutel toevoegen raakt dus alle vier.

Daarnaast vier uitlegpagina's: /why, /how-it-works, /governance, /about. Die hergebruiken inhoud die ook op de homepage staat; er wordt daar niets nieuws beweerd.

Een inschrijving raakt nooit kwijt

De volgorde is: eerst naar schijf, dan pas naar Odoo.

Lukt het wegschrijven niet, dan ziet de bezoeker een fout. Dat is de enige situatie waarin we niets kunnen garanderen. Lukt Odoo niet, dan ziet de bezoeker gewoon de bedankpagina, want zijn inschrijving staat veilig. De fout gaat naar het log en scripts/replay-leads.mjs biedt die regels later opnieuw aan.

Andersom was het eerst, en toen betekende een Odoo-storing van vijf minuten dat elke inschrijving in die vijf minuten weg was.

Weringen tegen misbruik: een honeypot-veld, een ondertekende tijdstempel en een teller per IP in het geheugen. Geen captcha, want dat kost een externe bron en botst met het hele uitgangspunt van de site.

Geen externe bronnen

De CSP staat op 'self'. Geen CDN, geen webfont van een ander domein, geen tracker, geen captcha. Dat is niet alleen hygiene: een site over Europese digitale onafhankelijkheid die scripts van derden inlaadt, weerlegt zichzelf.

Daarom zijn ook de lettertypen zelf gehost, en loopt Plausible via eigen routes (/js/stats.js, /api/event) in plaats van rechtstreeks vanuit de browser.

Er is wel JavaScript, en het staat allemaal in losse bestanden omdat inline script door de CSP wordt geblokkeerd:

public/js/counters.js   telt de cijfers op de homepage omhoog
public/js/menu.js       sluit de menu's bij een klik ernaast en bij Escape
src/pages/js/stats*     Plausible, alleen als PLAUSIBLE_SCRIPT_URL gezet is

De site werkt zonder al deze bestanden. Ze voegen gedrag toe, geen inhoud.

npm run check-promises toetst dit tegen een draaiende server: geen enkele route zet een cookie, geen enkele pagina haalt een subresource van een ander domein, en de CSP noemt geen externe herkomst. Dat zijn geen stijlregels maar uitspraken die in de privacyverklaring staan, en een juridische uitspraak die stilletjes onwaar wordt is erger dan geen uitspraak. scripts/release.sh draait het tegen het gebouwde image, dus tegen wat er echt op edano.eu komt.

Merk

Merkgids v3.0 is leidend, behalve de kleuren: die waren toen nog niet bepaald. Het palet staat in src/styles/global.css, met per kleur waar hij voor is en de gemeten contrastwaarde erbij. /styleguide zet alle merkbeslissingen naast elkaar; die pagina staat niet in de navigatie en blijft ook na livegang uit de index.

Twee regels die niet ter discussie staan, allebei bewaakt door npm run check-contrast:

  • Op donker is alle tekst vol wit. Gedempt wit haalt het op de lichte kant van het verloop niet (3.76).
  • Bij een verloop telt de slechtste tussenstop, niet de uiteinden.

Het logo is vector, geen tekst. Als tekst zou het afhangen van of het font laadt. Het vlak heeft de gehaakte e UIT GESTANST met een masker, dus er is geen apart bestand voor een lichte variant: het vlak krijgt currentColor en door de uitsparing schijnt de ondergrond. In de kop loopt dat vlak tot de bovenrand van de pagina (flushTop), zoals op rijksoverheid.nl.

Nog te doen

  • Odoo is nog niet gekoppeld. Zonder de vier ODOO_*-variabelen schrijft de site elke inschrijving naar LEADS_DIR en logt [lead][ODOO-FAILED]; de bezoeker ziet gewoon de bedankpagina, er gaat niets verloren. Zodra de koppeling staat haalt npm run replay-leads de wachtrij op. Draait Odoo buiten het cluster, dan moet dat adres bij de egressregel in namespace.yaml, anders faalt de koppeling stil.
  • my.edano.eu serveert nog de standaard Odoo-pagina. De ledeningang in de voet wijst er al naartoe.
  • Cookies, Terms en Security ontbreken nog naast /privacy.
  • De cijfers 13+, 10+ en 4 zijn door de eigenaar bevestigd als "vooralsnog prima", maar staan wel op een geïndexeerde site.
  • Er is geen CI-runner met het label nixos. Tot die er is gaat uitrollen met de hand via scripts/release.sh.

Afgedaan sinds de eerste versie: de privacyverklaring is ingevuld en SITE_INDEXABLE staat aan, het beeld staat op de site, en het echte logo heeft de gegenereerde plaatsvervanger vervangen.