Skip to main content
Introducing packages.sweber.dev
All packages
BetaMIT + Pro

InverseThe withdrawal button (§ 356a BGB) and the cancellation button (§ 312k BGB) for Next.js and React, with the two-step flow, the receipt e-mail and a page check.

pnpm add @sweberdev/inverse @sweberdev/inverse-react

Since 19 June 2026, every online business that concludes contracts with consumers in the EU needs a withdrawal button labelled "Vertrag widerrufen". German subscription businesses have needed a cancellation button labelled "Verträge hier kündigen" since 2022. Shopify, Shopware and WooCommerce have plugins for this; custom shops, SaaS products and booking apps built with Next.js or React mostly don't.

Inverse adds both buttons to your own app. It gets the details right that courts look at: the statutory labels, a second step with "Widerruf bestätigen" or "Jetzt kündigen", the time of receipt set by your server, an acknowledgement e-mail with the content of the declaration, and a copy the consumer can download. You keep the data and send the e-mail with your own provider. A CLI checks your pages for the buttons, so a redesign can't quietly remove them.

Example

A short exampleCopy it into your project.

app/api/inverse/route.ts

import { createInverseHandler } from "@sweberdev/inverse"

export const POST = createInverseHandler({
  company: { name: "Acme GmbH", email: "hallo@acme.de" },
  onDeclaration: (record) => db.declaration.create({ data: record }),
  sendReceipt: (receipt) => resend.emails.send({ from: "service@acme.de", ...receipt }),
})

// footer: <InverseLink kind="withdrawal" href="/widerruf" />
// app/widerruf/page.tsx: <WithdrawalForm endpoint="/api/inverse" />

Features

What you getFree under MIT, with Pro on top.

Free, MIT

  • <InverseLink> with the statutory labels "Vertrag widerrufen" and "Verträge hier kündigen"
  • <WithdrawalForm> and <CancellationForm>: details, review with the statutory confirm button, receipt with download
  • Server-side record with date and time of receipt, and the acknowledgement e-mail with the content of the declaration
  • Labels, errors and receipts in German, English, French and Italian
  • Withdrawal deadline and contract end date, with weekends and your public holidays
  • Request → Response handler for Next.js, Remix, Hono, SvelteKit and Astro; form posts without JavaScript
  • inverse check: finds missing or mislabelled buttons on a page, exit code for CI

Pro

  • Evidence ledger: every declaration and receipt in a SHA-256 hash chain, evidence sheet per declaration, erasure that keeps the chain verifiable
  • Site audit: every page from the sitemap, buttons followed to the form without login, HTML report for clients, many sites in one run
  • Branded receipts, a team notification with the refund or end date, and transports for Resend, Postmark, SendGrid, Brevo, Mailgun and SMTP

Compare

Free and ProSide by side.

FeatureFreePro
Buttons, two-step forms and receipt e-mailIncludedIncluded
Deadlines, handler and page check CLIIncludedIncluded
Tamper-evident evidence ledgerNot includedIncluded
Site-wide audit with client reportNot includedIncluded
Branded receipts, team notification, mail transportsNot includedIncluded
LicenceMITPer person
SupportGitHub issuesAgency and Lifetime

Pro

Pro packagesAdd-ons on top of the core.

  • @weber-development/inverse-ledger

    Stores declarations and receipts in a hash chain, so later changes are detected, and prints an evidence sheet per declaration.

  • @weber-development/inverse-audit

    Checks every page of a site for both buttons, follows them to the form without login and writes a report for clients.

  • @weber-development/inverse-mail

    Sends receipts in your branding, notifies your team with the next due date, and ships transports for the common mail providers.

Pricing

PricingPrices are in CHF.

Inverse Pro: coming soon

The Pro packages are not on sale yet. Join the waitlist and you get a note when they are.

Freelancer

For one person working on client projects.

CHF 190

per year

2 months free

  • 1 person
  • No support entitlement
Join waitlist

Agency

Recommended

For teams of up to ten named people, one price.

CHF 590

per year

2 months free

  • Up to 10 people
  • Support included
Join waitlist

Lifetime

Pay once for up to ten people and keep updates and repository access.

CHF 1'990

one-time

  • Up to 10 people
  • Support included
Join waitlist

11 people or more: get in touch

  • After cancelling, every version you already received keeps working. Only updates and repository access end.
  • No licence key, no phone-home. The packages never contact a server to check your licence.
  • Agency and Lifetime cover up to ten named people for one price: you choose the number of seats at checkout and assign them in Polar. Your clients and their websites need no licence of their own.
  • Checkout, invoices and VAT are handled by Polar as merchant of record.
Read the licence terms

FAQ

QuestionsShort answers.

Do I need both buttons?

The withdrawal button is needed wherever consumers can conclude a contract on your site or app, including shops, bookings and subscriptions. The cancellation button is needed in Germany for continuing contracts such as subscriptions and memberships that can be concluded online. Many SaaS products need both.

Does Inverse store anything or send data to you?

No. The handler calls your own function to store the declaration and your own mail provider to send the receipt. Nothing goes to Inverse or to us.

Can I change the labels?

Yes, every text can be overridden. The law allows an equivalent, unambiguous wording, but the statutory labels are the safe choice, so they are the default.

Does it work without Next.js?

Yes. The handler takes a Fetch API Request and returns a Response, so it runs on Remix, Hono, SvelteKit, Astro and any Node server. The forms need React; without React you can render your own and post to the same handler.

Is this legal advice?

No. Inverse implements the published wording and process of § 356a and § 312k BGB and explains its reasoning in the docs. For your specific case, ask a lawyer or your trade association.

Articles

ArticlesGuides and release notes.