diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index def1002e..b2135b91 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,6 +19,8 @@ env: PUBLIC_VAPID_PUBLIC_KEY: ${{ secrets.PUBLIC_VAPID_PUBLIC_KEY }} VAPID_PRIVATE_KEY: ${{ secrets.VAPID_PRIVATE_KEY }} VAPID_SUBJECT: "mailto:web@programmerbar.no" + PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY: 1x00000000000000000000AA + CLOUDFLARE_TURNSTILE_SITE_SECRET: 1x0000000000000000000000000000000AA jobs: ci: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b2a1e1c3..5571ee26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -187,6 +187,9 @@ importers: svelte-sonner: specifier: 1.0.7 version: 1.0.7(svelte@5.48.0) + svelte-turnstile: + specifier: ^0.11.0 + version: 0.11.0(svelte@5.48.0) tailwind-merge: specifier: 3.4.0 version: 3.4.0 @@ -7802,6 +7805,11 @@ packages: peerDependencies: svelte: ^5.30.2 + svelte-turnstile@0.11.0: + resolution: {integrity: sha512-2LFklx9JVsR3fJ7e3fGG1HEAWWEqRq1WfNaVrKgZJ+pzfY2NColiH+wH0kK2yX3DrcGLiJ9vBeTyiLFWotKpLA==} + peerDependencies: + svelte: ^3.58.0 || ^4.0.0 || ^5.0.0 + svelte@5.48.0: resolution: {integrity: sha512-+NUe82VoFP1RQViZI/esojx70eazGF4u0O/9ucqZ4rPcOZD+n5EVp17uYsqwdzjUjZyTpGKunHbDziW6AIAVkQ==} engines: {node: '>=18'} @@ -7993,6 +8001,9 @@ packages: resolution: {integrity: sha512-5JIA5aYBAJSAhrhbyag1ZuMSgUZnHtI+Sq3H8D3an4fL8PeF+L1yYvbEJg47akP1PFfATMf5ehkqFnxfkmuwZQ==} hasBin: true + turnstile-types@1.2.3: + resolution: {integrity: sha512-EDjhDB9TDwda2JRbhzO/kButPio3JgrC3gXMVAMotxldybTCJQVMvPNJ89rcAiN9vIrCb2i1E+VNBCqB8wue0A==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -16971,6 +16982,11 @@ snapshots: transitivePeerDependencies: - '@sveltejs/kit' + svelte-turnstile@0.11.0(svelte@5.48.0): + dependencies: + svelte: 5.48.0 + turnstile-types: 1.2.3 + svelte@5.48.0: dependencies: '@jridgewell/remapping': 2.3.5 @@ -17169,6 +17185,8 @@ snapshots: turbo-windows-64: 2.7.2 turbo-windows-arm64: 2.7.2 + turnstile-types@1.2.3: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 diff --git a/programmerbar-web/.env.example b/programmerbar-web/.env.example index 1f6c8ee5..a4120043 100644 --- a/programmerbar-web/.env.example +++ b/programmerbar-web/.env.example @@ -57,4 +57,14 @@ PUBLIC_GITHUB_SHA="development" # # Enable Sentry error tracking and performance monitoring # -------------------------------------------------------- -SENTRY_AUTH_TOKEN= \ No newline at end of file +SENTRY_AUTH_TOKEN= + +# -------------------------------------------------------- +# Cloudflare Turnstile +# +# Site key and secret key for Cloudflare Turnstile CAPTCHA +# Values for testing can be found at: +# https://developers.cloudflare.com/turnstile/troubleshooting/testing/ +# -------------------------------------------------------- +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=1x00000000000000000000AA +CLOUDFLARE_TURNSTILE_SITE_SECRET=1x0000000000000000000000000000000AA diff --git a/programmerbar-web/package.json b/programmerbar-web/package.json index 5918ed7a..fb7bd383 100644 --- a/programmerbar-web/package.json +++ b/programmerbar-web/package.json @@ -84,6 +84,7 @@ "react-dom": "19.2.3", "resend": "6.8.0", "svelte-sonner": "1.0.7", + "svelte-turnstile": "^0.11.0", "tailwind-merge": "3.4.0", "web-push": "^3.6.7", "zod": "4.3.6", diff --git a/programmerbar-web/src/lib/components/app/landing/ContactForm.svelte b/programmerbar-web/src/lib/components/app/landing/ContactForm.svelte index 5e5f7b12..f17cf04b 100644 --- a/programmerbar-web/src/lib/components/app/landing/ContactForm.svelte +++ b/programmerbar-web/src/lib/components/app/landing/ContactForm.svelte @@ -2,6 +2,8 @@ import { toast } from 'svelte-sonner'; import { createContactSubmissionAction } from '../../../../routes/(app)/common.remote'; import CLIWindow from '$lib/components/app/CLIWindow.svelte'; + import { Turnstile } from 'svelte-turnstile'; + import { env } from '$env/dynamic/public'; @@ -53,6 +55,8 @@ > + +