Scout APM is PHP application performance monitoring designed for developers. With tracing logic that ties issues back to the line of code causing them, you can pinpoint n+1 queries, memory leaks, and other abnormalities in real time so you can knock them out and get back to building a great product. Start your free 14-day trial today and get the performance insight you need in less than 4 minutes.

Building Mailcoach

Original – by Freek Van der Herten – 12 minute read

Today, our team released Mailcoach, a beautiful, self-hosted mailing list manager. It integrates with services like Amazon SES, Mailgun, or Sendgrid to send out mailings affordably. It’s packaged as a stand-alone app, or can be integrated into a Laravel project, it's perfect for bloggers, artisans, and entrepreneurs.

Even if you're not in the market for an email solution, Mailcoach includes a video course on how it’s built. I'm sure you'll see some valuable techniques that you can bring to your own project.

In this blogpost, I'd like to share why and how we've built this.

The origin story

Phase one: feeling the pain

Building mailcoach is a clear-cut case of scratching my own itch. A few years ago, I started to send a bi-weekly newsletter on Laravel, PHP, JavaScript, and whatever keeps me busy.

For the first few editions I just used Mailchimp, and everything was fine. People seemed to like the content, and my subscriber base grew over 2 000. If a list grows larger than that number Mailchimp isn't free anymore, and you'll have to pay $29,99 a month.

For a business that cost could be fine, but for a personal newsletter, that doesn't make any revenue on its own, paying $359,88 a year is too much. For a while, I lived with this. But when my newsletter grew even more, and yearly costs grew to $600, it was time to move to something else.

I found an alternative in Sendy, a self-hosted solution for sending out newsletters. It uses AWS to send out emails, which is way cheaper than Mailchimp. An email sent using AWS only costs $0,0001. So my monthly bill suddenly dropped from $600 to only a few dollars. Sendy doesn't look nearly as polished as Mailchimp, but the low costs for sending out emails made me stick with it. For a while, everything was fine again.

As time passed by, my email list kept growing. A few months ago, my server started to have problems every time I sent out a newsletter. Up until this day, I'm not 100% sure what caused this problem, but I have a heavy suspicion that it was caused by the large amount of incoming requests to track opens and clicks, right after a newsletter was sent out.

I decided to investigate the problem inside the Sendy code base. But after opening a few source files, I quickly gave up. With all due respect to the creators of Sendy (they launched quite a successful product), this is PHP code from a different era. Each screen is handled by its own PHP file, there is PHP code mixed with raw SQL queries and HTML, and includes are used all over the place.

Immediately after looking at the Sendy source code, I thought, how hard can this problem be? I opened PhpStorm and started building my own solution.

Phase two: from a hobby project...

My initial idea was to create an open-source package called laravel-email-campaigns. After having worked in secret on Flare for months, it felt good to work in the open again. Scratching your own itch is fun!

In the span of a few weeks, I fleshed out all functionality. Sending the mails via email service providers, tracking opens, tracking links, tracking unsubscribes, and so on... I don't want to take all the credit for it. I get feedback on the open-source parts from my colleagues too, which made the package better.

At the start of October 2019 I thought the package was done, so before actually releasing it, I started using it myself for a couple of things. At that time, there was no UI; everything had to be done in code. This became old very fast, so I decided to start working on a UI.

Maybe it's because I lack experience, but generally I feel that creating a UI is much more work than coding up backend logic. There are people in my team, like Willem and Seb, who can do a much better job than me, so I asked for their help.

Phase three: ... to a full product

Even for my front end colleagues, creating a beautiful, polished UI can take quite some time. It was clear that, if this package remained open-source, it would take a very long time to complete. So, we decided to make a full-fledged product. laravel-email-campaigns is a fine package name, but it falls short as a product name that speaks to the imagination. Willem came up with the name Mailcoach, and he built a small promotional site that we shared with the world.

We broadened our scope. Initially, Mailcoach was only intended to work as a package to be installed in existing Laravel apps. But we wanted it to be easy for people with less (or no) experience to use this solution as well. So, we also made a full-fledged application, that comes with auth screens and user management, that has the Mailcoach application pre-installed into it. We've even made a one-click installer that can set up an entire server with the Mailcoach app preconfigured on it.

