« Back to all articles

Building a softphone: a journey from PoC, MVP to MLP

Written by Jeroen van Veen on 21st June 2018

After we finished our initial cleanup process of the Vialer-js Click-to-dial plugin a year ago, no one would have thought that the project would progress to what it is today. It transformed in a relatively small timespan, between January 2018 and May 2018, into an alpha-quality WebRTC softphone, introducing major changes in architecture, design, and UX.

How did this happen?

There were some indications that something like this was about to happen, namely:

  1. WebRTC/OpenBTS R&D that investigated WebRTC calling with SIP.js and Asterisk.
  2. Replacement of SipML5 with SIP.js in Vialer-js; We used SipML5 for presence information in Vialer-js back then. SIP.js would make it much easier for us to implement new features(calling) later.
  3. The VoIPGRID platform started to support WebRTC audio calls.
  4. A PoC Vialer-js branch was made to demonstrate audio calls with WebRTC.

This Vialer-js PoC dealt with the bare minimum of calling functionality; SIP REGISTER and handling basic SIP.js call events. As soon as a user would be called in the PoC, one would immediately be part of the call, without the option to deny or pick up the call. There was no option to transfer a call to a colleague, to hold a call, to mute the microphone or to choose which device should be used for headphones, ringtone & microphone. In short, most of the essential functionalities of a softphone were still missing. What the PoC did show was how easy it is to utilize WebRTC and Sip.js to set up a call with from A to B, using just a browser; given that the right SIP infrastructure is in place already.

Replace the hardphones

It would still require significant work and considerable planning to get it ‘right’, but the main goal – sparking enthusiasm with the right people – was met and unexpectedly induced in a short time to the planning of a secretive project within Spindle; the Vialer-js softphone. The project’s purpose was to provide a hardphone replacement for one of our main partner’s customer support division, when they would move to their new location in March 2018. This meant that we had a development period of less than three months to build an MVP!



Defining the project

To get a grasp of the involved work, Tim and I started early January 2018 by creating a small project definition; defining scope, expectations, technical limitations and responsibilities of the involved people. From the start, we had intensive talks with our partner’s early adopters. This was of great use to keep people on the same page, and to make sure that we would build the right thing from the start. After we roughly agreed on what to build, we immediately got started with a small development team (JavaScript: Jeroen/Redmer, UX: Antoine, Backend: Jasper). Antoine was building Invision mockups at lightspeed, while I was further refactoring the codebase to allow faster iterations.

The approach

To be able to iterate on a user interface quickly, we needed a view library that would replace the legacy Jquery DOM manipulation. Also, we needed a more centralized and coherent way to handle state, because of the way that a WebExtension has to communicate between its background and foreground scripts. Due to time pressure and lack of consensus, Jeroen took a unilateral decision to use Vue and to build a simple state management system, that relies on Vue-stash. This simple approach turned out to be good for the project’s progress so far but caused some friction that we were able to resolve later. We all agreed that the project’s progress should predominate.

Involve the users

Also, we were involving our early users in the decision-making process from the start, and I think we did a pretty good job listening to their wishes and reported issues so far. This translated almost instantly to new mockups, which then were implemented at a fast pace, because we got rid of the last technical debt. Our first MVP milestone included attended transfer and on-hold functionality, which would allow our first users to start testing the softphone in a real-life support environment.

The test period

During this test period, we learned a lot from our users; strengths, weaknesses, and pitfalls of a WebRTC softphone that lives as a WebExtension in the browser. We learned about:

  • Optimal user workflows for extensively used calling features
  • Potential network issues (WIFI/UTP, USB-c, power management, dealing with online/offline) and network requirements
  • OS-specific bugs in Chrome for Windows, MacOS, Linux, and Chromebook
  • Microphone configuration issues: headset/Bluetooth dongle issues, device detection improvements, pulseaudio issues and sink selection options with WebRTC
  • A blocking issue that prevents us from applying our softphone functionality to Firefox

This was all extremely valuable to us in order to be able to improve Vialer-js. All in all, we wouldn’t have been that far yet, without the feedback from our first early adopters. A big thank you to you guys and girls!

Stability issues

We succeeded in making about 10 early adopters use our softphone for their daily work. But, as the project progresses, we started to encounter some troubling stability issues which make it harder to keep our first users aboard. Software should make our user’s work easier. A user is quick to determine whether the software is worth investing time in or not. Having to deal with software inconsistencies makes it more likely that a user will abandon the software. Thereafter, it will be more difficult to gain trust and to maintain a positive image of the software.

Introducing stability tests

So, to fight stability issues, we were introducing unit tests and regression tests. This makes us more confident about introducing new features, without breaking existing ones. Also, we added exception logging to capture software errors in realtime, and we are looking for a good way to get insight in a user’s RTP stream statistics in order to analyze potential sound quality issues. This will also be useful for future customer support, because it makes it easier for support to analyze reported problems and help customers.

Minimal Lovable Product

While contemplating about the end-product, it seems obvious to us now that an MVP is not the state of an application that we want to give to your end-users. Instead, we focus on progressing the MVP to a so-called Minimal Lovable Product (MLP) first, i.e. to make the software experience a more positive and coherent one. This will put less stress on support and will lead to a better experience for the final customer.

Moving forward

The coming months will be spent focussing on achieving this MLP with our early adopter test group. We are also determined to involve the open source community in this project, by modularizing and separating the last hardcoded VoIPGRID-specific functionality from Vialer-js, so that a general-purpose core softphone remains which can be used to connect to any provider that has SIP-over-WebSocket endpoints.

We believe that, when done right, this could be a tremendous opportunity for us to launch a new product that’s loved and used by a wider audience. It benefits the quality, stability, and security of the product, and will translate directly in more happy customers. To be continued!

Your thoughts

  • Written by Tristar on 23rd June 2018

    Thanks so much for the post.Much thanks again. Really Cool.

Devhouse Spindle