DEV Community

Abid niazi
Abid niazi

Posted on

Building Zero-Data-Retention EU Compliance Utilities in Next.js 14: Peppol XML, IBAN Validation & GDPR

Markdown

Why European Compliance Belongs on the Client Side

When building B2B applications for European clients, data privacy isn't just a feature—it is a legal requirement. With the rollout of mandatory electronic invoicing across the EU (such as Belgium’s Jan 2026 mandate and France’s Sep 2026 reform) alongside strict GDPR enforcement, developers are faced with a dilemma:

How do you validate sensitive financial data (banking details, invoice totals, VAT numbers) without introducing server-side data liability?

The answer is 100% Client-Side Execution. By shifting parsing, XML serialization, and validation algorithms entirely to the browser in Next.js 14, you completely eliminate server logging, database retention, and GDPR payload overhead.

Here is an architectural look at how we built a zero-server EU compliance utility suite on FreeToolForge.


1. Generating Peppol BIS Billing 3.0 UBL 2.1 XML in the Browser

Peppol (Pan-European Public Procurement OnLine) requires invoice data to strictly match the UBL 2.1 XML schema and EN16931 European standards. Sending raw financial payloads to a backend API introduces data security risks.

To solve this, our client component builds the XML document object model locally before rendering:


typescript
// Client-side XML Escaping & Payload Construction
function escapeXml(str: string): string {
  return str.replace(/[<>&'"]/g, (c) => {
    switch (c) {
      case '<': return '&lt;';
      case '>': return '&gt;';
      case '&': return '&amp;';
      case '\'': return '&apos;';
      case '"': return '&quot;';
      default: return c;
    }
  });
}

// Generating compliant UBL 2.1 XML without server roundtrips
export function generatePeppolXml(invoiceData: InvoicePayload): string {
  return `<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
  <cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
  <cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
  <cbc:ID>${escapeXml(invoiceData.id)}</cbc:ID>
  <cbc:IssueDate>${invoiceData.issueDate}</cbc:IssueDate>
  <cbc:DocumentCurrencyCode>${invoiceData.currency}</cbc:DocumentCurrencyCode>
  <!-- Fully generated client-side -->
</Invoice>`;
}
You can test and generate valid UBL 2.1 XML files directly in your browser using our Peppol BIS 3.0 E-Invoice Generator.

2. Off-Thread Bulk IBAN & SEPA Validation (MOD 97)
Validating International Bank Account Numbers (IBAN) requires rearranging characters, converting letters to digits, and running a Modulo 97 calculation (checksum % 97 === 1).

When users paste hundreds of bank accounts at once, running this on the main UI thread can cause frame drops. We offload bulk string parsing to a Web Worker or memoized client routine:

Format Check: Regex validation based on ISO 13616 country structures (e.g., DE + 20 digits, FR + 27 characters).

SEPA Route Verification: Ensuring the country code belongs to the 36 SEPA zone nations.

Test bulk lists offline using the zero-log Bulk IBAN & SEPA Validator.

3. Lightweight, Zero-Dependency Cookie Consent Banners
Instead of pulling in heavy third-party tracking scripts that bloat your bundle size and trigger GDPR flags, web applications should use lightweight, zero-dependency cookie banners.

We engineered a client-side wrapper that manages consent state directly in localStorage without external telemetry. Try building your lightweight consent layout using our EU React Cookie Consent Generator.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)