DEV Community

Freek Van der Herten
Freek Van der Herten

Posted on • Originally published at on

★ A new website for Spatie: backend highlights

For the first time in 4 years we completely redesigned our company website. We launched it today. The site is a simple Laravel app with some technical niceties. True to form we also open sourced the app, you can find the code in this repo on GitHub.

In this blogpost I'd like you to give you a tour behind the scenes.


GitHub integration

The past years we've been more and more involved in the open source community. We've created 100+ packages that have been downloaded for over 15 million times. On our website we dedicated an entire section to highlight our efforts. We list all our open source packages and projects.


We use the GitHub API to import most info on our public repositories to the database. The import is done by this console command which is scheduled to run daily.

GitHub doesn't have any info on download counts. That's why there is a seperate command that queries the Packagist API for the download numbers.

Getting involved in open source has a lot of benefits. We think it's important the lower the barrier of entry for those wanting to start contributing to open source. That's why we also list a few easy issues on our repos. These are perfect


Those easy issues, which are recognized by a specific label on an issue, are also imported via the GitHub API. Here's the command that handles the import of easy issues. Notice that any new issue also are automatically tweeted.

Our open source stuff wouldn't be as good if we don't get any help from the community. We are grateful for anyone we improved our code with a PR, fixed a typo for us, opened up an issue to ask us a question or report a problem. Symfony recently started with thanking random contributors on their site. We think this is a nice gesture so we've done that as well. Here's the command that imports a random contributor.


Displaying responsive images

All of our open source stuff falls under a specific license called postcardware. This means that if our code makes it into your production environment you're required to send us a postcard from your hometown. For us is kinda cool to get postcards from over the entire planet. We share every postcard we received on this dedicated page on our site.


We now have about 200 postcards displayed on that page. When I take a picture of a postcard with my phone the filesize is about 4 to 6 MB. If we were to use those images directly that the page size would be about 1GB.

You might think, just create a thumbnail version, but we went on step further. We used our own medialibrary to generate responsive images for those postcards. This means that if you visit the site via a small mobile device your browser will download smaller images than if you were working on a device with a larger monitor. We leverage the srcset attribute to accomplish this behaviour.

The first time you visit the postcards page you might have noticed that blurry versions of the postcards were displayed. This is a technique called progressive image loading. We inline a blurred svg version of the postcards in the page so that the browser can display that immediately. The browser will replace this with a real image when it gets downloaded.

Here's the markup that is generated by the medialibrary for a responsive image.

