Investment Platform Case Study
Problem
The client is a French company operating in the investment space that wanted an all-in-one platform where its investors, onboarded individually, could follow the entire investing flow in one place: from identity verification (KYC / KYB) to reviewing the specific investment opportunities made available to them (along with their related information), all the way to signing the investment contract in an embedded way.
Another key requirement was administrative control. Access to opportunities is never open by default: admins individually decide which opportunities each user is granted visibility into, and differentiate action types and fees on a per-user basis.
First Thoughts
The first decision was which CMS to use. We'd worked with tools like Strapi on similar use cases in the past, but this platform needed something lower-level and more customizable. We settled on Directus, which looked like the best option on every axis that mattered: file management, user permissions, and the ability to implement automated, data-driven actions without writing a line of code.
The most logical choice for the tech stack was Next.js, so that frontend and backend could live in a single project. That translates directly into more efficient development: one project means the team doesn't need to juggle multiple languages, type safety comes out of the box, and there's generally less time lost to glue work.
Since we're proficient with SQL, we chose Supabase for the Postgres database.
With that, everything was in place:
- Directus: the CMS that lets admins create, edit, archive, and delete investment opportunities, manage users, and store and download files, all directly through the UI, without a line of code.
- Supabase: the Postgres database that Directus connects to.
- Next.js: for building the frontend and interacting with Directus.
Modus Operandi
With the design phase done, the rest was implementation, which we tackled in the order listed above.
First, we set up two separate environments: pre-production and production. Each Directus instance had its own domain, as did each web app. This was straightforward to set up and let us keep building and shipping features cleanly, without stepping on the live environment.
We didn't run into any major roadblocks, the tech stack worked in our favor throughout.
The most interesting feature was giving a user the ability to have sub-users. The original goal was to let a single personal account own multiple business accounts. After weighing a few approaches, we found that the best solution was not to fight Directus but to use it to our advantage.
Directus only accepts conventionally formatted email addresses, so we couldn't invent an arbitrary identifier scheme. Instead, we encoded the information we needed inside a valid-looking address, using the pattern:
<base_email>.<shared_subuser_suffix>.<custom_name>.com
<base_email>: the parent account the sub-user belongs to.<shared_subuser_suffix>: a fixed marker, identical for every sub-user, that flags the address as a sub-user in the first place.<custom_name>: the name the user assigned to that sub-user.
From the address alone, we could then resolve all three: that it's a sub-user, which parent it hangs off, and its custom name, all while staying within a format Directus would accept.
Once the base platform was built, we started layering additional features on top. Email notifications were one example: as mentioned, Directus made this easy. We implemented each email trigger in a no-code fashion and integrated it with an external email provider.
Changes
Several changes were made to the original scope. The most significant was adding an admin dashboard, giving admins a place to perform key actions directly: sending email reminders, consulting documents, and viewing aggregated information about a user and their related sub-accounts.
Team
The whole project was realized before NFW Web Agency even existed. Despite that, both developers on the current team were involved. The web design was done fully in-house, with certain elements, namely the color palette and fonts, specified by the client from their existing design system.
Numbers
Over the platform's lifetime to date, its admin-managed investor base has grown to more than 100 individually onboarded investors, primarily based in France. It manages more than €4M in assets, across 35 investment opportunities and 27 unique roles.
Lighthouse / Speed Insights
Given the nature of this platform, a public Speed Insights score isn't meaningful, the full feature set sits behind a login.
That doesn't mean we ignored performance; we did the opposite. We minimized blocking calls by embedding everything needed to understand a user's permissions and data directly into the user context. That data is then available with no additional round-trips, the tradeoff being that the user token has to be kept continuously up to date.
Lessons Learnt
This is still an actively managed, actively developed project. It began in November 2024 with a v1 (not covered in this case study), migrated to v2 in January 2025, and has been developed continuously since. It's one of the most extensive and feature-rich projects we've worked on, if not the most, and we're grateful that Valeureux trusted us with it.
Being honest about it, though, the biggest thing we'd do differently is testing. We shipped the early versions without automated tests. With a small, contained feature set that felt like a reasonable call at the time, but as features accumulated, verifying everything by hand on each deployment became unmanageable, and a manual pass inevitably misses things. The result was that, in its first months, the platform wasn't always stable: never fully down, but with individual features occasionally not behaving as expected, which made the early experience less predictable than it should have been.
The important part is that we understand exactly why it happened and what prevents it. Automated tests covering each core flow, login, the investment flow, document uploads and downloads, and the rest, should have been in place from day one, and are the kind of safeguard that's cheap to add early and expensive to retrofit late. The instability only ever surfaced while the user base was small and the platform was in its earliest stages; the lesson we took from it now applies to everything we build.
