I'm Finance Ops, not a developer. I built a KoSIT-valid XRechnung generator in the browser anyway

Published: (February 21, 2026 at 05:56 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Background

My day job is Finance Ops and accounting, not software engineering. In the DACH region the gap between what accountants need and what developers build is real—and expensive—so I decided to close it myself.

The Regulatory Context

Germany’s E‑Rechnungspflicht is no longer theoretical.

  • B2G (Business‑to‑Government) invoicing has required a valid XRechnung for years.
  • B2B rollout is phased: reception from 2025, issuance for > €800 k revenue from 2027, and broad adoption from 2028.

A PDF— even a perfect one— is not enough.

Existing Solutions

Every tool I found fell into one of three categories:

CategoryExampleDrawbacks
Enterprise ERPSAP, DATEVFull XRechnung support, but costs hundreds of euros/month; built for teams, not freelancers
SaaS invoicingLexoffice, sevDeskSubscription‑based; invoice data lives on their servers; lock‑in by design
CLI toolsOpen‑source Java/Python librariesAssume you know how to run java -jar or similar command‑line tools

The Missing Middle

Freelancers, one‑person consultancies, and Kleinunternehmer who need to invoice public authorities (e.g., the municipality of Hamburg) once a quarter lack a suitable, low‑cost solution. That’s who I built this for—also for myself.

Solution: Browser‑Native XRechnung Generator

  • Zero‑server, zero‑account: All processing happens locally in the browser; no data leaves your machine.
  • Live demo: (local‑first, zero tracking)
  • Validation: KoSIT Validator v1.6.2 (Config v3.0.2) + EN 16931. Supports both UBL 2.1 and UN/CEFACT CII syntax.
  • Source code: (MIT license)

Key Characteristics

  • Invoice data (client names, project descriptions, amounts, IBANs) is high‑signal.
  • XML generation, PDF rendering, and pre‑validation run entirely in the browser.
  • Network traffic: Zero outbound requests (verified via DevTools Network tab).

Development Approach

My role is more architect/orchestrator than “code‑all‑day” developer. The workflow:

  1. Read the EN 16931 spec and map the domain model into TypeScript types.
  2. Define validation rules based on the spec.
  3. Implement the generator, keeping the domain model syntax‑agnostic (produces both UBL 2.1 and CII from the same Invoice object).

AI Assistance

Parts of the implementation were AI‑assisted (Claude Code / Codex) under my architecture, with manual review and validation loops. This forced a deep understanding of the standard because you cannot “prompt your way past” a KoSIT schema validation error you don’t understand.

Hardest Challenge

Building a typed domain model that outputs both UBL 2.1 and CII without branching logic everywhere. The same invoice object yields two syntax outputs, keeping the core model clean.

Deployment

  • Every push to master triggers a GitHub Actions workflow that builds and deploys to Cloudflare Pages.
  • No servers, containers, or databases are involved.
  • Static assets are cached at Cloudflare’s edge, resulting in near‑zero latency (“the file is already there”).

Lessons Learned

  • Read the full EN 16931 + CIUS context before touching any code.
  • XRechnung is not “just XML with German quirks.” It layers EN 16931 Core, CIUS, and KoSIT profile requirements.
  • URN identifiers alone took two days to get right and are a common cause of validation failures even when invoice data is correct.
  • Typed constants (const values in TypeScript) eliminated an entire class of errors—worth knowing upfront.

Call for Feedback

If you’ve worked with XRechnung, EN 16931, or Peppol:

  • What validation errors do you see most often in production?
  • Do your clients’ ERPs consume UBL or CII?
  • What is the one missing feature that would make this generator useful for you?

Technical Breakdown

A full architectural and code walkthrough is available at:

0 views
Back to Blog

Related posts

Read more »