The entire team contributed to the project. Willem and Seb worked on the UI and branding. Alex was in charge of setting up Satis. Rias sketched out the license site and video section and took care of the 1-click-installer. Adriaan wrote big parts of the application docs and I mainly worked on improving the core and helped with all of the above. I also created a video course, which I'll outline below.

Introducing Mailcoach

In a nutshell, Mailcoach can send out newsletters and email campaigns. It uses Amazon SES, Mailgun, or Sendgrid to send out the mails themselves. Those services send feedback by a WebhookCallFailedEvent on which emails are opened and which links inside those emails have been clicked. Mailcoach can process and summarise that feedback.

construction

It has support for double-opt in flows, you can create custom placeholders, you can segment lists and much, much more.

If you want to see the UI, you can watch this introduction movie.

Mailcoach intro from Spatie on Vimeo.

One of the things I'm most excited about is the extensibility of our package. Mailcoach sends out events whenever a mail is opened, a link is clicked, ... You can use those events to do whatever you'd like. You could, for example, add a tag to a subscriber whenever a particular mail is opened, or link is clicked.

If you want to know more about Mailcoach, head over to the product site or read the extensive documentation that we've written.

Creating the video course

When we decided to build Mailcoach as a product, we were aware that the number of people that might need a self-hosted solution for mails could be quite low. But our gut feeling was that there are a lot of people that want to know how it works and how we code, so that they can use some of the same techniques in their own projects.

Although I made a few videos before, the sound and overall production quality were not that high.

I asked my friend Dries, who just got into podcasting, for some advice and bought and Audio Technica AT2020USB+ microphone and Rode PSA1 mount.

My office space in my home is quite high and empty. In the first attempts to make a video, the audio had a lot of reverb. I solved that by constructing a recording set up using a bed turned on its side, draped with blankets, and putting that in the middle of the room.

construction

I also got a few recording tips from my friend Marcel (who, in turn, got some of those tips from Jeffrey Way, I believe). Here are the ones that helped me a lot:

  • Record and speak at the same time. Don't record your video and voice in two separate passes. This will make it more natural.
  • It's perfectly ok to, when recording, pause, and gather your thoughts. You can edit out those pauses in the recording
  • Don't play with your mouse while recording, this will make it more difficult to edit
  • Clean up your Desktop, if it is visible during the video, you don't want unrelated files to be displayed
  • Try to avoid pasting large pieces of code. It overwhelms the user. A snippet is fine, but otherwise, type it out while explaining it as you go.
  • 1280x720 or 1280x800 is a good resolution to record on. On a Mac that doesn't offer this resolution natively, you can use SwitchResX to force it.

Here's one of the videos included in the course. It'll teach you how to refactor ugly conditionals safely.

I'm really proud of the Mailcoach video course and can see myself recording some more in the future.

Meanwhile, I also recorded two videos for Laracasts. I consider it quite an achievement to be featured on a site that taught me so much. Even without a subscription, you can watch my videos on snapshot testing and on simplifying controllers

Using Mailcoach for the freek.dev newsletter

I've already been dogfooding Mailcoach for a while for my own newsletter. I'm using a double opt-in flow and a welcome newsletter there.

With Mailcoach installed, this is all the code that's needed for that subscription flow.

namespace App\Http\Controllers;

use App\Http\Requests\SubscribeToNewsletterRequest;
use Spatie\Mailcoach\Models\Subscriber;

class NewsletterSubscriptionController
{
    public function subscribe(SubscribeToNewsletterRequest $request)
    {
        $emailList = $request->emailList();

        Subscriber::createWithEmail($request->email)
            ->redirectAfterSubscribed(action([static::class, 'confirmed']))
            ->subscribeTo($emailList);

        return redirect()->action([static::class, 'confirm']);
    }

    public function confirm()
    {
        return view('front.newsletter.confirm');
    }

    public function confirmed()
    {
        return view('front.newsletter.confirmed');
    }
}

The welcome mail will get sent whenever somebody has subscribed to the newsletter. It contains links to the latest newsletters (Mailcoach takes care of the web views too) and the latest posts that I've written. Because Mailcoach just lives in my own application, I can simply use the Campaign model to get the latest campaigns. Nice!

Here's the code of that mailable.

namespace App\Mail;

use App\Models\Post;
use Illuminate\Support\Collection;
use Spatie\Mailcoach\Mails\WelcomeMail as MailcoachWelcomeMail;
use Spatie\Mailcoach\Models\Campaign;
use Spatie\Mailcoach\Models\Subscriber;

