diff --git a/LOGBOEK.md b/LOGBOEK.md
index bf35f50..877640a 100644
--- a/LOGBOEK.md
+++ b/LOGBOEK.md
@@ -66,7 +66,40 @@
- Workshop details (datum/tijd/locatie) compact weergegeven met iconen
### Volgende sessie
-- [ ] Inschrijfformulier/betaallink toevoegen
-- [ ] Deploy naar productie
-- [ ] SEO meta tags toevoegen (Open Graph, Twitter Cards)
-- [ ] Formulier validatie en betalingsflow
+- [x] Inschrijfformulier/betaallink toevoegen
+- [x] Deploy naar productie
+- [x] SEO meta tags toevoegen (Open Graph, Twitter Cards)
+- [x] Formulier validatie en betalingsflow
+
+## 2026-02-10 - Sessie 4: Mollie betaalflow, SEO en deploy
+
+### Wat is gebouwd
+- Mollie Payment Links aangemaakt (test + live) voor workshop betaling
+- Tally formulier geintegreerd voor e-mailverzameling voor inschrijving
+- Inschrijfpagina (/inschrijven) met embedded Tally formulier
+- Bedankt-pagina (/bedankt) voor na succesvolle betaling
+- Payment config bestand (src/config/payment.js) voor centrale URL configuratie
+- CTA-knoppen (Pricing, FinalCTA, StickyBar) gelinkt naar inschrijfpagina via React Router Link
+- Hero CTA scrollt nog steeds naar pricing sectie
+- OpenGraph en Twitter Card meta tags in index.html
+- OG-afbeelding (1200x630) gemaakt in Canva met site-kleuren en headline
+- SVG favicon (coral CC icoon)
+- Umami analytics script toegevoegd (zelfde ID als frankmeeuwsen.com)
+- Canonical URL ingesteld
+- Base path config (/workshopclaudecode/) alleen voor production builds
+- .htaccess voor SPA-routing in submap
+- Deploy script (deploy.sh) voor build + upload naar Coolify Docker container
+- Site live gedeployd op https://frankmeeuwsen.com/workshopclaudecode/
+
+### Technische beslissingen
+- Tally als tussenstap voor e-mailverzameling (geen backend nodig, AVG-compliant, gratis)
+- Betaalflow: CTA -> /inschrijven (Tally embed) -> Mollie betaalpagina -> /bedankt
+- Vite base path conditioneel: / voor dev, /workshopclaudecode/ voor build
+- React Router basename via import.meta.env.BASE_URL (werkt automatisch in beide modes)
+- Hero afbeelding pad via import.meta.env.BASE_URL voor correcte submap-verwijzing
+- Deploy via rsync + docker cp naar WordPress container op Coolify
+
+### Volgende sessie
+- [ ] Testimonials toevoegen zodra beschikbaar
+- [ ] Structured data (JSON-LD Event schema) toevoegen
+- [ ] Eerste testbetaling via live link verifiëren
diff --git a/content/Social image CC workshop.png b/content/Social image CC workshop.png
new file mode 100644
index 0000000..c3c6dd5
Binary files /dev/null and b/content/Social image CC workshop.png differ
diff --git a/deploy.sh b/deploy.sh
new file mode 100755
index 0000000..2962988
--- /dev/null
+++ b/deploy.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Deploy script voor Claude Code Workshop sales page
+# Bouwt de site en deployt naar de Coolify WordPress container
+#
+# Gebruik: ./deploy.sh
+
+set -e
+
+SERVER="coolify"
+CONTAINER="wordpress-d0wko4gskokosssogcw8040g"
+REMOTE_PATH="/var/www/html/workshopclaudecode"
+TMP_PATH="/tmp/workshopclaudecode"
+
+echo "1/4 - Building..."
+npm run build --silent
+
+echo "2/4 - Uploading naar server..."
+rsync -avz --quiet dist/ "$SERVER:$TMP_PATH/"
+
+echo "3/4 - Kopieren naar container..."
+ssh "$SERVER" "docker cp $TMP_PATH/. $CONTAINER:$REMOTE_PATH/ && docker exec $CONTAINER chown -R www-data:www-data $REMOTE_PATH/"
+
+echo "4/4 - Opruimen..."
+ssh "$SERVER" "rm -rf $TMP_PATH"
+
+echo "Done! https://frankmeeuwsen.com/workshopclaudecode/"
diff --git a/index.html b/index.html
index dca59fb..7563f95 100644
--- a/index.html
+++ b/index.html
@@ -2,11 +2,34 @@
-
+
Claude Code Workshop - Van nieuwsgierig naar praktisch aan de slag
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/.htaccess b/public/.htaccess
new file mode 100644
index 0000000..8350a92
--- /dev/null
+++ b/public/.htaccess
@@ -0,0 +1,13 @@
+# SPA routing: stuur alle requests naar index.html
+# zodat React Router de routes /bedankt, /inschrijven etc. kan afhandelen
+
+ RewriteEngine On
+ RewriteBase /workshopclaudecode/
+
+ # Als het bestand of directory bestaat, serveer het direct
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+
+ # Alles anders naar index.html
+ RewriteRule ^ index.html [QSA,L]
+
diff --git a/public/favicon.svg b/public/favicon.svg
new file mode 100644
index 0000000..803e11b
--- /dev/null
+++ b/public/favicon.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/public/og-image.png b/public/og-image.png
new file mode 100644
index 0000000..c3c6dd5
Binary files /dev/null and b/public/og-image.png differ
diff --git a/src/components/FinalCTA.jsx b/src/components/FinalCTA.jsx
index 68bedfe..5918a96 100644
--- a/src/components/FinalCTA.jsx
+++ b/src/components/FinalCTA.jsx
@@ -2,9 +2,12 @@
* FinalCTA.jsx - Afsluitende call-to-action sectie
*
* Coral-500 achtergrond met witte tekst.
- * Bevat datum, locatie en primaire CTA button (wit met coral tekst).
+ * Bevat datum, locatie en CTA button die naar Mollie betaalpagina linkt.
*/
+import { Link } from 'react-router-dom';
+import { PAYMENT_CONFIG } from '../config/payment';
+
function FinalCTA() {
return (
@@ -55,16 +58,16 @@ function FinalCTA() {
- {/* CTA Button - wit met coral tekst */}
-
Doe mee op 6 maart
-
+
{/* Contact info */}
diff --git a/src/components/Hero.jsx b/src/components/Hero.jsx
index 6339720..68680fa 100644
--- a/src/components/Hero.jsx
+++ b/src/components/Hero.jsx
@@ -122,7 +122,7 @@ function Hero() {
diff --git a/src/components/StickyBar.jsx b/src/components/StickyBar.jsx
index 98014b7..2d5e18b 100644
--- a/src/components/StickyBar.jsx
+++ b/src/components/StickyBar.jsx
@@ -7,6 +7,8 @@
*/
import { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
+import { PAYMENT_CONFIG } from '../config/payment';
function StickyBar() {
// State om te bepalen of de bar zichtbaar moet zijn
@@ -63,12 +65,12 @@ function StickyBar() {
€399 excl. BTW
-
Inschrijven
-
+
@@ -89,12 +91,12 @@ function StickyBar() {
{/* Right: CTA */}
-
Inschrijven
-
+
diff --git a/src/config/payment.js b/src/config/payment.js
new file mode 100644
index 0000000..cd1c1e9
--- /dev/null
+++ b/src/config/payment.js
@@ -0,0 +1,11 @@
+/**
+ * payment.js - Betaalflow configuratie
+ *
+ * CTA-knoppen linken naar de inschrijfpagina met embedded Tally formulier.
+ * Na het formulier redirect Tally naar de Mollie betaalpagina.
+ * Test/live Mollie link wordt ingesteld in Tally's redirect URL.
+ */
+
+export const PAYMENT_CONFIG = {
+ SIGNUP_URL: '/inschrijven',
+};
diff --git a/src/main.jsx b/src/main.jsx
index 2dc4f8f..32bbc23 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -5,14 +5,18 @@ import './index.css'
import App from './App.jsx'
import Privacy from './pages/Privacy.jsx'
import Terms from './pages/Terms.jsx'
+import ThankYou from './pages/ThankYou.jsx'
+import Signup from './pages/Signup.jsx'
createRoot(document.getElementById('root')).render(
-
+
} />
} />
} />
+ } />
+ } />
,
diff --git a/src/pages/Signup.jsx b/src/pages/Signup.jsx
new file mode 100644
index 0000000..84a9ac1
--- /dev/null
+++ b/src/pages/Signup.jsx
@@ -0,0 +1,90 @@
+/**
+ * Signup.jsx - Inschrijfpagina met embedded Tally formulier
+ *
+ * Bezoekers komen hier via de CTA-knoppen op de sales page.
+ * Na het invullen van het formulier redirect Tally naar de Mollie betaalpagina.
+ */
+
+import { useEffect } from 'react';
+import { Link } from 'react-router-dom';
+
+function Signup() {
+ // Laad het Tally embed script zodra de pagina mount
+ useEffect(() => {
+ const scriptUrl = 'https://tally.so/widgets/embed.js';
+
+ // Check of het script al geladen is
+ if (typeof window.Tally !== 'undefined') {
+ window.Tally.loadEmbeds();
+ return;
+ }
+
+ // Script nog niet geladen? Voeg het toe
+ if (!document.querySelector(`script[src="${scriptUrl}"]`)) {
+ const script = document.createElement('script');
+ script.src = scriptUrl;
+ script.onload = () => {
+ if (typeof window.Tally !== 'undefined') {
+ window.Tally.loadEmbeds();
+ }
+ };
+ document.body.appendChild(script);
+ }
+ }, []);
+
+ return (
+
+ {/* Header */}
+
+
+ {/* Content */}
+
+
+
Inschrijven
+
+ Vul je gegevens in en je wordt doorgestuurd naar de betaalpagina.
+
+
+ {/* Embedded Tally formulier */}
+
+
+
+
+ {/* Workshop samenvatting */}
+
+
Claude Code Workshop | Vrijdag 6 maart 2026 | 9:00 - 14:00 | Utrecht
+
EUR 399 excl. BTW (EUR 482,79 incl. BTW)
+
+
+
+
+ {/* Footer */}
+
+
+ );
+}
+
+export default Signup;
diff --git a/src/pages/ThankYou.jsx b/src/pages/ThankYou.jsx
new file mode 100644
index 0000000..9bad0fb
--- /dev/null
+++ b/src/pages/ThankYou.jsx
@@ -0,0 +1,108 @@
+/**
+ * ThankYou.jsx - Bedankt-pagina na succesvolle betaling
+ *
+ * Bezoekers komen hier terecht na betaling via Mollie.
+ * Toont bevestiging, workshop details en vervolgstappen.
+ */
+
+import { Link } from 'react-router-dom';
+
+function ThankYou() {
+ return (
+
+ {/* Header */}
+
+
+ {/* Content */}
+
+
+ {/* Checkmark icoon */}
+
+
+
Je bent erbij!
+
+ Je inschrijving voor de Claude Code Workshop is bevestigd.
+
+
+ {/* Workshop details */}
+
+
Workshop details
+
+
+
+
Vrijdag 6 maart 2026
+
+
+
+
9:00 - 14:00 uur
+
+
+
+
+
+ {/* Vervolgstappen */}
+
+
Wat gebeurt er nu?
+
+ -
+ 1
+ Je ontvangt een bevestigingsmail met je factuur.
+
+ -
+ 2
+ Een week voor de workshop ontvang je een mail met praktische informatie en voorbereidingsinstructies.
+
+ -
+ 3
+ Op 6 maart neem je je laptop mee en gaan we aan de slag!
+
+
+
+
+ {/* Contact */}
+
+ Vragen? Mail naar{' '}
+
+ frank@frankmeeuwsen.com
+
+
+
+
+
+ {/* Footer */}
+
+
+ );
+}
+
+export default ThankYou;
diff --git a/vite.config.js b/vite.config.js
index 8b0f57b..cdb4de0 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -2,6 +2,8 @@ import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
-export default defineConfig({
+// base path alleen voor production build, lokaal blijft het op /
+export default defineConfig(({ command }) => ({
plugins: [react()],
-})
+ base: command === 'build' ? '/workshopclaudecode/' : '/',
+}))