What a year this has been. I guess that in January, nobody suspected that we'd got ourselves a worldwide pandemic on our hands.
For many people, 2020 has been a pretty rough year. While the pandemic also impacted me, I think that the problems I have only exist in my head. Nobody around me had health or financial troubles, and I also don't have any complaints on those fronts. That makes me a very lucky man.
In this blog post, I'd like to reflect on the things I did in 2020.
On a personal level
I don't want to share too much about my private life, as I consider that... private. I can share that I'm still living with my girlfriend and two boys (they are 6 and 8 now) in the beautiful city of Ghent.
Improving the home office
Due to the pandemic, I spent a lot more time at home. In Belgium, teleworking has become mandatory. In previous years I only worked one or two days a month from home. This year about 90% of my work was done in the home office.
Right before the pandemic took off, I made some significant improvements to my workroom at home. Here's a picture before (yeah, that's my kid playing on the game PC, which was previously on the same desk)
And here's a picture of the "new" desk:
As you can see, it's a lot tidier. And there's some streaming hardware on the desk as well (more on that later in this post). Behind the desk, there is a LED strip that allows me to change the office's vibe. In the evening, I often use a darker color. Here's how that looks.
Here's a post that mentions the exact hardware you see on my desk.
Releasing and creating music
I've been playing music in bands all my life. Again, due to the pandemic, that has changed this year. For a good part of these past 12 months, we didn't come together with the band as it wasn't allowed (nor wise) to do so.
In my twenties, I did a lot of music recording on my own. This year, I started doing that again. After a buddy of mine explained me the ropes, I bought myself a license of Ableton Live Suite. And boy, is it fun to work with. Here is a recording I did on my own in the rehearsal room (played all the instruments separately). And here's another one, created using only an acoustic guitar and some effects at home.
With my new Ableton skills, I revisited some recordings I did in my twenties. I added some guitar and bass lines to the old songs; it felt like jamming with myself. After that, I edited, EQ'ed, and prepared them for release.
Releasing these polished versions of older work gives me some closure and headspace to work on new stuff. Next year, I'll probably spend some more time recording solo stuff, but I hope rehearsals with the full band can also happen again frequently.
Music I listened to a lot in 2020
Here are some of my favourite records that were released in 2020.
- Daniel Avery & Allsessandro Cortini - Illusion of Time
- Lee Randaldo & Raul Refreee - Names of North End Women
- Nathan Fake - Blizzards
- Numun - Voyage Au Soleil
- Sam Prekop - Comma
- Sufjan Stevens - The Ascension
- Torn Hawk - White Labels and Outtakes
- Kevin Morby - Sundowner
- Fiona Apple - Fetch The Bolt Cutters
- HAIM - Women In Music
Missing all the things
I'm surrounded by a beautiful family and live in a spacious home, so staying more at home isn't problematic. Even though the circumstances at home are very good, I miss traveling, seeing friends, going out... I've learned that, even though I consider myself an introvert, I need many people around me to feel at my happiest.
Like said in the intro, the only problems I have, are the ones that exist in my mind. This past year, by focusing on paid products, I experienced a new kind of stress. I sometimes felt a (I now know misplaced) sense of guilt by making some products paid and not free.
In the past years, I've always managed to separate my sense of happiness from the success of the open-source packages. With paid products, I've not always been successful in making this separation. In the weeks leading up to a launch, I was undoubtedly tenser than is healthy. In hindsight, I think I took these product launches much too personal.
Some of these products, which were logical to create for our company, did partially compete with stuff with what others are making, did not feel good.
The truth is most of these products couldn't have achieved the level of quality if they would be free. By making this paid, company resources can be spent, and colleagues can use their expertise to improve products.
I hope that in 2021 I'll manage to keep the stress and anxiety I felt for product launches under control. All launches so far were a success, so I shouldn't need to worry too much. Even if a launch is unsuccessful, I shouldn't take it personal.
Even though working and releasing paid products was stressful at times, I did enjoy creating and working on them a lot.
It's been an excellent year for Spatie. Our team accomplished a lot of things this year. We moved to a bigger office, where YET AGAIN due to the pandemic, we didn't spend as much time with our team as we'd like to. Let's hope that we can enjoy it more in 2021.
We've temporarily become a near 100% remote company. On a technological level, this works. We can communicate well online, and the projects don't suffer too much impact from this change.
Working so much from home does have an interpersonal impact. You don't have these casual conversations at the coffee machine anymore or good talks with the whole team during lunch. We try to have a frequent digital "coffee break" for informal conversations, but it isn't the same.
What the pandemic taught us is that our team works best when there's a mix between working at home and the office. Before the pandemic, my colleagues and I were already working at home for a couple of days and a couple of days at the office. I can't wait to go back to work this way.
We made a significant shift this year in the kind of work we do. In 2018, we devoted all our time to client work. In 2019, most of the income could be attributed to client work and a small piece to Flare. This year we've launched a mix of 6 digital products and video courses.
I would estimate that this year 30% of our total time was spent on our own products and 70% on client stuff. I'm proud to share that all of these products are profitable. So probably we'll try to grow that number in the next year.
It isn't our goal to completely move away from client work. We're fortunate that things are going so well that we can pick our clients. We only take on long-term projects in which our team can learn something.
To help us with client work, we hired a new team member Niels. Due to the pandemic, he didn't spent much time getting to know the team in person, but let's hope that we can see each other some more in 2021.
Let's take a closer look at a couple of things our team has done this year.
Releasing open source packages
Like previous years, our team released a lot of packages. These packages are mainly built for our own needs, but we're delighted that others find them useful too.
This year we hit the 100 million download mark. We celebrated this by asking the community for their stories on they use our packages. We published some of these stories on our site and sent them a custom Spatie backpack.
Here's the big list of packages that we created this year:
A first product: Mailcoach
In March of this year, we launched Mailcoach. This premium Laravel package can send out email campaigns. Mailcoach was born out of a need to have a simple, inexpensive way to send emails in Laravel. To know a bit more about the back story, read this section in the recap of 2019.
Mailcoach was the first Spatie product that we did on our own entirely. Although I had a fun time creating it, there was this feeling of (I now know misplaced) guilt because we were creating a paid product of this. Mailcoach started as an open-source package called laravel-email-campaigns, which was pulled when we decided to make it paid. Until the day of release, I was still having doubts our audience would be willing to pay us money for this.
Luckily it worked out well. After a few weeks, all development costs were already earned back, and sales are still good.
We were lucky that when we launched Mailcoach, GitHub also changed its pricing. Previously, we could not give our users access to the laravel-mailcoach repo as GitHub would charge each of our customers as users. GitHub's new pricing model doesn't involve pricing per user. So we can give all our customers access to the repo.
The advantages of this are quite substantial: our customers can see the features we're working on and even submit issues and PRs. This makes that working on Mailcoach has an open-source feel. On the repo, there's now a friendly little community of people who use Mailcoach.
At Spatie, we're using ourselves to reach our audience. My newsletter also gets sent via Mailcoach. I feel that, because we're such big users of Mailcoach, we can make a better product. Whenever, in using Mailcoach, we see something that can be improved, we just do it. Since its release, a lot of small and big improvements were made.
We're currently preparing v4 of Mailcoach. The tentpole features will be automations (think drip campaigns) and the handling of transactional emails (you'll be able to see each sent mail and track opens and clicks). My colleague Rias, who already helped out a lot with Mailcoach's support, is doing some very nice work making these new features come alive.
I'm delighted with how Mailcoach turned out, and I am looking forward to how far we can bring the package. We will probably release v4 of mailcoach somewhere in February / March of 2021. You can expect a very polished release.
The first video course: Laravel Package Training
Somewhere around April, May, we launched a Spatie profile on GitHub sponsers. Our idea was to do something special for this part of our audience.
As part of the Mailcoach release, I had recorded a couple of videos that explain how Mailcoach works internally. I loved creating videos and wanted to do it again. The idea was born to create videos to give away to our sponsors and sell the rest of our audience.
I'm pretty amazed at how fast this idea was executed. The recording of all these videos only took two days. Having created over a hundred packages certainly helps when creating a video course on that subject. The site, including a video section, itself took Willem only a couple of days.
Laravel Package Training also has done well commercially. Since the launch, we've added a couple of videos. We aim to keep the course up to date whenever there are changes to how we create packages.
In the past few years, the type of client work we do has changed. Whereas previously we worked on multiple smallish projects that are about a month in duration, we moved to working on big projects that have a duration of half a year at least. Currently, the client project where we focus on the most is a multi-year project with Laravel and event sourcing at its core.
When building an extensive application with a team, things like code structure and consistency become even more critical than when coding on your own or working on a small project. We think we have a good way of structuring this large application while still striking a balance between strictness and pragmatism.
In our team, my colleague Brent, amongst others, thinks a lot about these subjects. Many of the techniques, such as view models and refactoring to actions, have been pitched by Brent and improved upon by the team.
Because he's so passionate about these topics, Brent decided to publish posts on his blog to explain these techniques. Because this type of knowledge can help other developers so much, we decided to do a whole course.
Brent got a break from client projects in the middle of the year to work on the book and video course. Our entire team gave feedback on the content. My colleague Seb prepared the beautiful PDF version, Willem took care of the whole look and feel of the cover and marketing site. The creation of the course was a team effort.
When Laravel Beyond CRUD launched, I was nervous about how the Laravel community would react to this course. In this book, we preach to consider a more strict approach. In the Laravel community, there's a tendency to solve things pragmatically. I don't think that's bad, because I consider myself a pragmatist too.
Luckily our ideas were embraced well. Reactions, after we launched it, were great. Laravel Beyond CRUD is our best selling course, and it continues to do well. Like Laravel Package Training, we will update the book and include new insights our team learns when building big apps.
Rebuilding spatie.be as a sales platform
As mentioned above, it's only during 2020 that we started selling digital products of our own. Before that, we mostly worked on client projects. Our website was designed to attract new clients.
- we have to maintain certain things as the sale process and the video section multiple times
- it's hard to implement some pricing options, such as giving buyers of product A a discount on product B
That's why, before launching Laravel Beyond CRUD, we decided to move the sales process and video section of these separate marketing sites to spatie.be.
This move also has the additional benefit that it puts more emphasis on the Spatie brand. When people buy one of our products, they will also see other things in our portfolio. We hope that people buying our products will see the Spatie brand more and remember that we put out polished and quality products. When launching a new product, people will hopefully be more inclined to buy it as it's under the Spatie brand.
We see that the more people we get to visit our products page, the more sales we have. To attract more visitors to our main site, we decided to also move the documentation of our larger packages, and our guidelines from external sites to spatie.be.
In true Spatie fashion, we also open-sourced the Laravel app that powers our site. If you want to know more about the why and how of the rebuilding op spatie.be, read this series of blog posts, where I also do a deep dive in some parts of the code.
- Part 1: Intro + a tour of spatie.be
- Part 2: Logging in using GitHub
- Part 3: Giving customers access to private repositories on Github
- Part 4: Making a sale using Paddle
- Part 5: Using Satis to install private packages
- Part 6: Building a video section using Vimeo
- Part 7: Importing package documentation from GitHub
- Part 8: Mailing updates and news using Mailcoach
- Part 9: Serving ads on GitHub
- Part 10: Miscellaneous interesting tidbits + outro
Meanwhile, we also added advanced purchasing power parity calculations to our site and added support for referrals. I'll be sure to blog on these subjects soon.
Most of our team members are active bloggers. We now display links to their latest posts on our home page. We'll improve on that by adding a new blog page to spatie.be and listing all posts. Hopefully, this will help to get the individual blogs more traffic, and of course, it's also good for the SEO of spatie.be
I'm very happy with the changes we made to spatie.be this year. Our site now reflects the directory our company is going in.
Laravel Media Library is one of my favorite homegrown packages. Shortly said, this package allows you to associate files with Eloquent models. At Spatie, we use it in every project. The package is very mature: it's already a major version 9 and has over 3,5 million downloads.
The package only handles the back end stuff. In each project where we use Media Library, we had to code Vue or React components to handle uploads and manage files inside Media Library. In my mind, these front end components were always a missing part of the package.
We decided to not only create React components for our own projects but also Vue 2/3 and Livewire equivalents for people who prefer those technologies. To deliver polished components, we had to put several of our team members for a considerable amount of time on the project. That's why we decided not to release these components for free, but as a paid add-on package called Media Library Pro.
At Spatie, we often work out things by not planning features too much but relying on progressive insight. In this case, there was some friction in keeping the scope and API for all flavors (Vue/React/Livewire) in sync.
Our initial goal was to release these components in the summer. Because we underestimated the amount of work it took to create all the flavors, we had to delay the release. In hindsight, it would have been better to initially spend more time determining the exact scope and API of these components.
When we launched Media Library Pro in October, there was no prominent sales peak like we see with our courses. I think this is normal for this type of product: you'll probably only buy it at the start of a project to use the components. Since launching it, sales have continued to grow, and development costs are earned back. While Media Library Pro isn't an initial big hit, I'm sure sales and usage will grow in the future.
At Spatie, we administered several servers for our clients. The servers are backed up in multiple ways. One of these ways was BackupPC. This piece of software can ssh into any server and copy files unto itself.
Because the UI of BackupPC can be quite overwhelming, and install it is not that easy for non-server-admins, we wanted an alternative. Like many other times, I thought, how hard can it be to code this up myself?
At the beginning of the year, I had an enjoyable time creating this package. Under the hood, rsync is used to deduplicate files in subsequent backups. To know more about the package, take a look at this intro movie.
Like Mailcoach, Laravel Backup Server started as a free, open-source package. To make the package more comfortable to use, I wanted to add a front end to it. While I got everything front-end-wise to work, my work didn't have the level of quality my colleagues Seb, Adriaan & Willem can achieve. To spend company time creating a UI, we decided to make this package a paid product.
The package is fully functional, and it helps us back up our 100+ server, but the UI hasn't been released yet. You can interact with the package via Artisan commands. We've already allocated some time next year to polish and release the UI, so you'll probably see that coming in Q1 / Q2 of next year.
Our team, and certainly primary author Brent, had a lot of fun creating Laravel Beyond CRUD. Immediately after release in August, Brent and I thought of doing another course on a different subject. We settled on two ideas. I can't tell much about the first idea yet, as we're researching that one right now, and will probably announce it early next year.
The second idea was to write a book on modern PHP. The upcoming release of PHP 8 in November was the perfect moment to launch the book, so I started executing this idea. Brent focused on writing a book; I worked on the video course to demonstrate all new features in PHP 8. Because we could imagine that by PHP 8 release, many others would release similar videos, we decided to release the videos for free. They are used to lead people to the paid book.
I have fond memories of creating the joint introduction movie that you can see at the Front Line PHP website. Here's another unpublished video where you can see some of our bloopers.
After Laravel Beyond CRUD was released, Matthias Noback got in touch with us to give us some tips on improving the book's content. For Front Line PHP, we hired Mattias for a technical review before released the book. His feedback certainly made it a better product. I'm also grateful for Roman Pronskiy from Jetbrains agreeing to write the foreword.
Like Laravel Beyond CRUD, Front Line PHP has been a commercial success. And again, the feedback we got was excellent. We recently published an epub version of this book because there were so many people asking for it.
Because of the success we had this year with Laravel Package Training, Laravel Beyond CRUD, and Front Line PHP, we decided to release more courses in 2021. Brent is already at work researching the subject of our next course, and you can expect an announcement on this early next year.
Flare is a fantastic product that got too little of our attention this year. Flare did grow, but in our opinion, not enough. We made some changes in how Flare is managed behind the scenes, so new features and polishments can be introduced faster.
This year we mostly improved stuff behind the scenes. We did a big refactor of how errors are stored and clean up. This resulted in a much smaller database. More info on that in this blog post. To solve some performance problems, we had to use Blackfire to profile our application. We shared how we could install Blackfire on Vapor. Alex did some amazing work on this front.
We also did some smaller quality of life improvements, such as formatting the SQL queries and inline bindings.
Behind the scenes, my colleagues Alex and Ruben are preparing more significant new features, which will be launched Q1 next year. We also have some nice improvements for Ignition planned, which we'll probably launch together with Laravel's summer release.
Because product work has been so successful, we're planning on releasing more in 2021. In the other paragraphs, you've already read that we're already are prepping a new course, Mailcoach v4, and improvements to Flare.
We also have planned two other new products that are still under wraps. The first one will be a desktop application. I've already started some teasing. We'll launch this one in January 2021.
There weren't many conferences and meetups this year. That makes me a bit sad. Over the years, I met many people at these conferences, which I consider some good friends now. I miss these events and hope that we'll have them again somewhere in 2021.
There's one good thing that came from the pandemic. Because I missed public streaming, I decided to learn how to stream talks.
I started with using OBS. It's a fantastic piece of software that works very well. If I streamed on my own, I would have kept using it. Sometimes I like to bring guests on. Although I could get that to work in OBS and Skype, it was finicky to set up and a stress source during the stream.
Thanks to a tip by Caneco, I learned about streamyard.com. This is a hosted solution that makes it easy to invite guests on the stream. The stream's quality is excellent, I have less stress, so it's a no brainer for me to pay for it.
What I like about streaming is the casual feels around it. Just like meetups, the audience watching a stream is very forgiving.
You can see all the streams I did in my video channel on YouTube.
Here's a small selection:
- Refactoring Mailcoach to domains
- Adding favicons to the site list of Oh Dear
- Previewing Media Library Pro
- Generate dynamic open graph images for free.dev
- Laravel Workbench and Pest 0.2
Because I missed meetups so much, I decided to start an online one. I pitched my idea for a Laravel meetup to Taylor, and I was delighted that he allowed me to brand it as the Laravel Worldwide Meetup.
Meanwhile, we've had four editions of the meetup. You can see links to all recording on the event page of the meetup website.
At the end of the year, I took a little break in organizing the meetup, but it'll be back in January 2021. There are some plans to improve the interactions between attendees, but I can't share too much on that for now.
At Oh Dear
Oh Dear is the uptime tracker on steroids that my buddy Mattias and I have built. A while ago, Mattias said that he no longer considers Oh Dear as "a side business", but as "a business". After doubling our MRR in 2019, we managed to triple it this year. This growth is well above expectations.
This year we slowly, but surely, improved the service. In the first months of the year, we adapted a new logo and corporate identity. In March, we vastly improved the notification settings and added the ability to send test notifications for all channels.
Lots of our customers rely on webhook notifications, so we made them a lot better. You can now see a details log. You can even resend old notifications. You can read more about these features in this blog post.
In May, Mattias finished work on a feature that a lot of our customers were asking for: performance monitoring. For each site, you can now see how graphs that display how fast your site is responding. Oh Dear can now also send out alerts when there are big jumps in performance.
In September, another big feature was introduced: scheduled task monitoring. Using this check we will notify you when one of your scheduled tasks didn't run on time.
In November, my colleague Seb designed a new fresh look for our dashboard. I took care of importing and displaying favicons next to each site. In this stream you can see me coding up that feature from scratch.
Because most of my time is spent a Spatie, I still consider Oh Dear as a side project. I love the fact that, when I feel like it, I can spend the time to add some features and then leave it alone again for a couple of weeks. Oh Dear is a very stable app; there are almost no technical issues.
To know more about how Oh Dear is run behind the scenes, take a look at this talk I did at the PHPBenelux Meetup.
The freek.dev blog
freek.dev is now six years old. During that period, I wrote a post about every week. I still very much enjoy blogging, so I'll probably continue doing this in 2020. It's funny that when Googling problems, a blog post of mine turns up as the first result. Thanks for that solution, past self!
In the past year, I made a couple of changes.
- My newsletter is now sent using Mailcoach, instead of Sendy.
- I've added a community section, where everybody can propose links that should be displayed on this blog. I'm pleased that people submit links regularly
- There's a new music section. Right now, it only displays the music that I've created myself. I'm thinking of also adding links to music I'm listening to when coding.
- Social images are now generated automatically. I've streamed the coding of that part.
My blog received about 940K of pageviews in the past 12 months. I'm still delighted with the format: lots of links to external blogs, with posts of my own.
I'm the proudest of this series of posts where I share in great detail how we sell digital products at https://spatie.be
These are the blogpost I wrote myself this year:
- Using GitHub actions to run the tests of Laravel projects and packages
- Remove all history from a GitHub repository
- Building Mailcoach
- Pragmatically testing multi-guard authentication in Laravel
- Manage Docker containers using PHP
- A PHP package to execute commands via SSH
- laravel-event-sourcing v3 has been released
- Using BetterTouchTool as a window manager
- Laravel Tail can now tail remote logs
- How to refactor complex if statements
- How to write exceptionally good exceptions in PHP
- Behind the scenes of Flare (or How to structure big Laravel applications)
- How to use a MySQL database on GitHub Actions
- On using arrow functions in PHP 7.4
- Writing readable PHP: decrease indentation by returning early
- Mailcoach v2 has been released with support for custom HTML editors and multiple mailers
- How to configure and use multiple SES accounts in a Laravel app
- How to check which version of PHP you are running
- Building complex forms with Laravel Livewire in Oh Dear
- Some cool Laravel 7 Blade components
- A package to execute a random artisan command
- Using the 1-click-installer to set up Mailcoach in no time
- Replacing websockets with Livewire
- A package to dump anything to the log
- Mixing event sourcing in a traditional Laravel app
- A walkthrough of Laravel Backup Server
- Creating a Tweet wall in 3 minutes using Laravel Dashboard
- Building a realtime dashboard powered by Laravel, Livewire, and Tailwind (2020 edition)
- An unopinionated package to make Laravel apps tenant aware
- How we created over 200 PHP and Laravel packages
- Learn how to create PHP and Laravel packages using our new premium video course
- Adding try/catch to Laravel collections
- Improving readability by decreasing indentation
- A package to schedule Artisan commands at sub-minute frequencies
- Adding try/catch to Laravel collections
- Meetup time: discovering Laravel Workbench and Exploring Pest 0.2
- Announcing the Laravel Worldwide Meetup
- Introducing Laravel Schedule Monitor
- Announcing the Laravel Beyond CRUD video course and book
- How to clean up huge tables in Laravel with ease
- Customising and extending Laravel Form Requests
- Using Blade components for handling layouts
- Video: building a realtime dashboard power by Laravel and Livewire
- How to group queued jobs using Laravel 8's new Batch class
- Introducing Laravel Beyond CRUD: a way of building large Laravel applications
- How to schedule commands to run every few seconds in a Laravel app
- How to call an overridden trait function
- Why and how you should monitor scheduled tasks
- Creating a "Marked as Completed" button using Livewire
- Selling digital products using Laravel part 1: Intro + a tour of spatie.be
- Introducing Laravel Backup Server
- Adding a subscription form to the web views of Mailcoach
- Exploring PHP 8 features
- The problems with traditional form uploads
- The best PRs we got in October
- Media Library Pro makes uploading files to a Laravel app a breeze
- spatie/once v3 has been released, now uses a PHP 8 WeakMap
- Learn all new PHP 8 features by watching this free video course
- Store strongly-typed settings in a Laravel app
- Encrypting and signing data using private/public keys in PHP
- A better way to work with a backtrace in PHP
- My current setup (end 2020 edition)
- Building the Imagick PHP extension from master
- Moving PHP and Laravel tests from Travis CI to GitHub Actions
- Triaging feedback on GitHub using issues and discussion
- Refactoring the mailcoach codebase to domains
Full Stack Europe
Together with my buddy Dries Vints, I organized the first Full Stack Europe conference in 2019. The plan was to have a second edition in October of 2020. By February, we had already arranged an excellent line-up of speakers. Of course, the pandemic throws a spanner in the works.
By April, it was apparent that the health crisis would not be solved by October. We took the safe route and canceled the conference. Although it was a bit sad to send cancellation emails to our speakers, we were lucky not to have made any financial obligations yet.
We intend to organize the second edition of our conference at the end of 2021. Hopefully, the pandemic will mostly be a thing of the past by then.
Even though 2020 certainly has been a pretty weird year, I still consider it a good one, certainly given the circumstances.
Submit your recap here, and I'll add it to the list below.