
nForms
One script tag. Zero CAPTCHA. EU-only form backend.
## TL;DR
We run [nForms](https://nforms.eu) — a GDPR-compliant form backend with built-in bot protection via Proof-of-Work (instead of CAPTCHA). Last week I realized our compare pages had a huge conversion leak: visitors would read "nForms vs. reCAPTCHA", nod along, then bounce because they couldn't picture how hard the migration actually is.
So over 2 days I shipped:
- 4 drop-in migration guide pages (reCAPTCHA, Turnstile, hCaptcha, Friendly Captcha)
- EN + DE content for all 4 (~80k characters of markdown)
- HowTo + FAQPage JSON-LD schemas on each for Google Rich Results
- A 45-second inline screencast with live Proof-of-Work visualization — real API challenge, real SHA-256 solver, real numbers animating on screen
- og:video + Twitter player card metadata so shared URLs unfurl as inline video
- Conditional "Migrate in 60 seconds" CTA block on all 4 compare pages
- Cross-links from 6 existing blog posts that already rank for reCAPTCHA keywords
Results are pending (deployed today), but here's what I learned and why it should work.
---
## The leak I found
Our compare/recaptcha page already ranked on long-tail queries. Visitors landed, read the pain points, saw the feature table, agreed conceptually — and then the only CTAs were "Get Started Free → /login" and "View Pricing".
That's a huge commitment for someone who's 2 minutes into the page. What they actually want at that moment is proof that the migration isn't a weekend project. "Show me how hard this is" comes before "let me sign up".
I had nothing to show them.
---
## The drop-in snippet approach
The core insight that made the content click: reCAPTCHA has 3 common integration flavors in the wild — v2 Checkbox, v2 Invisible, v3 Score-based. Most migration guides cover one and leave the other two readers stranded.
But our "after" snippet is identical for all three:
```html
<script src="https://api.nforms.eu/shield.js"></script>
<form action="https://api.nforms.eu/f/YOUR_KEY" method="POST"
data-nforms-key="YOUR_KEY">
<input name="email" required />
<button type="submit">Send</button>
</form>
```
Three complex Before-states → one simple After-state. That asymmetry is the story. Once I framed it that way, the page wrote itself.
Plus the "what you can delete" section (server-side siteverify endpoint, RECAPTCHA_SECRET_KEY, cookie banner entry, react-google-recaptcha from package.json) is emotionally satisfying in a way that devs on Twitter eat up. People love deleting code.
---
## The live Proof-of-Work visualization
The thing I'm most proud of: the screencast doesn't just claim Shield runs a PoW solver, it shows it.
I wrote a Playwright script that renders a single-page HTML video with 6 narrative scenes:
1. Hook (3s) — "22 → 2" — big display
2. Problem (7s) — reCAPTCHA code + red stats
3. Solution (6s) — nForms code + emerald stats
4. Live PoW (9s) — fetches a REAL challenge from api.nforms.eu, solves it for real, animates the counter from 0 → n_found over 7 seconds, shows the real hash, displays the real solve time
5. Proof (9s) — fills and submits a real form with live Shield
6. CTA (4.5s) — nforms.eu with emerald glow
The PoW scene is the moneymaker. Every number and hash shown on screen is real — salt, target, counter, found n, completion time. Only the sweep speed is throttled (500k iterations compressed from ~200ms to 7 seconds of visual drama). It proves the "zero puzzles, just math" claim instead of stating it.
Playwright records at 1280×720, I export to MP4 (1.8 MB, for Twitter/LinkedIn), WebM (3.2 MB, for the embedded player), and GIF (8 MB, for Reddit/dev.to).
---
## On-site discoverability
The video is embedded directly on all 4 migration pages as autoplay-muted-loop. This does three things:
- Dwell time skyrockets (Google's strongest ranking signal after backlinks)
- Shared URLs unfurl as inline video on Twitter/LinkedIn/Slack (`og:video` + twitter:card=player)
- Visitors see the "60 seconds" proof before they even scroll
Plus the compare pages now have a conditional CTA block between "Why Switch" and "Feature Comparison" — exactly at the moment visitors go from problem-awareness to solution-evaluation.
---
## The internal link strategy
Instead of praying for external backlinks, I added 6 internal links from blog posts that already rank for reCAPTCHA keywords:
- /blog/why-proof-of-work-beats-captcha
- /blog/is-recaptcha-gdpr-compliant
- /blog/recaptcha-gdpr-problem
- /blog/recaptcha-alternative-eu
(Plus DE variants for each.)
Each post now closes with a CTA paragraph pointing to the migration guide. These are already-indexed, already-ranking pages passing link equity to the new target. No waiting for crawl budget or backlink outreach — the equity is there, I just needed to route it.
---
## Schema.org for Rich Results
Every migration page has both HowTo and FAQPage JSON-LD. Google's HowTo rich result is one of the few that still shows step counters and "total time" in SERPs. I set totalTime: "PT1M" (60 seconds) so the SERP snippet literally shows "⏱ 1 min" next to the headline. That's CTR gold.
The FAQ schema pulls the 3-7 most common questions per page. Combined with the HowTo schema, each page has ~11 KB of structured data that Google and LLM crawlers can cite directly.
---
## What I'd do differently
- Launch the distribution in parallel to the build: I finished the guides first, then started writing Twitter threads. Should've had drafts ready so I could ship + post in the same hour.
- Record per-competitor screencasts: Currently all 4 migration pages share one video (the reCAPTCHA one). Native per-competitor videos would rank better for "migrate from turnstile" etc., but the effort-to-impact felt marginal for v1.
- PostHog events: I didn't wire specific events for the migration guide funnel (page view → video play → CTA click → signup). Doing that this week so I can actually measure if any of this worked.
---
## Tech stack (for the curious)
- Next.js 15 on Cloudflare Pages via OpenNext
- Content in flat JSON files (`lib/docs/content-{en,de}.json`) rendered via a tiny custom tokenizer — no MDX, no CMS
- Playwright 1.59 for the screencast recording, ffmpeg for format conversion
- Sitemap auto-generated from a DOC_SECTIONS config
- Deployed via GitHub Actions → Cloudflare (3-4 min per deploy)
---
## Links
- Main migration page: https://nforms.eu/docs/migrate-from-recaptcha
- Compare page with new CTA: https://nforms.eu/compare/recaptcha
- nForms itself: https://nforms.eu (free tier: 100 submissions/month, no credit card)
Happy to answer questions about the PoW economics, the content strategy, or the Playwright screencast pipeline if anyone wants to steal it.
Hey IH 👋
I'm Noah, solo founder from Germany. I just launched nForms into public beta.
The problem I kept running into:
Every client form needed three things — spam protection, accessibility compliance, and GDPR compliance. reCAPTCHA handles one of those (badly). WCAG needs manual ARIA work. GDPR means cookie consent banners just for bot protection.
What I built:
A form backend that replaces CAPTCHA with SHA-256 Proof-of-Work. The browser solves a math challenge in ~200ms — bots can't scale it, users don't see it. The same script tag also adds WCAG 2.2 AA form validation automatically.
Zero cookies. EU-only infrastructure. One script tag.
Stack: Cloudflare Workers (Frankfurt), D1, Hono, Next.js
Where I'm at:
- Revenue: $0/mo
- Users: handful of beta testers
- Built solo as a side project
- Free tier: 100 submissions/month
- Paid: €9/mo
What I'm looking for:
Honest feedback. Especially from devs who've dealt with form spam or EU compliance headaches.
→ nforms.eu (the contact form is a live demo — Shield is active on it)
Happy to answer any questions about the tech or the journey so far.
1 Like
Comment
About
reCAPTCHA on client forms meant cookies, US data transfers, consent banners. No tool handled spam + accessibility + GDPR together. So I built one. PoW bot protection, WCAG validation, EU-only. One script tag.

Comment