Open-sourcing our guidelines

At Spatie we recently launched a new site: It contains articles on how we go about setting things up at Spatie and a collection of styleguides. The source code of the site is available on GitHub. In this blogpost I'd like to share why and how we created our guidelines site.

Why did we create this?

Let's start with a quote from Sandi Metz from her excellent post on why we argue about style:
I firmly believe that all of the code that I personally have to examine should come to me in a consistent format. Code is read many more times than it is written, which means that the ultimate cost of code is in its reading. It therefore follows that code should be optimized for readability, which in turn dictates that an application's code should all follow the same style. Adhering to a common style saves you money.
Spatie is web agency. So most of the time we are working on multiple projects at the same time. When the initial project is done, more of than not, we will also maintain it for several years. To keep things manageable we try to code things in a consistent way. That way we can dive into a project and easily reason about it. I'd argue that in addition to adhering to a common code style, setting up your projects in a consistent way will save time and money too. For years I've been the sole developer at Spatie. It was seemingly easy to keep things consistent because there was nobody else working on the code. But the truth is that at the time I certainly did not notice the little differences in my code style across the projects (PSR-2 wasn't a thing back then). Now that the company is growing (Alex recently joined our team with more new members on the way) it's getting more and more important to keep things consistent. Like Sandi mentioned in the above quote code should be optimized for readability. Having all code in a common style will save you money because it takes less time to understand the code. But I'd argue having a style guide will save you time writing code as well. Trying to decide if the view names or route names should be camelCases or kebab-cased? Don't waste your time and just check the relevant guidelines. Most of these rules originate from a discussion of the entire team (or they've been decided by an individual who cared enough to put it in a rule). Having these rules written down avoids discussing them over and over again. Because "best practices" really are nothing more than "current practices" you should still, from time to time, re-evaluate the rules to see if they still make sense.

Behind the screens

The guidelines site itself is build with Laravel. It's completely open source. Here's the repo containing the code that's actually deployed on our server. We've set up the guidelines site in such a way that everybody can contribute it. At the bottom of every page there's an Edit this page on GitHub link. Clicking it will create a PR against the repo. When we merge in the PR the code will automatically get deployed (we use Forge's auto deploy feature for this). Because the guidelines are our very opinionated thoughts on how to do things, we're not going to just accept every single PR we get. You can 't change our minds just by PRing a new rule. But we do welcome new rules that we agree with, or a discussion why our existing rules could be bad. And of course we're also grateful for PRs that fix typos.

Storing the content

The content itself is stored as a set of markdown files. To display every page (expect for the home page), the PageController is used:
namespace App\Http\Controllers;

use App\Markdown\MarkdownConverter;

class PageController extends Controller
    public function __invoke($url)
        abort_unless($page = app('navigation')->getPage($url), 404);

        return view('page', [
            'title' => $page->title,
            'editUrl' => $page->edit_url,
            'contents' => MarkdownConverter::convert($page->contents),

Making content private

The aforementioned PageController controller will ask the Navigation class which page should be displayed. When looking at the code of the Navigation class you'll notice that it also tries to get content from a private directory. This private directory contains content that we don't want to share publicly, such as semi sensitive information and custom procedures that are not interesting for the outside world. The content of that private directory is not in our public repo, but in a separate private repo that's being symlink so Navigation can read it. And of course that private content is only viewable by users who are logged in.

Logging in

At Spatie we use Google Apps and every team member has his or her own email-address on the domain. Wouldn't it be nice if anyone with a address on Google would be able to login? Then we wouldn't have to create credentials manually whenever we onboard a new team member. That's why we opted leveraging Laravel Socialite to handle logins. Socialite makes it very easy to authenticate with OAuth providers such as Google, Facebook, Github, ... Installing Socialite is very easy. After it is installed and configured the necessary APIs at Google you don't need too much to code to handle social logins. This is the entire LoginController:
namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\User;
use Socialite;

class LoginController extends Controller
    public function __construct()

    public function redirectToProvider()
        return Socialite::driver('google')

    public function handleProviderCallback()
        $user = Socialite::driver('google')->stateless()->user();

        abort_unless(ends_with($user->getEmail(), ''), 403);

        $authenticatableUser = User::findOrCreate($user);

        auth()->login($authenticatableUser, true);

        return redirect('/');

    public function logout()

        return redirect('/');
When visiting /login the app will execute the redirectToProvider method. The user will get redirected to a login page at Google. When users provide the right credentials Google will redirect them back to our site. That response from Google is handled in handleProviderCallback. There we abort unless the email-address of logged in user ends with And then there's a piece of boring code. Because a socialite user isn't directly authenticatable we find (or create) a regular user in the database and log that one in.

In closing

If you're working in a company that doesn't follow any guidelines to keep code and configuration consistent, I highly recommend talking to your team and convincing them of the value of writing such guidelines down. Take the time to discuss and agree on some common rules. I bet nearly everybody on your team will find such guidelines helpful and it'll make it easy for newcomers to your team. You could opt to just follow our guidelines or create your own set of rules. If you choose the latter, maybe you could use the code of our guidelines site to set up your own. The site and the writing down of the guidelines was largely spearheaded my colleague Sebastian, who, as always, did an excellent job. That site isn't the first thing we've open sourced. Take a look at the opensource pages on our company site to find out the Laravel, PHP and JavaScript packages we previously created.

CSS Utility Classes and “Separation of Concerns”

In my day to day work I don't write any css at all, but I still very much enjoyed this blogpost by Adam Wathan where he shares some interesting things about how css should be structured and he makes the case for using utility classes to make visual tweaks.
When you think about the relationship between HTML and CSS in terms of "separation of concerns", it's very black and white. You either have separation of concerns (good!), or you don't (bad!). This is not the right way to think about HTML and CSS. Instead, think about dependency direction. ... One of the biggest benefits of using small, composable utilities is that every developer on your team is always choosing values from a fixed set of options.

Cruddy by design

At this year's Laracon US Adam Wathan gave a talk titled "Cruddy By Design" on how to structure your controllers better. After the conference he published a new GitHub repo that contains the demo app he refactored on stage. The 4 main tips to improve your code come as PRs on the repo with a full description on why the change is valuable. Very cool stuff.
Using this convention as a "rule" is a good way to force yourself to keep your controllers from becoming bloated, and can often lead to learning interesting new things about your domain. For the presentation, I put together a demo app called "CastHacker" that showcases podcasts about software development. It's not a "real" app by any means (lots of imaginary features, no tests, etc.); it's just enough code to demonstrate the concepts from the presentation. Feel free to clone it and play with it locally if you like though. I've written up each refactoring I shared in the presentation as a detailed pull request.

Good Product Team / Bad Product Team

Marty Cagan, who held jobs at eBay, AOL, Netscape and HP, describes the most important differences between good and bad product teams.
What I’ve learned is that there is a profound difference between how the very best product companies create technology products, and the rest. And I don’t mean minor differences. Everything from how the leaders behave, to the level of empowerment of teams, to how the organization thinks about funding, staffing and producing products, down to how product, design and engineering collaborate to discover effective solutions for their customers.

How we improved our PWA score by 53 points in 4 hours

On the madewithlove blog Frederick Vanbrabant wrote a post on how he and colleague improved the PWA score of their company site.
So the first thing you should know about PWA (or progressive web apps) is that it’s an adaptation of your current site or web app. This means that if you want to have all the features of a progressive web app, you are going to need to change your current site/application. The good news here is that they are all changes you would want to have anyway.

Configuration-driven PHP security advice considered harmful

Scott Arciszewski debunks the commonly given advice on securing your PHP installation by setting some php.ini values.
There have been countless examples posted in various places (Reddit, Hacker News, Twitter, Facebook, Slashdot, and even LinkedIn group discussions), and while a handful occasionally contain one or two tips that might be beneficial towards securing your PHP applications, almost all of the advice they contain is either wrong, a huge waste of time, downright silly, or all of above. As part of a team that specializes in application security (in particular: securing PHP applications), I feel it's high time someone cleared the air about this advice.

A checklist for all projects that are going live

Apart from our open source work, we do client work at Spatie as well. Over the years we've learned that one of the most critical moments of a project is when it is going live. No matter how you confident you are about the correctness of the code base there are so many big and little things that could go wrong when moving to production. To make sure a new project is launched correctly we've created a list with important items to check off. We've shared our checklist on GitHub. Some items are specific to our workflow, bust most things are applicable to any project. There are also tasks on the list that we take care off well before launching but verify again just to make sure that everything is in order. In this post I want to highlight a few items.
  • Use the Chrome DevTools and throttle your CPU and network with 10x CPU slowdown and set the network to "Good 3G". At our office we use modern Apple hardware and a fast internet connection. Mobile users probably have a much slower internet connection and slower CPU.
  • Check all pages for n+1 problems. Because we use powerful hardware we're probably not noticing any n+1 problems while developing a project. We use Barry vd. Heuvel's laravel-debugbar. That awesome package can report all queries that were executed when rendering a page.
  • Add redirects from old to new pages if necessary. Redesign an existing site will often results in a changed site structure. We don't leave people (and search engines) in the cold and provide redirects from the old urls to the new ones. To manage such redirects in a Laravel app we use our home grown laravel-missing-pages-redirector package.
  • Verify that all http status codes are ok. Links to missing pages are really not classy. That's why we unleash our crawler on the new site to make sure that links on all pages return a good response code.
The checklist contains many more items. Take a look at the entire list on GitHub: Do you think we've missed an important check? Submit a PR.

The Magic Tricks of Testing

In a mail sent to all subscribers on the Adam Wathan mentioned a talk Sandi Metz gave a couple of years ago at Rails Conf. It's a really good talk that explains in a clear way when and what you should test.
Tests are supposed to save us money. How is it, then, that many times they become millstones around our necks, gradually morphing into fragile, breakable things that raise the cost of change? We write too many tests and we test the wrong kinds of things. This talk strips away the veil and offers simple, practical guidelines for choosing what to test and how to test it. Finding the right testing balance isn't magic, it's a magic trick; come and learn the secret of writing stable tests that protect your application at the lowest possible cost.

Use sane defaults over exceptions

Freek Lijten, a developer at Schiphol, makes the case for just setting a sane default value instead of throwing an exception when invalid input entered the application.
I didn't think much of this, but I've seen a major drawback lately while working on a site that is a bit bigger than I was used to. With over half a million visitors a week and lots of scrapers, bots and other stuff visiting, these exceptions and fatal errors clog up logging quite a bit. Not to the point that we can't handle the volume, but it generates false positives in monitoring channels and it is something we do not want to act upon anyway.

Pragmatic coding

Stefan Koopmanschap argues that, besides writing beautiful code and using kickass frameworks and libraries, we should be able to do some quick and dirty coding as well.
Can you write me a simple script that fetches some information from an RSS feed and displays the titles? Like, just write me that script in a couple of minutes. I don't care about tests, quality, etc. Just get me the information, quickly.

PHP 7 is gaining ground fast

Jordi Boggiano shared some new stats on PHP version usage he collects via Packagist.
A few observations: 5.3 and 5.4 at this point are gone as far as I am concerned! 5.5 still has a good presence but lost 12% in 6 months which is awesome. 5.6 basically stayed stable as I suspect people jumped from 5.5 to 7 directly probably when upgrading Ubuntu LTS. 7.0 gained 15% and is now close to being the most deployed version, 1 year after release! That should definitely encourage more libraries to require it IMO, and I hope it is good encouragement to PHP internals folks as well to see that people actually upgrade these days :)
It's very cool that PHP 7 is being adopted so quickly. I suspected that it would go down this way. Unfortunately the majority of package creators are still targeting PHP 5. Jordi has this to say on that.
As I wrote in the last update: I would like to encourage everyone to be a bit more aggressive in bumping PHP requirements when tagging new major releases of their libs. Don't forget that the old code does not go away, it's still there to be used by people using legacy PHP versions.
Amen! Read Jordi's blogpost here:

Let’s talk about phone numbers on mobile sites

Wes Bos shares a quick tip to make phone numbers on websites tappable.
I’m talking about when phone numbers on a website aren’t tapable. Often the HTML is so that mobile operating systems cannot select the phone number alone and you are forced to remember/recite or write down the actual number. So, when you put a phone number on a website, don’t just use any old element, use a link with the tel protocol.

On Being Explicit

Mathias Verraes, one of the organizers of DDD Europe, recently gave a talk at DDD London on how to name things to both improve your code and to improve communication with the business.
“Make the implicit explicit” must be one of the most valuable advices I ever got about software modelling and design. Gather around for some tales from the trenches: stories from software projects where identifying a missing concept, and bringing it front and centre, turned the model inside out. Our tools: metaphors, pedantry, type systems, the age old heuristic of “Follow the money”, visual models, and a healthy obsession with language.

Does code need to be perfect?

Andreas Creten explains his view on wether you should always try to write perfect code. Spoiler: no.
The engineers want to write perfect code using the latest techniques, make sure that the code is well documented so they can fully understand how everything works and that it has tests so they can easily update things later. Product owners on the other hand just want things to be done, fast and cheap, so they can ship new features or convince new clients. How can you make these conflicting views work together?

How to open source at Zalando

Zalando, a large online fashion plaform, published it's guidelines around open source creation and usage.
Why Open Source? Because it can: improve quality, mitigate risk, increase trust, save us money, expand our technology choices, be fun, enable us to give back to the community, strengthen our tech brand, and attract talent. ... Do “Open Source First”: If your Zalando project can also be useful to non-Zalandos, release it as open source from the start.

Structuring PHP exceptions

Alain Schlesser wrote an article on how to manage exceptions in a large codebase.
I seem to constantly work on improving my habits regarding the use of exceptions. I think it is an area that I haven’t yet fully explored, and it is very difficult to find anything more than very basic explanations and tutorials online. While the consensus is to use exceptions, there is very little information on how to structure and manage them in a larger codebase. The larger and more complex your projects become, the more important it is to start with a proper structure to avoid expensive refactoring later on. In my opinion a good exception message in most cases contains three things:
  • the reason why something went wrong
  • the data that caused the problem
  • suggestions on how to solve the problem
Named constructors for exceptions are the perfect place to build up such a message. Want to learn more? Ross Tuck wrote a good blog post on the subject too.

10 modern software over-engineering mistakes

Subhas Dandapni wrote an excellent overview of the most common over-engineering mistakes.
Few things are guaranteed to increase all the time: Distance between stars, Entropy in the visible universe, and Fucking business requirements. Many articles say Dont over-engineer but don’t say why or how. Here are 10 clear examples.

When are single-character variable names acceptable?

Generally I don't like to abbreviate variable names. This answer on Quora lists a few situations where an abbreviation is probably ok.
There is a simple (but unsatisfying) answer to all questions of this form: they are acceptable when they would make the code clearer. This can happen in a few ways. The most common, as you noted, is convention: i, j, k for loop variables, x and y for coordinates, e for exceptions, f and g for functions and so on. Another is structure. Often, the broad structure of an expression is more important than its contents. Using shorter variable names makes it easier to read at a glance. I think this is often more important than being easy to read in detail! If a variable has a very small scope—say one or two lines at most—and it's easy to see where it comes from, having a long name is just noise.

Hunting for great names in programming

A great story by DHH on his quest to find good names for some functions he was working on.
One of the real delights of programming is picking great variable, method, and class names. But an even greater treat is when you can name pairs, or even whole narratives, that fit just right. And the very best of those is when you’re forced to trade off multiple forces pulling in different directions.

Practicing YAGNI

In a new post on his blog Jason McCreary, creator of Laravel Shift, wrote down the summary of his Laracon US talk.
I consider myself a searcher. On a quest to find the Holy Grail of programming practices - that single practice which instantly levels up my skills. While I know this doesn’t exist, I do believe in a set of practices. Recently, I found one to be YAGNI. YAGNI is a principle of eXtreme Programming - something I practice daily at work. YAGNI is an acronym for You Aren’t Gonna Need It. It states a programmer should not add functionality until deemed necessary. In theory, this seems straightforward, but few programmers practice it.