<img srcset="/images/medialibrary/539/responsive-images/open-source ___medialibrary_original_2400_2605.jpg 2400w, /images/medialibrary/539/responsive-images/open-source___ medialibrary_original_2007_2178.jpg 2007w, /images/medialibrary/539/responsive-images/open-source ___medialibrary_original_1680_1823.jpg 1680w, /images/medialibrary/539/responsive-images/open-source___ medialibrary_original_1405_1525.jpg 1405w, /images/medialibrary/539/responsive-images/open-source ___medialibrary_original_1176_1276.jpg 1176w, /images/medialibrary/539/responsive-images/open-source___ medialibrary_original_983_1066.jpg 983w, /images/medialibrary/539/responsive-images/open-source ___medialibrary_original_823_893.jpg 823w, /images/medialibrary/539/responsive-images/open-source___ medialibrary_original_688_746.jpg 688w, /images/medialibrary/539/responsive-images/open-source ___medialibrary_original_576_625.jpg 576w, /images/medialibrary/539/responsive-images/open-source___ medialibrary_original_482_523.jpg 482w, data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHg9IjAiCiB5PSIwIiB2aWV3Qm94PSIwIDAgMjQwMCAyNjA1Ij4KCTxpbWFnZSB3aWR0aD0iMjQwMCIgaGVpZ2h0PSIyNjA1IiB4bGluazpocmVmPSJkYXRhOmltYWdlL2pwZWc7YmFzZTY0LC85ai80QUFRU2taSlJnQUJBUUVBWUFCZ0FBRC8vZ0E3UTFKRlFWUlBVam9nWjJRdGFuQmxaeUIyTVM0d0lDaDFjMmx1WnlCSlNrY2dTbEJGUnlCMk9EQXBMQ0J4ZFdGc2FYUjVJRDBnT1RBSy85c0FRd0FEQWdJREFnSURBd01EQkFNREJBVUlCUVVFQkFVS0J3Y0dDQXdLREF3TENnc0xEUTRTRUEwT0VRNExDeEFXRUJFVEZCVVZGUXdQRnhnV0ZCZ1NGQlVVLzlzQVF3RURCQVFGQkFVSkJRVUpGQTBMRFJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZCUVUvOEFBRVFnQUlnQWZBd0VSQUFJUkFRTVJBZi9FQUI4QUFBRUZBUUVCQVFFQkFBQUFBQUFBQUFBQkFnTUVCUVlIQ0FrS0MvL0VBTFVRQUFJQkF3TUNCQU1GQlFRRUFBQUJmUUVDQXdBRUVRVVNJVEZCQmhOUllRY2ljUlF5Z1pHaENDTkNzY0VWVXRId0pETmljb0lKQ2hZWEdCa2FKU1luS0NrcU5EVTJOemc1T2tORVJVWkhTRWxLVTFSVlZsZFlXVnBqWkdWbVoyaHBhbk4wZFhaM2VIbDZnNFNGaG9lSWlZcVNrNVNWbHBlWW1acWlvNlNscHFlb3FhcXlzN1MxdHJlNHVickN3OFRGeHNmSXljclMwOVRWMXRmWTJkcmg0dVBrNWVibjZPbnE4Zkx6OVBYMjkvajUrdi9FQUI4QkFBTUJBUUVCQVFFQkFRRUFBQUFBQUFBQkFnTUVCUVlIQ0FrS0MvL0VBTFVSQUFJQkFnUUVBd1FIQlFRRUFBRUNkd0FCQWdNUkJBVWhNUVlTUVZFSFlYRVRJaktCQ0JSQ2thR3h3UWtqTTFMd0ZXSnkwUW9XSkRUaEpmRVhHQmthSmljb0tTbzFOamM0T1RwRFJFVkdSMGhKU2xOVVZWWlhXRmxhWTJSbFptZG9hV3B6ZEhWMmQzaDVlb0tEaElXR2g0aUppcEtUbEpXV2w1aVptcUtqcEtXbXA2aXBxckt6dExXMnQ3aTV1c0xEeE1YR3g4akp5dExUMU5YVzE5aloydUxqNU9YbTUranA2dkx6OVBYMjkvajUrdi9hQUF3REFRQUNFUU1SQUQ4QSsyckh3NUtnUEJyMCtjOGZrWmFYdzI1Y0VxZUtibVhHTFJEZGVISFpqZ0dzSEk3SUt4V1BoaHovQUFtbGMzUjYxRG95Um43b3JEbU1lUWsvc2xNL2RGSE9QbEd0b3lNZnVpbHpGcFdHL3dCaUovZEZITU0zZkxyTW9YeTZBRTh1Z0E4dWdDU2dZVUFGQUJRQVVBRkFCUUFVQWYvWiI+Cgk8L2ltYWdlPgo8L3N2Zz4= 32w" sizes="1px" src="/images/medialibrary/539/open-source.jpg" width="2400">

Some more background info on how this all works can be found on the relevant page in medialibrary docs.

Avoiding cookies

We think cookie warnings are ugly and make the user experience worse. To avoid having to put such a warning on our site, we decided that our website shouldn't set any cookies at all. If you want to know how you can avoid setting any cookies in a laravel app, read this blogpost by Dieter Stinglhamber.


Our site does have a very small admin section to upload postcards. Because In order for the csrf protection to work on that form we need to set a session cookie. That's why we sneakily change the session driver when visiting that page.

Add postcard

Gathering visitor statistics

For most of our client sites we use Google Analytics. Because Google Analytics relies on setting cookies we can't used it on Instad of Google Analytics we use Matomo. It's a free, self hosted, open source tool that that can gather information about site visitors. It's easy to install on a server. In order to gather data about a site visitor a small JavaScript snippet is included on every page. It can operate without setting any cookies.


Fun fact: "matomo" is a Japanese words that can be translated as "honesty" or "deceny".

Improving performance by caching the response

Without any caching the app is already pretty snappy. On my MacBook Pro (from 2015) response times vary from 150 to 200ms. In my mind that's very acceptable but we can do better.

One of our popular package is laravel-responsecache. It can greatly speed up any laravel application by caching the entire response. If you need some more on how it works, read this blogpost. With that package installed response times average around 50ms.

We took a pramatic approach to invalidate the cache. Whenever something changes in the database we clear the responsecache. That happens in the base Eloquent model.

Closing thoughts

Our new site was principally designed by Willem Van Bockstal. During development everybody in our company contributed, making this a team effort. We're pretty happy with the results, but we won't stop here. In the coming months we'll add some more content and do some tweaks here and there.

Be sure to check out the guest post by my colleague Willem to know more about what's going on at the front end of our new site.

What do you think of our new site? Let us know in the comments below!

Top comments (0)