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).
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.



