cjjutba
Back/Work

Fiscplus

A production, multi-tenant SaaS that replaces the email-and-spreadsheet chaos of a Belgian accounting practice with a single source of truth - three role-scoped portals, real-time collaboration, and a full Belgian anti-money-laundering compliance module.

Type
SaaS · Web App
Role
Solo Full-Stack Build
Built
2026
Client
Confidential - Belgian accounting firm
React 19NestJS 11Prisma 7PostgreSQLRedis / BullMQSocket.io
Private client project — source & URL withheld
3
Role-scoped portals
36+
Feature modules
80+
Real-time events
92+
RBAC permissions
01

Why I built it

A Belgian accounting practice ran its fiscal periods on a patchwork of email threads, shared drives, spreadsheets, and manual chases. Client onboarding, document collection, VAT and tax cycles, and anti-money-laundering compliance all lived in disconnected tools with no single source of truth - so the real state of any client was whatever someone could reconstruct from their inbox that morning.

Regulated work raises the stakes well past inconvenience. ITAA professional norms and the Belgian Anti-Witwaswet (AWW / AML) demand auditable identification, screening, and record-keeping - the kind of trail ad-hoc tooling simply cannot guarantee. A missed recheck or an unrecorded decision is not a tidy-up task; it is a compliance exposure.

Fiscplus exists to collapse that sprawl into one auditable system of record: a single place where the firm, its staff, and its clients work from the same data, and where every meaningful action leaves a trace. The product's job is to make the correct, compliant path also the easiest one.

Fiscplus poster - 'One source of truth for the whole firm': the admin dashboard replacing email-and-spreadsheet chaos with a single auditable system
02

The three portals

Fiscplus is one codebase serving three role-scoped portals. Admin runs firm operations and oversight; Assistant handles delegated work and task management; and Client is a multi-company self-service space for the accounting firm's own clients. Each audience gets an interface shaped to its job, rather than a one-size-fits-all dashboard with half the buttons greyed out.

Underneath, a single shared, type-safe API layer serves all three. Each portal exposes only the modules and actions its role requires, but they are not three separate apps - they are three views onto the same domain, which is what keeps them from drifting out of sync as the system grows.

Access is governed by granular RBAC: 92+ permissions with per-user overrides on top of role defaults. A firm can delegate precisely - this senior assistant may approve documents but not edit AML decisions - without inventing a brand-new role for every exception.

Fiscplus poster - 'One codebase, three role-scoped portals': Admin, Assistant, and Client views from a single type-safe API
03

The AML (AWW) compliance module

The hardest part of the build is a complete Belgian AWW (Anti-Witwaswet / AML) compliance lifecycle. It covers client identification, KBO and VIES business-registry validation, UBO (Ultimate Beneficial Owner) declaration, PEP, sanctions and adverse-media screening, and a four-pillar risk-scoring model that turns all of it into a defensible risk band.

Compliance is not a one-time form, so the module treats it as a living process: it generates engagement letters, schedules periodic rechecks, runs ongoing vigilance monitoring, and stores an investigation-file vault with configurable retention. When a PEP or sanctions hit surfaces, it becomes a tracked item with a required resolution, not a footnote someone hopes to remember.

Every step is auditable by construction. The point of a regulated module is not just to do the checks but to be able to prove, later, exactly what was checked, when, by whom, and on what evidence - so the whole lifecycle is built to be replayed.

Fiscplus poster - 'Belgian AML compliance, by the book': four-pillar risk scoring, UBO and PEP/sanctions screening, fully auditable
04

Real-time collaboration

Because three portals work the same data at once, the system has to keep them honest in real time. A firm administrator approving a document, an assistant updating a client's status, a client uploading a missing file - each change has to show up everywhere it matters without anyone hitting refresh.

Fiscplus does this with an event-driven core: every mutation emits a domain event, a WebSocket gateway broadcasts it to the interested portal rooms, and subscribers invalidate exactly the affected query keys - with own-action de-duplication so the person who made a change doesn't get an echo re-render. Across the system that is 80+ domain events driving optimistic, always-current UI.

The result is that 'the same truth, everywhere, instantly' is a property of the architecture rather than a slogan - which, for a compliance tool where stale data is a liability, is exactly the point.

Fiscplus poster - 'Everyone sees the same truth, in real time': a mutation in one portal broadcasting domain events to the others
05

Architecture

Fiscplus is a React 19 and Vite single-page app - TanStack Query for server state, Zustand for session state - talking to a modular NestJS 11 API over REST and WebSocket. Data lives in PostgreSQL via Prisma 7, with Redis for cache, queues, and pub/sub, BullMQ for background jobs, and 20+ scheduled cron tasks handling rechecks, reminders, and lifecycle work.

It is type-safe end to end: TypeScript strict throughout, Prisma-generated types flowing from the database through the service layer, and Zod plus class-validator enforcing the same shapes at the API boundary at both runtime and compile time. A shape change is a compile error, not a production surprise.

The deliberate split - a thin, presentational frontend over a backend that owns all logic, data, and secrets - is what lets one engineer reason about a system this size without it collapsing into spaghetti.

06

Key decisions

Four architectural choices shaped the whole system, each made in service of the same goal: software a regulated firm can actually trust.

Real-time, event-driven sync

80+ domain events drive optimistic UI and cross-portal cache invalidation. Every mutation emits an event; the WebSocket gateway broadcasts to interested rooms; subscribers invalidate only the affected query keys - with own-action de-duplication to prevent echo re-renders.

Granular RBAC

92+ permissions with per-user overrides on top of role defaults. The permission engine checks both role-level grants and explicit per-user allow/deny entries, so firm administrators can delegate precisely without creating new roles.

Type-safe boundary

Zod schemas on the API boundary and class-validator decorators on NestJS DTOs enforce the same shape at both runtime and compile time. Prisma-generated types flow from the database through the service layer to the React Query hooks - no manual casting.

Auditability by default

Every sensitive mutation (client records, AML decisions, document uploads, permission changes) is logged to an append-only audit trail. The log captures actor, timestamp, before/after state, and the originating request - making compliance reviews straightforward.

07

The outcome

One accountable engineer delivered an agency-scale, regulated SaaS - three role-scoped portals, a full Belgian AML compliance module, and real-time collaboration - to production. The firm replaced its spreadsheet-and-email workflow with a single, auditable system it owns outright, code included.

The deeper result is what the build demonstrates: that compliance-grade software - the kind usually associated with large vendors and long timelines - can be designed, built, and shipped by one engineer working closely with the people who depend on it, without cutting the corners regulation does not allow.

Up Next

AuraHire

Explainable, fair AI recruitment - every score shows its work.

AI Platform · Web App
Open to work

Have a project in mind? Let's build it.

I'm available for freelance projects, and open to the right full-time role.

I build web apps, SaaS, and MVPs for founders and startups. Tell me what you're working on.