Web design 7 min read

Case study: how we built SAFTCheck -
a validator where the file never leaves the browser

The Dilys team 19 August 2026

Over the next few years almost every Bulgarian company will go through the same test: SAF-T. The standardised accounting file for the Bulgarian National Revenue Agency (NRA) is being introduced in waves from 2026 to 2030 under § 17 of the Transitional and Final Provisions of the Bulgarian State Budget Act for 2025: first large enterprises above the thresholds, and by 2030 everyone else, including VAT-registered micro-businesses. The rhythm is monthly: the file is submitted by the end of the month following the reporting month, and if it is rejected there are only 7 days to correct it. In other words, mistakes are costly and there is little time to react.

Against this backdrop our team built SAFTCheck, a free tool for checking SAF-T files with one unusual architectural feature: the file never leaves the user's browser. In this article we talk openly (the project is ours) about the decisions we made, why we made them and what we learned along the way. Not because we want to pat ourselves on the back, but because the same principles apply to any product that handles sensitive data.

If you are considering a similar tool for your business, this is the case study we wish we had read before we started.

The challenge: how do you earn trust when you are asking for accounting data

A SAF-T file is not just XML. Inside is the company's entire accounting for the month: account turnovers, balances, counterparties, documents. This is data that accountants, out of habit (and with good reason), guard like the apple of their eye. The classic SaaS model, “upload your file to us and we will check it”, starts with a huge handicap with this audience. Every upload to a server raises questions you have to answer: where does the data go, who has access, how long is it kept, what happens in a breach?

The second particularity of the task was timing. SAF-T arrives in waves and the market is only just taking shape: the first wave affects large enterprises from 2026, but the questions start much earlier. We wanted a tool that is useful from the moment an accountant first comes across the requirement, not only once they have a file ready to submit.

We framed the task like this: remove every barrier between the user and the check. No sign-up, no email, no upload, no price. Every barrier removed is one less reason not to try it.

The three decisions that shaped the project

The check runs in the browser

Validation runs locally through libxml2 compiled to WebAssembly. There is no server that accepts files, so there is nothing to leak.

A static site

Around 120 KB initial load, brotli compression, immutable cache. It opens instantly even on a work laptop over an office VPN.

Primary sources only

Everything on the site is based directly on NRA documents, not on second-hand summaries. When a topic is new, accuracy is the only currency.

Decision no. 1: the check runs entirely in the browser

We made the most important architectural decision at the very start: validation runs locally, in the user's browser, through WebAssembly. We compiled libxml2 (the same library that has been doing XML validation across the industry for decades) into a WASM module that loads the official NRA XSD schema (v1.0.2) and checks the file on the spot.

But the schema is only the start. XSD tells you whether a file is structurally valid, not whether it makes sense from an accounting point of view. So on top of it we added our own checks:

  • Balance equalities per account and matching TotalDebit/TotalCredit
  • Cross-references: every document must point to a counterparty that is actually declared
  • UTF-8 encoding and a file name that follows Annex 3
  • EIK check digit (the Bulgarian company ID): a small detail that can make an otherwise perfect file fail

Local processing pays off twice. For the user: nothing can leak because nothing is uploaded. The privacy promise is not a paragraph in a privacy policy but a property of the architecture, which anyone can verify in their browser's network panel. For us: there is no server processing other people's accounting data, and therefore none of the operational and legal burden that comes with it.

Decision no. 2: a static site instead of a platform

Since validation runs on the client, the server has nothing to compute. So the whole site is static: the initial load is around 120 KB, everything goes through brotli compression, and assets are cached as immutable. In practice the tool opens instantly even on a work laptop over an office VPN, which is exactly the environment our real audience works in.

The static architecture also let us be consistent all the way: the site has no cookies and no third-party trackers, and the analytics are our own and anonymous. It would have been absurd to promise that the file does not leave the browser while sending the user's behaviour to three advertising platforms.

Decision no. 3: content from primary sources only

The third decision is not technical but editorial: everything on the site is based directly on NRA documents, not on second-hand summaries. When a topic is new and stressful, accuracy is the only currency.

That is how a whole layer of helper tools grew up around the check itself. We built a reference of all 347 schema elements with the NRA's official descriptions, plus the code lists and the national chart of accounts. We added a “Which wave am I in?” calculator for the 2026-2030 deadlines, an error glossary with ten in-depth pages and an “Explain my error” paste-in tool, as well as an index of all 188 official questions and answers from the NRA document (version 2, 2026).

