diff --git a/CLAUDE.md b/CLAUDE.md index bab8374..0e21011 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,6 +15,7 @@ npm run dev # Vite dev server on port 5173 npm run build # Production build to dist/ npm run preview # Preview production build npm run lint # ESLint +./preflight.sh # Pre-deploy checks (lint + build + asset path validation) ``` ## Architecture @@ -58,10 +59,10 @@ Reusable component classes defined in `src/index.css` using `@layer components`: ## Deployment ```bash -./deploy.sh # Build + deploy naar productie (geen passphrase nodig) +./deploy.sh # Preflight + build + deploy naar productie (geen passphrase nodig) ``` -Deployment flow: `npm run build` → rsync naar server → `docker cp` naar WordPress container → chown fix +Deployment flow: `./preflight.sh` → `npm run build` → rsync naar server → `docker cp` naar WordPress container → chown fix - **Server:** Hetzner (37.27.183.46) via SSH alias `coolify-deploy` - **Container:** `wordpress-d0wko4gskokosssogcw8040g` @@ -75,3 +76,29 @@ Deployment flow: `npm run build` → rsync naar server → `docker cp` naar Word - Inline SVG icons (Heroicons-style) rather than an icon library - StickyBar has separate mobile (bottom) and desktop (top) layouts triggered by scroll position (600px threshold) - Anchor links use `#inschrijven` for CTA scroll targets + +### Verificatie Werkwijze + +**Voor elke wijziging: check bestaande patronen** in de code voordat je iets nieuws toevoegt. Hoe doen vergelijkbare items het? Gebruik dezelfde aanpak. + +**Wanneer `./preflight.sh` draaien:** +- Nieuwe bestanden toevoegen (afbeeldingen, componenten) +- Nieuwe data-entries met paden of URLs +- Imports of exports wijzigen +- Structurele wijzigingen (nieuw component, nieuwe route) +- Configuratie aanpassen (vite.config, tailwind.config) + +**Niet nodig bij:** +- Tekst aanpassen (quote, titel, beschrijving) +- Getallen wijzigen (bijv. availableSpots) +- CSS tweaks (kleur, spacing, font-size) + +Vuistregel: als het kan breken, check het. Als het alleen tekst is, niet. + +### Static Assets (BELANGRIJK) +- Statische bestanden (afbeeldingen, etc.) staan in `public/` +- **Altijd** `${import.meta.env.BASE_URL}` als prefix gebruiken bij verwijzingen vanuit code +- Reden: productie draait op `/workshopclaudecode/`, niet op `/` +- Voorbeeld: `` src={`${import.meta.env.BASE_URL}foto.jpg`} `` +- NOOIT: `src="/foto.jpg"` (werkt lokaal maar breekt op productie) +- `./preflight.sh` detecteert hardcoded paden automatisch diff --git a/deploy.sh b/deploy.sh index fb960f8..1640469 100755 --- a/deploy.sh +++ b/deploy.sh @@ -11,6 +11,9 @@ CONTAINER="wordpress-d0wko4gskokosssogcw8040g" REMOTE_PATH="/var/www/html/workshopclaudecode" TMP_PATH="/tmp/workshopclaudecode" +echo "0/4 - Preflight checks..." +./preflight.sh +echo "" echo "1/4 - Building..." npm run build --silent diff --git a/preflight.sh b/preflight.sh new file mode 100755 index 0000000..102acdf --- /dev/null +++ b/preflight.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Preflight checks - draait voor elke deploy om veelvoorkomende fouten te vangen +# +# Checks: +# 1. ESLint +# 2. Vite build (syntax errors, missing imports) +# 3. Hardcoded asset paden die BASE_URL missen +# 4. Gerefereerde public/ bestanden bestaan daadwerkelijk + +set -e + +ERRORS=0 + +echo "=== Preflight Checks ===" +echo "" + +# 1. Lint check +echo "[1/4] ESLint..." +if npm run lint --silent 2>&1; then + echo " OK" +else + echo " WAARSCHUWING: lint errors gevonden (niet-blokkerend)" +fi +echo "" + +# 2. Build check +echo "[2/4] Vite build..." +npm run build --silent +echo " OK" +echo "" + +# 3. Check voor hardcoded asset paden zonder BASE_URL +# Zoekt naar src= of avatar: paden die beginnen met "/" gevolgd door een bestandsnaam +# maar NIET import.meta.env.BASE_URL gebruiken +echo "[3/4] Asset paden check (BASE_URL)..." +BAD_PATHS=$(grep -rn 'src=\s*"\/[a-zA-Z0-9]' src/ --include="*.jsx" --include="*.js" 2>/dev/null || true) +BAD_AVATAR=$(grep -rn "avatar:\s*[\"']/[a-zA-Z0-9]" src/ --include="*.jsx" --include="*.js" 2>/dev/null || true) + +if [ -n "$BAD_PATHS" ] || [ -n "$BAD_AVATAR" ]; then + echo " FOUT: Hardcoded asset paden gevonden zonder BASE_URL prefix!" + echo " Deze werken lokaal maar breken op productie (/workshopclaudecode/)." + echo "" + [ -n "$BAD_PATHS" ] && echo "$BAD_PATHS" | sed 's/^/ /' + [ -n "$BAD_AVATAR" ] && echo "$BAD_AVATAR" | sed 's/^/ /' + echo "" + echo " Fix: gebruik \${import.meta.env.BASE_URL}bestandsnaam.jpg" + ERRORS=$((ERRORS + 1)) +else + echo " OK" +fi +echo "" + +# 4. Check dat gerefereerde bestanden in public/ bestaan +echo "[4/4] Public assets bestaan..." +MISSING=0 +for file in public/*; do + [ -f "$file" ] || continue +done + +# Zoek alle BASE_URL referenties en check of het bestand bestaat in public/ +# Matcht alleen bestandsnamen (letters, cijfers, punt, streepje, underscore) +REFS=$(grep -roh 'BASE_URL}[a-zA-Z0-9._-]*' src/ --include="*.jsx" --include="*.js" 2>/dev/null | sed 's/BASE_URL}//' | grep -v '^$' || true) +for ref in $REFS; do + if [ ! -f "public/$ref" ]; then + echo " FOUT: public/$ref bestaat niet (gerefereerd in code)" + MISSING=$((MISSING + 1)) + fi +done + +if [ "$MISSING" -eq 0 ]; then + echo " OK" +else + ERRORS=$((ERRORS + MISSING)) +fi +echo "" + +# Resultaat +echo "=== Resultaat ===" +if [ "$ERRORS" -gt 0 ]; then + echo "GEFAALD: $ERRORS fout(en) gevonden. Fix deze voor deploy." + exit 1 +else + echo "ALLES OK - klaar voor deploy." + exit 0 +fi diff --git a/public/20260211174-MoniqueDubbelman.jpg b/public/20260211174-MoniqueDubbelman.jpg new file mode 100644 index 0000000..bb12869 Binary files /dev/null and b/public/20260211174-MoniqueDubbelman.jpg differ diff --git a/src/components/Hero.jsx b/src/components/Hero.jsx index d4244f6..00de26a 100644 --- a/src/components/Hero.jsx +++ b/src/components/Hero.jsx @@ -6,8 +6,9 @@ */ function Hero() { - // Aantal beschikbare plaatsen - later dynamisch te maken - const availableSpots = 8; + // Aantal beschikbare plaatsen + const totalSpots = 8; + const availableSpots = 7; return (
@@ -33,7 +34,7 @@ function Hero() { - {availableSpots} plekken - kleine groep, persoonlijke aandacht + {totalSpots}{' '}{availableSpots} plekken - kleine groep, persoonlijke aandacht diff --git a/src/components/Testimonials.jsx b/src/components/Testimonials.jsx index debf4c3..6ea59d2 100644 --- a/src/components/Testimonials.jsx +++ b/src/components/Testimonials.jsx @@ -31,6 +31,14 @@ function Testimonials() { url: "https://drawn.today/", initials: "JB" }, + { + quote: "Frank leert je op een laagdrempelige en humoristische manier hoe je zelf in een paar uur je eigen app bouwt, zonder technische kennis. Je leert dingen waarvan je niet wist dat je ze wilde leren", + name: "Monique Dubbelman", + role: "Community Manager", + avatar: `${import.meta.env.BASE_URL}20260211174-MoniqueDubbelman.jpg`, + url: "https://modub.nl/", + initials: "MD" + }, { quote: "Kan een niet-developer apps, websites, games maken? Het lijkt te mooi om waar te zijn, totdat Frank je met een glimlach en geduld gerust stelt. Voor mij was deze sessie zeer inspirerend en zorgde ervoor dat ik vier apps heb gemaakt in korte tijd.", name: "Ewout Wolff",