class WelcomeMail extends MailcoachWelcomeMail
{
    public Collection $posts;

    public Collection $campaigns;

    public function __construct(Subscriber $subscriber)
    {
        parent::__construct($subscriber);

        $this->campaigns = Campaign::sent()->orderByDesc('sent_at')->limit(3)->get();

        $this->posts = Post::published()->originalContent()->orderByDesc('publish_date')->limit(10)->get();
    }

    public function build()
    {
        return
            $this
                ->markdown('mails.welcome')
                ->subject('Welcome to the freek.dev newsletter');
    }
}

Open source

Even though Mailcoach isn't open-source, the open-source spirit isn't entirely gone. While we were creating Mailcoach, we extracted some of its functionalities to packages:

  • laravel-rate-limited-job-middleware: this one lets you rate limited the number of jobs that can execute within a given timeframe. Mailcoach uses this to not hit any sending limits the email service providers have in place.
  • simple-excel: the package offers an easy way to read and write huge excel files. Mailcoach uses this to import and export email lists. It can even stream large exports (which I think is very cool).
  • laravel-welcome-notification: this one can send a welcome email when a new user is created. That welcome mail contains a link that allows that new user to set an initial password.

Closing thoughts

I sure had a lot of fun creating Mailcoach. Sending out my newsletter is a joy again, and I hope this solution works well for you too.

Even though I'm pretty sure that, on a technical level, everything works in Mailcoach. I'm not entirely confident whether it will also be a commercial success. As mentioned above, the target audience for this product could be quite small. I'm hoping that the video course is interesting for a lot of developers that generally wouldn't be interested in Mailcoach as a product.

The dream of our company is to slowly grow to a product company. If Mailcoach does well, it would make it easier to start working on the next product.

No matter what happens, we'll retain an open-source spirit. Open source packages will always be created. Either as byproducts of client work or our own products.

I hope you'll like Mailcoach. Give it a spin!

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

Webmentions

