How We Accidentally Ended Up in Regulatory Fintech
or: what happens when a director comes back from a meeting with a word nobody in the office has heard before
How We Accidentally Ended Up in Regulatory Fintech
or: what happens when a director comes back from a meeting with a word nobody in the office has heard before

A consulting director returns from a client meeting — a client we had already delivered an RDM solution to, a data mapping tool that was doing its job. A normal meeting, a normal client. Except for one small thing.
“There’s something called XBRL coming. Regulation for listed companies. I think we could add it as a module.”
Nobody in the room knew what XBRL was.
The logic made sense on the surface — it’s about mapping financial data to elements of some taxonomy. Sounds like something the RDM tool already does, just with a different output. A new module, a few weeks of work, done.
My colleague, the lead dev, and I — somewhere between junior and mid at the time — were given the task to investigate. We opened the first XML files.
There was a lot in there.
It was 2020, corona, lockdown. The entire team went remote overnight, like everyone else. But for the two of us, that actually meant something unexpected — days of pair research sessions, sharing screens and trying to figure out what XBRL even was.
XML files were the first contact. And there were many. ESEF builds on top of the IFRS taxonomy, which means you don’t just download one file and get to work. There’s an entire hierarchy — linkbases, labels, presentations, calculations. Every element has its URI, its relationships, its contexts. We slowly started to understand the structure.
Our first assumption was logical: only elements that exist in the taxonomy can be used for tagging. No custom tags, no shortcuts. The taxonomy is the law.
With that understanding, we built the first screen. On the left side — a table, loaded from Excel. On the right — the taxonomy in a treeview. The user finds an element, drags it onto a table cell. Drag and drop. Simple to use, complex under the hood.
Somewhere in that period we came across competition. Arelle — an established player in the market. We looked at how they approached it. A bit of reverse engineering, as much as was feasible. Not to copy — but to understand what the market standard looked like, and where we could be better and more practical for the end user.
The first version worked. Synchronous generation, tagging of financial statements, extensions for elements that didn’t exist in the standard taxonomy. For a start — enough.
But users quickly showed us where the limits were. Nobody builds financial statements in Excel from scratch — everyone has Word documents. Years of established processes, templates, formats. “Can we upload a Word file?” Sure. We added the ability to upload a Word document and insert tables that had been prepared in Excel. Excel plus Word — that combination lived for a long time, longer than we expected.
Somewhere in that period we got in touch with XBRL Europe. We had sessions with Michal, a developer from Poland who knew the standard well. The first conversation was — looking back — a little embarrassing. We were asking questions that revealed we still didn’t understand the depth of the problem. Michal, politely but directly, let us know that what we were trying to do wasn’t trivial.
A few months later we called him again. This time the questions were different — hypercubes, dimensions, contexts. Technical questions that only come from someone who has really dived into the standard. Michal told us he was surprised. Two developers, a few months, and a functional product covering a solid portion of the ESEF specification.
That was one of the rare external validation moments in that period.
The next iteration brought text tagging — notes, textual values that weren’t in tables. JavaScript, partly jQuery, integrated into the existing interface. And that’s when we integrated Arelle for the first time — an open source XBRL processor we called from the application to validate the generated ZIP. If Arelle says it’s fine, it’s fine.
Arelle was telling us the output was valid. But “Arelle says it’s fine” and “the product is certified” are not the same thing.
XBRL International has a software tool certification program — a formal confirmation that an implementation correctly interprets and generates XBRL according to the specification. We decided to go through that process relatively early, while we still had only a handful of clients. The reason was practical — certification was a selling point. In conversations with potential clients, especially those who understood what XBRL was, “we’re certified by XBRL International” closes a lot of questions at once.
It went surprisingly smoothly. Which, looking back, was a good signal — not that the process was easy, but that in those pair research sessions and conversations with Michal we had actually understood the standard well.
Sales picked up. Around twenty instances, each onprem, each client their own server, their own VPN, their own way of connecting. Installation per client — at least half a day, even with an installer. And the application was still in heavy development, meaning updates came frequently. Every update, every fix, every new feature — multiply by twenty.
A mess.
Two banks stayed on onprem by choice — with them, the story is its own category. Installing and maintaining software at a bank is a project in itself, with tickets, approvals, and waiting. Everything else migrated to a single instance in the cloud. Each client sees only their own reports — not multitenancy in the true sense, but enough to bring the maintenance problem down to something manageable.
And that’s when Docker entered the picture. On a Windows server. Because of one Linux tool.
There was a problem we hadn’t anticipated. Financial reports weren’t written by clients themselves in Word — they were done by designers. Nicely formatted documents, publicly published, branded. Word-to-HTML conversion lost pages, formatting, layout. Not an option.
pdf2htmlex was the answer. PDF to HTML conversion almost one to one — fonts, positioning, visual output that looks like the source. For most documents — excellent. For some special graphics and fonts — the limits showed, but were acceptable.
The problem was underneath the surface.
What the user sees as a table — rows, columns, cells — in pdf2htmlex output is a pile of span and div elements. Sometimes individual letters in their own span. No semantic structure, just positioning by x and y coordinates. For XBRL tagging you need a table element. Between those two states stood a non-trivial problem.
That’s where I took the lead.
I researched mathematical models, papers on element grouping, clustering by spatial coordinates. In the end I built a configurable multi-step process. The user draws a rectangle around what looks like a table — like a marquee selection on a desktop. They enter the number of columns. The system automatically detects rows, merges elements that together form a cell, even text that wraps across multiple spans. Where the automation wasn’t confident — the user can manually resize columns, merge rows.
The output was a table element whose style was almost identical to the source. To the eye — an imperceptible difference.
Every cell of that table was saved to a SQL database with its path to the HTML element. And then — the same screen as before. The client tags. Only now from a PDF that a designer made, not from Excel.
Somewhere in that period it became clear that what we had built wasn’t a module. It was a product. And a product running on twenty servers demands a different architecture.
But that’s already another story.
메타데이터
- post_id
- 76c773a13eec
- slug
- how-we-accidentally-ended-up-in-regulatory-fintech-76c773a13eec
- url
- https://medium.com/@curic.bernard.inf/how-we-accidentally-ended-up-in-regulatory-fintech-76c773a13eec
- canonical_url
- https://medium.com/@curic.bernard.inf/how-we-accidentally-ended-up-in-regulatory-fintech-76c773a13eec
- author_url
- https://medium.com/@curic.bernard.inf
- status
- ok
- fetched_at
- 2026-06-22 05:41:33