347schema elements with official descriptions
360accounts from the national chart of accounts, with search
188official questions and answers from the NRA
120 KBinitial load of the tool

The newest piece is a converter in beta: you feed in the trial balance and the chronological journal as CSV and get a monthly SAF-T XML, again entirely in the browser and free during the beta. It is the logical continuation of the same principle: if the check can be local, why not the compilation too? You can see it in action in the converter app.

What we learned

Speed is part of trust

We are used to thinking of speed as an SEO metric. Here it turned out to be more than that: a tool that opens instantly and works without sign-up sends a signal of seriousness. The reverse is also true: a slow site with an email form before the result says “you give us something first, then we give you something”.

Privacy is proven, not declared

The difference between “we do not share your data” and “your data physically does not reach us” is the difference between a promise and a fact. The second is harder to build, but incomparably easier to communicate: it can be explained in one sentence and checked by any technically literate user.

Primary sources are a competitive advantage

Content drawn directly from the schema and the NRA's official answers is slow, boring work. That is exactly why almost nobody does it, and exactly why it pays off. With a professional audience there is no stronger argument than quoting the primary source accurately.

What this means for you

If your business is considering a tool that handles sensitive data (financial, medical, personal), the SAFTCheck case comes down to three transferable lessons:

  • Client-side processing is now a realistic option. WebAssembly allows serious computation right in the browser. If the data should not leave the user, it no longer has to.
  • Not everything needs a platform. A static site with a smart front end can carry a fully fledged product: faster, cheaper and more secure than the equivalent SaaS when the computing is done locally.
  • Remove the barriers to first use. Sign-up, upload and price are three doors the user has to pass through before seeing any value. Every closed door costs you users you will never know you lost.

Not every product can (or should) run entirely in the browser. But the question “can this processing happen on the client?” deserves to be asked at the start of every project involving sensitive data. If the answer is “yes”, you get an architecture where trust is not built with words: it is built in. And if you are looking for a partner to ask that question with you, you know where to find us.

Frequently asked questions

Is the SAF-T file really not uploaded anywhere?
It is not. Validation runs locally in the browser through libxml2 compiled to WebAssembly. There is no server that accepts files. This is a property of the architecture, not a promise in a privacy policy, and anyone can verify it in their browser's network panel.
What does the tool check besides the structure?
On top of the official XSD schema of the Bulgarian NRA (v1.0.2) we added our own checks: balance equalities per account and matching TotalDebit/TotalCredit, cross-references to counterparties that are actually declared, UTF-8 encoding and a file name that follows Annex 3, as well as the EIK check digit (the Bulgarian company ID).
Why a static site and not a platform?
Since validation runs on the client, the server has nothing to compute. So the whole site is static: around 120 KB initial load, brotli compression and an immutable cache for assets. No cookies and no third-party trackers, otherwise the privacy promise would only be half kept.
When does SAF-T apply, and to whom?
It is being introduced in waves from 2026 to 2030 under § 17 of the Transitional and Final Provisions of the Bulgarian State Budget Act for 2025: first large enterprises above the thresholds, and by 2030 everyone else, including VAT-registered micro-businesses. The file is submitted by the end of the month following the reporting month, and if it is rejected there are 7 days to correct it.
Can this approach be applied to another product as well?
Yes, when the processing can happen on the client. WebAssembly allows serious computation right in the browser. The question “can this processing happen on the client?” deserves to be asked at the start of every project involving sensitive data, whether financial, medical or personal.

Keep reading

More
on this topic.

We picked articles from the same category. Looking for something specific? The blog has a search and a reading-time filter.

Web design5min

Brand identity: what it includes and why it is not just a logo

What brand identity really includes: logo, colour system, typefaces, tone of voice and guidelines. How the process works and when the investment pays off.

Read
Web design4min

What your website must have by law in Bulgaria: a 2026 checklist

Practical checklist of website legal requirements in Bulgaria: company details, GDPR policy, cookie consent and, for stores, terms and right of withdrawal.

Read
Web design4min

When is it time for a new website? 8 signs (and 3 cases when you don't need one)

The eight signs you need a new website, and the three cases where a redesign won't solve the problem. Plus how to keep your SEO history.

Read
All articles

Make your business
findable.

+359 882 95 89 89 office@dilys.bg 2A Tsar Asen St., Sofia
Free
consultation