Eerste commit voor Helvoirt Gevelreiniging
This commit is contained in:
+188
@@ -0,0 +1,188 @@
|
||||
# Helvoirt Gevelreiniging — Architecture
|
||||
|
||||
Status: **marketing-pagina's LIVE + CMS-migratie loopt (16-06-2026) — morgen verder met live zetten.** Astro 6 + Emdash + Cloudflare, gemodelleerd naar `../exterios`. Live op **`https://helvoirt-gevelreiniging.mike-197.workers.dev`** (preview; echt domein nog niet gekoppeld). **Laatste deploy: version `f576e989`.** Live: homepage + `/diensten`-overzicht + 5 dienst-detailpagina's + `/over-ons` + `/contact` + **`/maastricht`** (locatiepagina) (onbekende slug → branded 404). `astro check` 0, axe 0 (kwaliteitsmeting van vóór de CMS-migratie). Wijzig uitsluitend in `C:\projects\dewebsmid\helvoirt`.
|
||||
|
||||
**CMS (emdash, geseed op remote D1):** SEO-partij beheert `paginas` (gewone pagina's, root-URL) + `locaties` (locatiepagina's, root-URL) + `site_settings` (NAW + site-brede SEO + GTM). Ingebouwde `pages`/`posts` verwijderd. Zie `CMS-SEO-handleiding.md`. **Bestaande pagina's worden "volledig naar CMS" gemigreerd** (klantopdracht), elk met de huidige tekst als fallback (site breekt nooit) + live sentinel-verificatie: **Over ons** (`over_ons` + `waarden`-repeater + foto's in mediabibliotheek), **Homepage-tekst** (`homepage` + werkwijze/reviews/FAQ-repeaters), **Contact** (`contact_page`) = KLAAR.
|
||||
|
||||
**Go-live code-laag AF + LIVE (17-06-2026, deploy `15e076ff`):** `robots.txt`, `sitemap.xml.ts` (vaste routes + live CMS-`paginas`/`locaties`; overschrijft emdash's eigen sitemap), `site:` in config, JSON-LD `HomeAndConstructionBusiness` + GTM-render + twitter/theme-color in `Base.astro`, `privacy`/`voorwaarden`-pagina's + footer-links, `lib/smtp.ts` + `api/contact.ts` (D1 `contact_submissions` + 2 mails), `plugins/smtp-email.ts` (magic-link) geregistreerd, `middleware.ts` (http→https/www→apex), `cloudflare-env.d.ts`. **Resteert:** externe input (secret `CONTACT_SMTP_PASS`, SEO-partij-`users`-rij, klantcontent, domein-DNS) + optioneel CMS-migratie Wave 3/2b, self-hosted fonts, echte OG-image. Zie `todo.md` §9/§12 + `newsite.md` §12.
|
||||
|
||||
---
|
||||
|
||||
## Wat is dit project
|
||||
**Helvoirt Gevelreiniging** — lokaal gevelreinigings-/renovatiebedrijf. Diensten: gevelreiniging + renovatie, voegwerk, dak reinigen + coating, schoorsteen-voegwerk, algemeen reinigen. Domein `helvoirtgevelreiniging.nl`.
|
||||
|
||||
**Register:** conversiegerichte marketing-site (doel: gratis-offerte-aanvragen). Volgt de blauw/petrol-palette van het zusterbedrijf `onderhoudsbedrijfvanhelvoirt.nl`. **Niet** de quiet-luxury van `../exterios`: hier zijn before/after, reviews en een dominante CTA juist gewenst. We hergebruiken wel de **technische** architectuur van exterios.
|
||||
|
||||
---
|
||||
|
||||
## Repo layout (huidige staat)
|
||||
|
||||
```
|
||||
C:\projects\dewebsmid\helvoirt\
|
||||
├── architecture.md ← dit document
|
||||
├── CLAUDE.md ← AI-assistent context (stack, IDs, regels, Vite-fix, status)
|
||||
├── todo.md ← bouwplan + status
|
||||
├── package.json ← Astro 6 + Emdash 0.1.0 + Cloudflare adapter
|
||||
├── tsconfig.json ← extends astro/tsconfigs/strict
|
||||
├── astro.config.mjs ← output:server, cloudflare adapter, react, emdash (d1/r2), Vite noDiscovery
|
||||
├── wrangler.jsonc ← worker "helvoirt-gevelreiniging", D1 (PLACEHOLDER id) + R2 bindings, nodejs_compat
|
||||
├── emdash-env.d.ts ← auto-gen types (door dev server)
|
||||
├── .env ← GEMINI_API_KEY (gitignored)
|
||||
├── input/ ← klant-assets (NIET in build)
|
||||
│ ├── Content.docx ← dienstenlijst + referentie-instructie
|
||||
│ └── foto's/ ← 6 echte werkfoto's (schoorsteen+lood, tuinmuur, voegwerk, bemost dak, dakreiniging, trap)
|
||||
├── public/
|
||||
│ ├── favicon.svg ← cyaan tegel + witte waterdruppel (merkmark)
|
||||
│ └── images/ ← WebP's + 768/1280/1920-srcset-varianten
|
||||
│ ├── hero-after.webp / hero-before.webp ← schone + (PIL-vergroende) gevel (before/after-paar; hero-before alleen via het ongebruikte BeforeAfter.astro; hero-after ook in dienst-galerijen)
|
||||
│ ├── hero-gevel.webp ← schone gevel (over-ons-hero + voegwerk-galerij)
|
||||
│ ├── dienst-{gevelreiniging,voegwerk,dakreiniging,schoorsteen,algemeen}.webp
|
||||
│ └── werk-1..6.webp ← echte input-foto's, geconverteerd
|
||||
├── scripts/
|
||||
│ ├── nano-banana-with-truststore.py ← Gemini beeldgeneratie (Windows cert-wrapper)
|
||||
│ ├── img-variants.py ← srcset-varianten (PIL)
|
||||
│ ├── degrade-before.py ← maakt hero-before.webp uit hero-after.webp
|
||||
│ ├── convert-input.py ← input-foto's → WebP
|
||||
│ └── screenshot-home.py / shoot-*.py / axe.py / contrast.py / touch.py ← QA/verificatie
|
||||
└── src/
|
||||
├── worker.ts ← re-export PluginBridge + Cloudflare handler
|
||||
├── live.config.ts ← emdashLoader() voor live content collections
|
||||
├── lib/img.ts ← buildSrcset + srcsetFor + IMG_WIDTHS (hero + dienst)
|
||||
├── lib/images.ts ← resolveCmsImage (Emdash image-veld → src/alt, met fallback)
|
||||
├── styles/tokens.css ← palette, type-scale, .btn-cta/.btn-outline/.btn-text, section-helpers, .reveal
|
||||
├── layouts/Base.astro ← header, drawer, prefooter-form, footer, sticky-CTA, reveal-IO, SEO-head
|
||||
├── components/
|
||||
│ ├── Hero.astro ← homepage-hero (tekst + werkfoto-collage)
|
||||
│ ├── BeforeAfter.astro ← herbruikbare voor/na-sleepvergelijker (range + :has-focus); ONGEBRUIKT (projecten geschrapt), bewaard als herbruikbaar component
|
||||
│ └── ContactForm.astro ← herbruikbaar offerte-formulier
|
||||
└── pages/
|
||||
├── index.astro ← homepage (alle secties inline)
|
||||
├── over-ons.astro ← over ons (hero + verhaal + 4 waarden + werkgebied)
|
||||
├── contact.astro ← contact (hidePrefooter + NAW + formulier, id="contact")
|
||||
├── diensten/index.astro ← diensten-overzicht (5 kaarten → detail)
|
||||
├── diensten/[slug].astro ← SSR dienst-detailsjabloon (5 slugs gevuld; onbekend → 404)
|
||||
├── werkgebied/index.astro ← werkgebied-hub (lijst gepubliceerde locaties → /<plaats>, anders pills)
|
||||
├── [...slug].astro ← root-router: locatiepagina (`locaties`) of CMS-pagina (`paginas`), beide op root, + branded 404
|
||||
└── api/contact.ts ← POST /api/contact (honeypot + time-trap + validatie)
|
||||
```
|
||||
|
||||
**Gebouwd deze ronde:** `seed/seed.json` (CMS-model), `lib/images.ts`, `pages/[...slug].astro` (root-router: locatie- én gewone CMS-pagina's op de root + branded 404), `pages/werkgebied/index.astro` (hub), `CMS-SEO-handleiding.md`. **Nog te bouwen:** `pages/{privacy,voorwaarden}.astro` (of als CMS-pagina), `pages/sitemap.xml.ts` (incl. CMS-`paginas`/`locaties`), `robots.txt`, JSON-LD, `DESIGN.md`. (Projecten geschrapt op klantverzoek.) Homepage-secties zijn nog inline in `index.astro`; extraheren naar herbruikbare componenten zodra de subpagina's ze delen.
|
||||
|
||||
---
|
||||
|
||||
## Stack
|
||||
|
||||
| Laag | Technologie | Detail |
|
||||
|---|---|---|
|
||||
| Framework | Astro `^6.1.2` | `output: "server"` (SSR) |
|
||||
| Adapter | `@astrojs/cloudflare` `^13.1.6` | Workers SSR; KV (`SESSION`) + Images auto-provisioned |
|
||||
| React | `^19.2.4` | voor Emdash admin-UI |
|
||||
| CMS | Emdash `^0.1.0` + `@emdash-cms/cloudflare` | admin `/_emdash/admin` (nog niet geseed) |
|
||||
| Database | Cloudflare D1 | `helvoirt-db` (WEUR) — `database_id` `0fb83f17-f91d-4910-ac8c-80f00569ce35`, aangemaakt |
|
||||
| Storage | Cloudflare R2 | `helvoirt-media` — aangemaakt |
|
||||
| Styling | scoped CSS + CSS vars | `tokens.css`, geen Tailwind |
|
||||
| Fonts | Archivo Expanded + Open Sans | Google Fonts |
|
||||
| Hosting | Cloudflare Workers | account `41972f4905f2c83f51111b80283e030b` |
|
||||
| Mail | Mailtrap | nog te configureren (todo §12) |
|
||||
|
||||
`astro.config.mjs`: `react()` + `emdash({ database: d1({binding:"DB",session:"auto"}), storage: r2({binding:"MEDIA"}) })`, `vite.ssr.optimizeDeps.noDiscovery`.
|
||||
|
||||
---
|
||||
|
||||
## Design-systeem (`src/styles/tokens.css`)
|
||||
|
||||
- **Strategie:** *committed* blauw/petrol. Eén familie draagt het ontwerp; cyaan is de accent-spaarzaamheid.
|
||||
- **Kleuren:** actie-blauw `#0069ff` / hover `#0055ce` (CTA, links), cyaan `#4ebfd9` + `#8fd9e8` (accent/labels), petrol `#1d4852` / diep `#15363d` (donkere secties, header, footer), off-white `#f6fafb` (page) / `#eef4f7` (soft) / `#fdfeff` (card), tint `#e3f6fd`, ink `#1f2a2e` / soft `#5b6a70` / line `#dce6eb`. Status/ster: `--c-on-error`, `--c-on-success`, `--c-star`. Neutralen getint (geen puur wit/zwart in surfaces).
|
||||
- **Typografie:** `--font-display` Archivo Expanded (700/800), `--font-body` Open Sans. Fluid `clamp()`-schaal.
|
||||
- **Knoppen:** `.btn-cta` (actie-blauw fill, wit, radius 8px), `.btn-outline`, `.btn-text` (pijl-link, action-deep). **Tapdoelen ≥44px.**
|
||||
- **Sectie-helpers:** `.section--paper / --soft / --tint / --petrol / --petrol-deep`.
|
||||
- **Motion:** `.reveal` IO-systeem (`.revealed` + `data-delay`) + varianten `.reveal--draw` (lijn tekent zich in vanaf links — tijdlijn) en `.reveal--stagger` (directe kinderen na elkaar omhoog, `--i`-index — werkgebied-pills + FAQ), ease-out-expo. Verder: sitebrede scroll-reveals op elke sectie, werkwijze-tijdlijn `.flow__line` die zich intekent terwijl de cijfers inploppen (`flow-num`), `:active`-indruk op `.btn-cta`/`.btn-outline`, offerteformulier-spinner (`aria-busy` → `cform-spin`) + geanimeerde succesmelding (`cform-success`), trage ambient gloed in de hero (`hero-glow`). `prefers-reduced-motion` overal gerespecteerd (transform/opacity-only).
|
||||
- **Contrast:** alle gemeten paren ruim WCAG AA; axe-core 0 violations.
|
||||
|
||||
> Een formele `DESIGN.md` is nog niet geschreven (de design-context staat in dit document + `CLAUDE.md`).
|
||||
|
||||
---
|
||||
|
||||
## Componenten & homepage-secties
|
||||
|
||||
**`Base.astro`** — solide **donkere petrol headerbalk** (altijd zichtbaar): merkmark (cyaan tegel + witte druppel-SVG) + "Helvoirt / Gevelreiniging", desktop-nav met cyaan-underline + Diensten-dropdown, klikbaar telefoonnummer (44px hit-area) en "Gratis offerte"-CTA; mobiele **drawer** (`inert` focus-trap + ESC); **prefooter** (`id="contact"`, petrol) met `ContactForm`; **footer** (petrol-deep); **sticky-mobile-CTA** die verbergt bij de prefooter; `.reveal`-IO + formulier-AJAX-JS; SEO-head (canonical/OG, `lang="nl-NL"`). `site_settings` via `getEmDashEntry` in try/catch → werkt vóór seed met fallbacks (telefoon/e-mail placeholder).
|
||||
|
||||
**`Hero.astro`** — **tekst links + foto-collage rechts** (Tailark hero-6 nagebouwd in Astro/scoped-CSS; `audit` 20/20 + `critique`-fixes; donker petrol, geen before/after-slider, **geen kicker**). Links (`.hero__inner`, z-3): Archivo-kop "Je gevel weer als nieuw." (**800**, wit `--c-on-dark`), sub, `.btn-cta` → `#contact` + onderstreepte tekstlink (taphit ≥44px), `.hero__points` (3 vinkjes) en een prominente `.hero__trust` (grote sterren + display-score "4,9 op Google"). Rechts (`.hero__gallery`, absoluut, z-1, `width: min(72%,1120px)`): `.hero__rail` met **3** staande `.hero__card`'s (`werk-1/3/5`: Voegwerk/Schoorsteen/Dakreiniging; breedte `clamp(200px,19vw,280px)`, verspringend via nth-child translateY, `--shadow-card-dark`, diepe `.hero__cap` bijschrift-overlay) die links **overlopen in het tekstblok**; `.hero__fade` (z-2, sterk links) laat ze wegvloeien in `--c-petrol-deep` (klantvoorkeur boven een rechts-uitgelijnde collage). Was 4 cards (incl. Metselwerk `werk-6`); op klantverzoek terug naar 3 — 4 was te druk — en de cards verbreed zodat ze de rechterzone blijven vullen. Cards laden kleine srcset-varianten (`werk-N-480/768.webp`); hover = subtiele image-zoom. Gestaggerde entrance + trage ambient gloed achter `prefers-reduced-motion`. Props: `subtitle`. **Mobiel** (≤900px): flex-kolom, tekst boven (`order:0`), rail als **swipebare scroll-snap-rail** eronder (`order:1`). Donkere overlays/scrims/schaduw via tokens (`--c-scrim-rgb`, `--c-petrol-deep-rgb`, `--c-brand-rgb`, `--shadow-card-dark`). NB: `hero-after/before/gevel.webp` nu ongebruikt op de homepage.
|
||||
|
||||
**`ContactForm.astro`** — offerte-formulier: naam (placeholder "Naam"), e-mail, telefoon, bericht + honeypot + time-trap. Eén instantie per pagina (prefooter OF /contact). Styling (`.cform*`) + AJAX-submit-JS globaal in `Base.astro`. Tijdens verzenden zet de JS `aria-busy` op de submitknop → pijl wisselt voor een spinner (`cform-spin`); de succesmelding komt geanimeerd binnen (`cform-success`).
|
||||
|
||||
**`index.astro`** secties (boven→onder):
|
||||
1. **Hero** (donker, tekst links + werkfoto-galerij rechts die links wegvloeit in de achtergrond; mobiel swipebaar. Geen before/after-slider).
|
||||
2. **Intro** (paper) — groot Archivo-statement + alinea + één inline meta-regel.
|
||||
3. **Diensten** (petrol-deep) — **uitklappende beeld-accordion**: 5 hoge foto-panelen, het paneel onder cursor/focus klapt open (grote foto + titel + tekst + "Bekijk"), de rest smalle stroken met verticale titel + "+"-indicator; blijft open om te lezen; mobiel = 5 gestapelde kaarten.
|
||||
4. **Werkwijze** (soft) — verbonden tijdlijn, 4 stappen, blauwe genummerde cirkels.
|
||||
5. **Bewijs** (paper) — asymmetrische galerij van de **echte** werkfoto's.
|
||||
6. **Reviews** (tint) — één uitgelichte quote + Google-score + 2 kleine (placeholder).
|
||||
7. **Werkgebied** (soft) — plaats-pills.
|
||||
8. **FAQ "Goed om te weten"** (paper) — 4 vragen vóór het formulier.
|
||||
9. **Prefooter** (globaal, petrol) — offerte-formulier.
|
||||
|
||||
**`api/contact.ts`** — POST: honeypot + time-trap (2s–6u) + per-veld validatie; honeypot/time-trap → silent 200; fouten → 422 `{errors}`. Nu `console.log` (Mailtrap-send = todo §12). `prerender = false`.
|
||||
|
||||
---
|
||||
|
||||
## Emdash datamodel (emdash — GESEED op remote D1; todo §3)
|
||||
**Bewust SEO-vriendelijk + simpel** ingericht zodat de externe SEO-partij zelf pagina's kan aanmaken/optimaliseren. Drie collecties (i.p.v. het volledige sectie-model):
|
||||
- **`site_settings`** (singleton, slug `main`): NAW (`phone`, `email`, `address`, `address_street`, `address_city`), `kvk`, `btw`, `whatsapp`, `werkgebied`, `openingstijden`, social-URL's, `google_reviews_url`, `overall_rating`, `logo`, `favicon`, `og_image`, **`meta_title`/`meta_description`** (site-brede SEO-fallback) en **`gtm`** (Tag Manager-ID).
|
||||
- **`paginas`** (gewone pagina's, `drafts/revisions/search`): `title` (H1), `intro`, `content` (portableText) + **SEO-groep** `meta_title`/`meta_description`/`canonical`/`og_image`/`noindex` + **`embed_code`** (rauwe HTML/script-embed, bv. cookieverklaring; `migrations/0013_paginas_embed.sql`). `[...slug].astro` rendert `embed_code` via `set:html` ZONDER sanitatie (PortableText/htmlBlock filtert `<script>` eruit; dit veld is de bewuste escape-hatch voor vertrouwde admins). Het script draait omdat het in de server-gerenderde HTML staat.
|
||||
- **`locaties`** (locatiepagina's per plaats, idem supports): `plaats`, `title` (H1, leeg = "Gevelreiniging in {plaats}"), `intro`, `content` (portableText) + dezelfde SEO-groep.
|
||||
|
||||
SEO-velden zijn **expliciet** gedefinieerd (geen impliciete emdash-`seo`-support) met nette NL-labels, zodat ze voorspelbaar zijn én door de routes worden uitgelezen. Image-velden via `resolveCmsImage` (`src/lib/images.ts`). PortableText render via `<PortableText value={…} />` uit `emdash/ui`. Geen `getStaticPaths()` (alles SSR).
|
||||
|
||||
### Pagina-migratie ("volledig naar CMS", klantopdracht) — collecties per pagina
|
||||
Elke bestaande pagina leest uit het CMS **met de huidige tekst als fallback** (de site breekt nooit, ook niet als een collectie leeg/onbereikbaar is). Toegevoegd via `migrations/*.sql` (gegenereerd door `scripts/gen-cms-sql.mjs` uit `scripts/cms-models/*`, die emdash's eigen tabelstructuur spiegelt; **geen search/FTS** op deze collecties). Repeaters = inline rijen (`validation.subFields`); image-rijen → aparte collectie (repeater kan geen image-subveld).
|
||||
- **`over_ons`** (singleton): hero-velden, verhaal (portableText), waarden-koppen, SEO + **beeldvelden** `hero_image`/`story_image` (foto's staan in de **mediabibliotheek**: R2 + `media`-rij). "Waarden" = inline **repeater**. ✅ KLAAR.
|
||||
- **`homepage`** (singleton): hero (titel/sub) + repeaters `hero_points`/`werkwijze`/`reviews_small`/`faq` + losse review-/sectie-velden. Gelezen door `index.astro` + `Hero.astro` (props). ✅ KLAAR (tekst). Beeld (hero-cards + galerij) = Wave 2b (TODO).
|
||||
- **`contact_page`** (singleton): kicker/H1/intro + SEO. ✅ KLAAR. NAW blijft uit `site_settings`.
|
||||
- **`diensten`** (collectie, 5 entries, 36 velden) — ✅ KLAAR (Wave 3, `0009_diensten.sql`). Deelt content tussen de **homepage-accordion** (`nav_*`), het **`/diensten`-overzicht**, de **`/diensten/[slug]`-detailpagina's** (alle velden: hero/points/intro/included/resultaat-galerij/aanpak/faq/seo/noindex) en het **nav-dropdownmenu** (`Base.astro`), gesorteerd op `nav_order`. Alles met code-fallback; beeldvelden leeg = statische foto. Resultaat-galerij = 3 vaste image-slots (repeater kan geen image-subveld).
|
||||
|
||||
Velden verplicht maken (om "(optional)" te onderdrukken) en labels wijzigen = `UPDATE _emdash_fields` op de remote D1. **`pages`/`posts` (emdash-defaults) zijn verwijderd** (`scripts/cleanup-default-collections.sql`); blijven weg zolang de setup-wizard niet opnieuw draait.
|
||||
|
||||
---
|
||||
|
||||
## Routes & data flow
|
||||
|
||||
```
|
||||
/ ✓ index.astro (homepage; site_settings via Base, rest hardcoded/placeholder)
|
||||
/api/contact ✓ POST honeypot+time-trap+validatie → console.log (Mailtrap TODO)
|
||||
/_emdash/admin ✓ Emdash admin (na seed/setup)
|
||||
/contact ✓ contact.astro (hidePrefooter + NAW + formulier, sectie id="contact")
|
||||
/diensten ✓ index.astro (overzicht) + /diensten/[slug] (5 diensten) — uit CMS-collectie `diensten` (fallback in code); onbekende slug → 404
|
||||
/over-ons ✓ over-ons.astro (hero + verhaal + waarden + werkgebied)
|
||||
/werkgebied ✓ werkgebied/index.astro (hub: lijst gepubliceerde locaties → /<plaats>, anders pills)
|
||||
/<plaats> ✓ locatiepagina uit collectie `locaties` (CMS), op de root (bv. /maastricht)
|
||||
/<slug> ✓ gewone CMS-pagina uit collectie `paginas`, op de root (bv. /onderhoudstips)
|
||||
/[...slug] ✓ root-router (catch-all, laagste prioriteit): zoekt locaties → paginas; onbekend → branded 404
|
||||
/projecten ❌ GESCHRAPT (klantverzoek) — uit nav + homepage-link; BeforeAfter.astro ongebruikt bewaard
|
||||
/privacy /voorwaarden ✓ code-pagina's (NAW uit site_settings); footer-links
|
||||
/sitemap.xml ✓ sitemap.xml.ts (vaste routes + live CMS-paginas/locaties; overschrijft emdash's eigen sitemap)
|
||||
/robots.txt ✓ public/robots.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build, dev & deploy (Windows)
|
||||
- **Install:** `npm install --ignore-scripts`.
|
||||
- **Dev (twee-fase bij koude cache):** wis `node_modules/.vite` + `.astro`; `$env:NODE_OPTIONS="--use-system-ca"; npx astro dev --port 4321`; 1 GET op `/` (crasht = warmt cache); Ctrl+C; opnieuw starten → stabiel.
|
||||
- **Check/build:** `$env:NODE_OPTIONS="--use-system-ca"; npx astro check` (0 errors), `npx astro build`.
|
||||
- **Deploy:** `$env:CLOUDFLARE_ACCOUNT_ID="…"; npx wrangler deploy` — pas ná D1/R2 + echte `database_id`.
|
||||
|
||||
---
|
||||
|
||||
## Bekende issues (geërfd, gelden hier)
|
||||
1. **Vite SSR chunk-error (Windows)** → twee-fase opstart (zie boven). Niet `optimizeDeps.exclude` voor emdash zetten.
|
||||
2. **`NODE_OPTIONS=--use-system-ca`** vereist voor elke astro/wrangler-call (corporate-cert), anders TLS-fout.
|
||||
3. **better-sqlite3** compileert niet op Windows → `--ignore-scripts`.
|
||||
4. **`database_id`** staat nu op de echte id (`0fb83f17-…`) van `helvoirt-db` in `wrangler.jsonc` (was placeholder-UUID; lege id breekt lokale miniflare).
|
||||
5. **Emdash seed CLI** werkt niet lokaal → setup-wizard of `wrangler d1 execute`.
|
||||
6. **nano-banana** via de truststore-wrapper + system python.org 3.12 (zie CLAUDE.md).
|
||||
|
||||
---
|
||||
|
||||
## Kwaliteit (laatste meting)
|
||||
`astro check` 0 errors · productie-build OK · **axe-core 0 violations op alle 9 pagina's** · geen horizontale overflow (1440/768/390) · contrast ruim AA · tapdoelen ≥44px (telefoon/e-mail/logo/skip-link gefixt in de audit) · impeccable-detector schoon (`[]`) op alle bronbestanden · **hero-audit 20/20 · hero-critique 33/40 · dienst-critique 33/40 · site-audit 17/20** (alle fixes door) · **alle 9 routes live 200, onbekend 404** (deploy version `ff725970`).
|
||||
Reference in New Issue
Block a user