Our offices

  • Exceev Consulting
    61 Rue de Lyon
    75012, Paris, France
  • Exceev Technology
    332 Bd Brahim Roudani
    20330, Casablanca, Morocco

Follow us

7 min read - Our Open-Source Framework Stack: Architecture Decisions Behind Exceev

Software Architecture & Open Source

Every framework decision is a bet. You're betting that this language, this runtime, this set of conventions will still make sense in three years — when the codebase is ten times larger, when half the team has changed, and when the requirements have drifted somewhere nobody predicted.

We've gotten some of these bets wrong over the years. But the stack we've landed on — TypeScript everywhere, Angular and NestJS as a matched pair, Next.js for content, Playwright and Jest for testing — has held up across dozens of client projects and our own products. The payoff is less onboarding friction, type safety from database to browser, and patterns that transfer between projects without rethinking. This post explains the reasoning behind each layer.

The TypeScript Bet

The most consequential decision we made wasn't choosing a framework. It was choosing a language.

TypeScript runs everywhere in our stack. Frontend, backend, build scripts, infrastructure-as-code, test suites. That sounds rigid, and honestly, it is. But the rigidity pays for itself.

When a NestJS API returns a ProjectResponse, the Angular frontend consumes the exact same TypeScript interface. Change a field in the DTO and the compiler yells at every consumer immediately — not QA three weeks later, not a customer filing a bug report. In a monorepo, this alone kills entire categories of integration bugs.

The other thing that matters at a consultancy: people move between projects constantly. Scopes shift, someone goes on leave, a new engagement starts that needs hands. When everyone writes TypeScript, an Angular engineer can review a NestJS pull request without context-switching into a different language. A backend person can jump into the frontend and fix a bug without a two-day ramp-up. One linter, one formatter, one test runner, one package manager. The muscle memory carries.

Is TypeScript the best language for every task? No. Python wins for ML. Go compiles to tiny binaries. Rust gives you memory safety we can only dream about. We reach for those when the job demands it. But 90% of what we build is web apps, APIs, and tooling — and for that, one language across the board beats a polyglot stack every time.

Frontend-Backend Symmetry

Angular and NestJS weren't chosen independently. We picked them as a pair, because they think about code the same way.

Both are module-based — Angular's standalone component imports and NestJS's module system draw the same boundaries around features. Both are decorator-driven — @Component, @Injectable, @Controller, @Guard — so the mental model transfers directly. Both are opinionated about where things go. Routes, services, guards, interceptors, pipes: each has a canonical home. A new engineer can navigate the codebase on day one without a guided tour.

That opinionation is the whole point. When we scaffold a new project, nobody is debating folder structure or bikeshedding naming conventions. The framework already decided, and we agreed to follow it. That frees up the architecture conversations for things that actually matter.

Angular for Product Interfaces

FormAI, our AI-powered form builder, runs on Angular. So does SoarUI, our open-source component library. Angular is our default for anything with complex state, deep component trees, and a maintenance horizon measured in years.

The recent evolution of Angular has made this easier to justify. Signals give us fine-grained reactivity without bolting on a state management library. Standalone components killed the NgModule boilerplate that used to make Angular feel heavy. And Angular's upgrade story — deprecation policies, migration schematics, predictable release cadence — matters a lot when you're maintaining enterprise codebases that need to last.

NestJS for APIs and Services

NestJS mirrors Angular on the server side. Controllers map to components. Services are injectable. Guards and interceptors handle cross-cutting concerns. If you know one, you can read the other.

The practical upside: code reviews get better. A frontend engineer reviewing a backend PR already understands the patterns. The shared vocabulary — modules, providers, guards, interceptors — means design conversations don't need a glossary.

NestJS also buys us transport flexibility. The same service logic works over HTTP, WebSockets, gRPC, or message queues. When a project starts as a REST API and later needs real-time features, we don't redesign — we add a transport layer.

Where Next.js Fits

Yes, we run two frontend frameworks. People ask about this.

The split is simple: Next.js handles content, Angular handles applications. This website, our blog, marketing pages — all Next.js. The priorities there are SEO, static generation, and writing content in MDX without fighting a build system. Next.js does that well. File-based routing, image optimization, SSR — it's built for exactly this kind of surface.

FormAI, SoarUI, client dashboards — those are Angular. Complex state, deep interaction, component reuse. Different problem, different tool.

We don't use Next.js for apps. We don't use Angular for content sites. The overlap is basically zero, and the cost of maintaining two frameworks is small compared to the cost of forcing one framework into a job it wasn't designed for.

How We Test

Two tools, clear boundary between them.

Jest covers everything below the browser. Service logic, utility functions, API endpoints, database queries, component rendering in isolation. For Angular we pair it with Angular Testing Library; for NestJS, the NestJS testing module. Same assertion API, same mocking approach, same config. An engineer switching projects doesn't need to relearn the test suite.

Playwright covers everything in the browser. We switched from Cypress about eighteen months ago, mostly because Cypress kept lying to us — flaky tests, cy.wait(2000) hacks everywhere, and real cross-browser testing was basically impossible. Playwright gave us Chromium, Firefox, and WebKit from one suite, reliable auto-waits, multi-tab support for OAuth flows, and parallel workers that run our E2E suite in 3 minutes instead of 12.

The rule is strict: Playwright tests user flows (authentication, data submission, multi-step workflows). Jest tests units and integration. We don't let them bleed into each other's territory. That boundary is what keeps both suites fast and maintainable.

Why This Matters More Than Any Single Choice

None of these tools are the objectively "best" option in their category. You can find benchmarks where another framework wins, blog posts arguing for a different testing tool, and valid reasons to pick a different language. We know. We've read them.

But the value isn't in any one tool. It's in the fact that they all work the same way. Onboarding takes days instead of weeks because the patterns are already familiar. An engineer on one project can review a PR on another project and actually catch real issues. Shared libraries — validation, auth flows, API clients, UI components — move between projects without rewriting. When something breaks at 2 AM, the person debugging already knows where to look.

That consistency is the architecture decision that matters most at Exceev. Not which framework is theoretically best, but which set of frameworks creates the most value when used together, across dozens of projects, over years.

If you're evaluating your own stack — whether you're starting a consultancy or rethinking an existing one — optimize for the set, not the parts. The best framework is the one your team can use well everywhere. And if you want a second opinion on your stack, we're happy to talk.

Curious about our stack?

We build with open-source tools and contribute back. Take a look at what we've shipped.

More articles

Running a Consultancy on Open-Source Business Tools: Our Operations Playbook

How Exceev runs its business operations on Twenty CRM, ZeroMail, n8n automation, Ghost publishing, Cal.com scheduling, and Postiz social publishing. An operations playbook for consultancies that want control over their business stack.

Read more

Self-Hosting Our Infrastructure: The Observability, Security, and Deployment Stack

How Exceev self-hosts its infrastructure with Grafana, Prometheus, Loki, k6, Coolify, Infisical, Docker, Tailscale, Cloudflared, Beszel, and Duplicati. An operational deep dive into observability, deployment, security, and resilience.

Read more

Tell us about your project

Our offices

  • Exceev Consulting
    61 Rue de Lyon
    75012, Paris, France
  • Exceev Technology
    332 Bd Brahim Roudani
    20330, Casablanca, Morocco