Phread replied on 31st January 2020
Thank you! The videos are amazing, great mattress. Can the same License for a Production (hosted) be used for a Development/Test site (local laptop) ? How many licenses would be required ? Also, thank you for all the amazing postcard-ware software!!!
Joshua de Gier replied on 31st January 2020
Spotted a type on the front-page (Sengrid -> see attached image)
Josua P. Sianturi liked on 31st January 2020
Muhammad Zeshan replied on 31st January 2020
Am I the only person seeing this? cc: @freekmurze
Unknown liked on 31st January 2020
Dennis Ong liked on 31st January 2020
Guus liked on 31st January 2020
Khorshed Alam liked on 31st January 2020
Thomas Vercruysse liked on 31st January 2020
Matthew Olding liked on 31st January 2020
Marco Pergola liked on 31st January 2020
Chris Bautista liked on 31st January 2020
Adrian Brown 🕶 liked on 31st January 2020
SANJIB ROY liked on 31st January 2020
David Aditya replied on 31st January 2020
I will purchase it soon :) The licence for the package itself is 1 year. But, will I get lifetime update on the video content?
Koen Van den Wijngaert liked on 31st January 2020
Stefam liked on 31st January 2020
Golohor Zeus 🇳🇬 liked on 31st January 2020
Michael Leigeber liked on 31st January 2020
Ruie Dela Peña liked on 31st January 2020
Felix Huber liked on 31st January 2020
Muhammad Imran liked on 31st January 2020
Frank G liked on 31st January 2020
Richard Wheatley liked on 31st January 2020
Chafik HADJ ABDOU RAZACK liked on 31st January 2020
Erik Larsson liked on 31st January 2020
Sumon Molla Selim liked on 31st January 2020
Wade Striebel liked on 31st January 2020
Edwin Egalite liked on 31st January 2020
Matt Bartel liked on 31st January 2020
Enzo Notario liked on 31st January 2020
Ricardo Fuhrmann liked on 31st January 2020
Faysal Ahamed liked on 31st January 2020
Raahul Seshadri liked on 31st January 2020
Rabi liked on 31st January 2020
Dario Diaz liked on 31st January 2020
Mattia Migliorini liked on 31st January 2020
Craig McCreath liked on 31st January 2020
Laravel Türkiye liked on 31st January 2020
Shirish liked on 31st January 2020
Román Miranda liked on 31st January 2020
William liked on 31st January 2020
Viral Patel liked on 31st January 2020
Saravanan replied on 31st January 2020
XX"©"©"""©"'**
ˎˊ˗ liked on 31st January 2020
Flavius Constantin liked on 31st January 2020
Oilmone liked on 31st January 2020
Patrice Mayet liked on 30th January 2020
bryceandy.com 🇹🇿 liked on 30th January 2020
Patrick Campbell liked on 30th January 2020
Nicolas Beaussart liked on 30th January 2020
Sean Talbot liked on 30th January 2020
Tiagosimoes liked on 30th January 2020
Nicolas Widart replied on 30th January 2020
Congratulations to the whole team! 💪
James Hemery liked on 30th January 2020
Bayo Cherif liked on 30th January 2020
Joren Van Hocht replied on 30th January 2020
The gif says enough
Robin Dirksen liked on 30th January 2020
Vikas Roy liked on 30th January 2020
Flamur Mavraj liked on 30th January 2020
Mickael Isaert liked on 30th January 2020
Andreas Tasch ⚡ liked on 30th January 2020
Daniele Esposito liked on 30th January 2020
Mikhail Kozlov liked on 30th January 2020
Arno Stalpaert liked on 30th January 2020
Simon Ellensohn liked on 30th January 2020
Gustavo Rojas. liked on 30th January 2020
David liked on 30th January 2020
Kfir replied on 30th January 2020
Congrats! Is there a way to embed user’s fields (name, username, etc.) in the email itself? Also, we are managing multiple email lists but often send the same email to all lists (no double sending ofc). Is it possible with Mailcoach?
Maarten Bode replied on 30th January 2020
Congrats on the launch! Found a small typo:
Solum DeSignum liked on 30th January 2020
wahlemedia | Philipp liked on 30th January 2020
Wyatt liked on 30th January 2020
Ricardo Valenzuela liked on 30th January 2020
Noe liked on 30th January 2020
Rakesh Reddy liked on 30th January 2020
Philipp Rappold retweeted on 30th January 2020
Worldwide 🌐 retweeted on 30th January 2020
Stefan Legg liked on 30th January 2020
Aran Reeks liked on 30th January 2020
Paul Anthony liked on 30th January 2020
Philipp Rappold liked on 30th January 2020
Tyler Woonton liked on 30th January 2020
Danny Dinges liked on 30th January 2020
Costas Loizou liked on 30th January 2020
Mikkel liked on 30th January 2020
Nick Gerakines retweeted on 30th January 2020
Ishan Vyas liked on 30th January 2020
Matthew Poulter liked on 30th January 2020
Long Do liked on 30th January 2020
Cyril Junior liked on 30th January 2020
Pedro Ladeira liked on 30th January 2020
Daniel Sturm liked on 30th January 2020
Pooyan Razian liked on 30th January 2020
Samy liked on 30th January 2020
Paul Ryley ⚡️ liked on 30th January 2020
Oliver Mensah liked on 30th January 2020
salierdev liked on 30th January 2020
johnathan lyman liked on 30th January 2020
Jake Casto liked on 30th January 2020
Nick Gerakines liked on 30th January 2020
George Drakakis 🖖 liked on 30th January 2020
Tejas Rane liked on 30th January 2020
Willan Correia liked on 30th January 2020
Andre Madarang liked on 30th January 2020
Pedro Ladeira retweeted on 30th January 2020
Abdus Fauzi retweeted on 30th January 2020
Niels liked on 30th January 2020
Albert Suntic retweeted on 30th January 2020
Miguel Piedrafita 🚀 retweeted on 30th January 2020
Alberto Garcia Jr A retweeted on 30th January 2020
Peter Fox retweeted on 30th January 2020
Alexander III retweeted on 30th January 2020
Neil Keena retweeted on 30th January 2020
Rizky Ivan liked on 30th January 2020
Robert Preston liked on 30th January 2020
Peter Fox liked on 30th January 2020
Amir Ahmic liked on 30th January 2020
Jonathan Zarate liked on 30th January 2020
Ryuta Hamasaki 🇸🇬 liked on 30th January 2020
Franco Gilio liked on 30th January 2020
Gareth Thurlow (Gaz) liked on 30th January 2020
Miguel Piedrafita 🚀 liked on 30th January 2020
Jose Soto liked on 30th January 2020
Himanshu Mishra liked on 30th January 2020
Igor Blumberg liked on 30th January 2020
Ty Noryan liked on 30th January 2020
Paul P liked on 30th January 2020
Suraj Jadhav liked on 30th January 2020
Tommy Marshall liked on 30th January 2020
Monney Arthur liked on 30th January 2020
Enes ÇAKIR liked on 30th January 2020
Andre Figueredo liked on 30th January 2020
Sam Podlogar liked on 30th January 2020
Mathias Onea liked on 30th January 2020
Neil Keena liked on 30th January 2020
James Fuller liked on 30th January 2020
James Fuller retweeted on 30th January 2020
Bagaskara Wisnu G retweeted on 30th January 2020
Abel Ponce retweeted on 30th January 2020
Karl Monson retweeted on 30th January 2020
Rafael Hernandez retweeted on 30th January 2020
Dave Sebek liked on 30th January 2020
Abbah Anoh liked on 30th January 2020
Matt Kingshott 🧐 liked on 30th January 2020
Nkhatho Ziggy Mahlomaholo liked on 30th January 2020
Yash Kavathiya liked on 30th January 2020
Michaël De Boey liked on 30th January 2020
Jachim Coudenys liked on 30th January 2020
Bagaskara Wisnu G liked on 30th January 2020
Cyril de Wit liked on 30th January 2020
Rebar Hama liked on 30th January 2020
Lars Janssen liked on 30th January 2020
Günther Debrauwer liked on 30th January 2020
Gilbert Pellegrom liked on 30th January 2020
Benjamin Michotte liked on 30th January 2020
Baki Goxhaj liked on 30th January 2020
Dieter Van der Stock liked on 30th January 2020
Karl Monson liked on 30th January 2020
/dev/glen liked on 30th January 2020
Marc Hampson liked on 30th January 2020
Stewan liked on 30th January 2020
Rafael Hernandez liked on 30th January 2020
Dumitru Botezatu liked on 30th January 2020
jalil liked on 30th January 2020
Austen Cameron retweeted on 30th January 2020
Peter Parsons retweeted on 30th January 2020
Adib Hanna retweeted on 30th January 2020
Javier Quintana retweeted on 30th January 2020
Vincenzo La Rosa retweeted on 30th January 2020
uma shankar sahu retweeted on 30th January 2020
Lee Overy retweeted on 30th January 2020
Mark Tetrode retweeted on 30th January 2020
نبيل الالمعي retweeted on 30th January 2020
Bobby Bouwmann retweeted on 30th January 2020
Eric L. Barnes retweeted on 30th January 2020
@kant@octodon.social retweeted on 30th January 2020
Nyan Lynn Htut retweeted on 30th January 2020
Aldo Mendez retweeted on 30th January 2020
Simon Kollross retweeted on 30th January 2020
BitFumes retweeted on 30th January 2020
Sebastian Fix retweeted on 30th January 2020
Vincenzo Raco retweeted on 30th January 2020
Teun de Kleijne retweeted on 30th January 2020
Bobby Bouwmann liked on 30th January 2020
@kant@octodon.social liked on 30th January 2020
Paul Ayuk liked on 30th January 2020
Nyan Lynn Htut liked on 30th January 2020
Robin liked on 30th January 2020
Aldo Mendez liked on 30th January 2020
Lennart Fischer liked on 30th January 2020
Fred Carlsen liked on 30th January 2020
Husain Ahmmed liked on 30th January 2020
Simon Kollross liked on 30th January 2020
Jordan Koschei liked on 30th January 2020
Jorge González liked on 30th January 2020
BitFumes liked on 30th January 2020
Babar Khan liked on 30th January 2020
Parthasarathi G K liked on 30th January 2020
Sanjay Ahlawat liked on 30th January 2020
Mattias Geniar retweeted on 30th January 2020
Ryan Atkins retweeted on 30th January 2020
DeanLJ retweeted on 30th January 2020
Phill Duffy retweeted on 30th January 2020
Brandon Surowiec retweeted on 30th January 2020
Antonio retweeted on 30th January 2020
Chris Fidao retweeted on 30th January 2020
Ken V. retweeted on 30th January 2020
Stephan Köllen retweeted on 30th January 2020
Julien Bourdeau retweeted on 30th January 2020
Khoa Hoang retweeted on 30th January 2020
Harish Toshniwal retweeted on 30th January 2020
Joren Van Hocht retweeted on 30th January 2020
Brandon Surowiec liked on 30th January 2020
Erick Patrick retweeted on 30th January 2020
Amit Merchant liked on 30th January 2020
Pluie liked on 30th January 2020
Heru Hang Tryputra liked on 30th January 2020
Cameron Scott liked on 30th January 2020
Ken V. liked on 30th January 2020
Severen liked on 30th January 2020
Harish Toshniwal liked on 30th January 2020
Nick Basile liked on 30th January 2020
Caneco liked on 30th January 2020
Nick liked on 30th January 2020
Benjamin Borowski liked on 30th January 2020
Lee Overy liked on 30th January 2020
Feras Shaer 🇵🇸 liked on 30th January 2020
smknstd liked on 30th January 2020
Francisco Neves liked on 30th January 2020
Dalton Sutton liked on 30th January 2020
Khoa Hoang liked on 30th January 2020
Dinh Quoc Han 🐳 liked on 30th January 2020
Julien Bourdeau liked on 30th January 2020
Jeffrey van Rossum liked on 30th January 2020
therouv liked on 30th January 2020
Joren Van Hocht liked on 30th January 2020
Filipe liked on 30th January 2020
Harish Toshniwal replied on 30th January 2020
thank you, looks so polished ❤️🚀
Grant Holle liked on 30th January 2020
Alex retweeted on 30th January 2020
Sebastian De Deyne retweeted on 30th January 2020
Mithicher Baro retweeted on 30th January 2020
NUNO MADURO 🅱 retweeted on 30th January 2020
Mohamed Said retweeted on 30th January 2020
Chrysanthos retweeted on 30th January 2020
Björn Franke retweeted on 30th January 2020
Dries Vints retweeted on 30th January 2020
Jeffrey Way retweeted on 30th January 2020
José Borges 🇵🇹 retweeted on 30th January 2020
Nana Adjei retweeted on 30th January 2020
Mubashar Iqbal retweeted on 30th January 2020
Roman Grachev retweeted on 30th January 2020
MJ retweeted on 30th January 2020
IAN LANDSMAN retweeted on 30th January 2020
Always Steven never Steve retweeted on 30th January 2020
Andrey Butov retweeted on 30th January 2020
Pilong retweeted on 30th January 2020
Jack Whiting retweeted on 30th January 2020
Sebastian Schlein 🤹 liked on 30th January 2020
Chrysanthos liked on 30th January 2020
Luís Dalmolin liked on 30th January 2020
Stefan Bauer liked on 30th January 2020
Dan Schoonmaker liked on 30th January 2020
Hemratna Bhimani liked on 30th January 2020
Dries Vints liked on 30th January 2020
Theodoros liked on 30th January 2020
Jamie York liked on 30th January 2020
José Borges 🇵🇹 liked on 30th January 2020
Gordesch liked on 30th January 2020
Tony Messias liked on 30th January 2020
Nana Adjei liked on 30th January 2020
Andrew Schmelyun liked on 30th January 2020
Mubashar Iqbal liked on 30th January 2020
Nordy Vlasman liked on 30th January 2020
Bojan Žarković liked on 30th January 2020
David On liked on 30th January 2020
MJ liked on 30th January 2020
jonassiewertsen liked on 30th January 2020
hans 👀 liked on 30th January 2020
Nick Ciske liked on 30th January 2020
Matt Murtaugh liked on 30th January 2020
Andre Kendeck liked on 30th January 2020
Freek Van der Herten replied on 30th January 2020
Thank you!
Freek Van der Herten replied on 30th January 2020
Thanks! Do let me know if you should have questions. Might be worth checking out the source code too, some cool stuff going on in there.
Freek Van der Herten replied on 30th January 2020
Yeah, I hope it’ll get approved by next week.
Freek Van der Herten replied on 30th January 2020
Thanks! :-)
Freek Van der Herten replied on 30th January 2020
Hero! 👑
Randy Allen replied on 30th January 2020
Congrats!
Peter Steenbergen replied on 30th January 2020
Purchased!
Sid replied on 30th January 2020
Very polished 👍🏼
Stefan Bauer replied on 30th January 2020
Good work Freek (and team!) 👍
Jeffrey Way replied on 30th January 2020
Congrats! Excited to try it out.
Cosmin replied on 30th January 2020
Awesomeness aside, it's really cool that you'll have a 1-click installer on @digitalocean 👌