Easy Screenshot Hack?

The custom dimensions drop down in Google Chrome

I recently found myself in a position where I had to take several screenshots – we have just launched Budget and did a final review to improve all the content and update all the images, whilst doing so, I discovered a hack.

Old Screenshot Method

In the past I would either screen grab the bit I wanted, or screen grab the entire page and crop the section I wanted in my editor of choice.

Deciding on the focus for the screenshot was always tough. You know what part of the page you want in focus but it’s tough deciding how much extra you need to include in the image to keep it consistent with other images on the page.

The Screenshot Hack?

OK, so what is the hack? Well, Chrome.

I was testing the responsive layout on one of my Apps and saw the “Edit” menu item in the “Dimensions” dropdown.

I set up a couple of custom options, 400 * 400 and 390 * 725 and boom! I have a nice frame for screenshots and can decide on the focus as well as ensure all the screenshots are the same size.

Late to the Party

To anyone that is a designer or discovered this “hack” a decade ago, I’m sure this revelation is laughable! However, if you are a developer first like me and need to take consistent screenshots. I’d suggest giving this a go.

I accept that very few people will learn anything from this hack; I’m obviously not adding anything to any developer’s toolkits. However, as much as this doesn’t add anything useful, you might be interested in reading about the project setup I’ve settled on which has been working well for years.

Multiple computers, the benefit

A shot of multiple devices and computers

Multiple computers can help you find more bugs in your Apps

I have a few computers that I use, most people would say too many, for me though, it works. Having multiple computers gives me the freedom to work in more than one location. I have my main desktop in my office, my old still usable desktop in my wife’s office space and two laptops, a Surface Book and a Macbook Pro. Both the Macbook Pro and Surface Book are a little long in the tooth, but they still work well enough for when I need to take a machine onsite for freelance or contract work.

Why am I mentioning I have a use multiple PCs, well, there are a whole host of development problems that you solve because you use multiple machines. Additionally, because I use multiple machines, I tend to make fewer changes to my setup than I used to. Other than my IDE of choice and Docker, my setup is simple, this makes it easier to replicate across my computers.

What is the gain?

So, what is the gain? Well, you can only use multiple PCs if your Apps are setup on each of them, this is the benefit, because you have to setup each App more than once you quickly get to spot any issues, if you added an extension when you developed a feature, boom, you’ll notice, if it isn’t easy to get your tests to run, boom you’ll notice. It also gives you the opportunity to test the first install process for your Apps, you’ll quickly notice the necessary data you added outside of a migration or the path that isn’t mapped.

Yes, having multiple computers is a luxury, the thing is though, keep your old stuff, it is more functional than you realise.

If you don’t have multiple machines, you can always use someone else’s, add an account to your partner, child’s, siblings, or parents’ computer, with their permission of course. Even if you only rarely setup one of your projects on another machine, you are bound to spot an issue you didn’t know existed.

Simpler than years ago

These days tools like Docker have solved a lot of the problems we used to experience but I still think you will find an issue or two when you setup an App fresh on another computer, especially if that App has been in development for a while or moved beyond basic functionality.

Budget – Official Release

Budget - The Official Release

Late last year, I released Budget, a free open-source App powered by the Costs to Expect API, with a beta tag. After bringing the Wife on board to help, we started to respond to feedback and polish the App. We wanted as much feedback as possible before the official release which is now ready.

Beta Release

We spent quite a while testing the App before releasing it with the beta label. However it is always amazing just how many issues appear when the public at large start using your stuff.

We ended up pushing seven small updates, each improving the UX and UI of the App that extra little bit. All these improvements will make it into Budget Pro (the subscription version of Budget) and eventually all my other Apps. After 25 years of web development, I still admit I have a lot to learn and am always happy when I do learn something new.

I’ve released several Apps over the last two years. However none have been as polished as Budget and I have to say I am proud of what I’ve created and keen to start focusing on Budget Pro, the commercial offering of Budget.

I have a blog post coming soon explaining why there are going to be two versions of Budget and why they are going to be created in the way they are. The short story is, I’ve always intended for the Apps to be separate, and I think the approach I’m taking will ensure that they can each shine in their own way.

The Next Chapter

This is the start of a new chapter and I’m keen to see where it goes, only time will tell.

We learned so much during the last two months, hopefully we can benefit from the new knowledge as we approach the beta release of Budget Pro. Budget Pro is much more complicated than Budget so I’m sure we will discover an entire new set of issues which hopefully our beta users will be able to help us resolve.

My typical project setup for Laravel

Laptop with movie style code

This is one of those posts that is more of a reference for me rather than general information, if however, you use PHP, Docker, MySQL, Windows, WSL2 and PHPStorm this post about my typical project setup may be of interest to you.

Docker and WSL 2

I use Docker, specifically docker compose. Typically, I define two services in the docker-compose.yml file, [project_name].app and [project_name].mysql. If the project is part of a service I will define a network, this is to make it easier for containers to communicate. All the Costs to Expect Apps rely on the Costs to Expect API so they all share the same network.

Below is an example of a docker-compose.yml file for Budget, our free budgeting tool.

version: '3'
services:
    costs.budget.app:
        build:
            context: .
            dockerfile: .docker/app/Dockerfile
        image: costs.budget.app
        container_name: costs.budget.app
        ports:
            - "80:80"
        volumes:
            - .:/var/www/html
        env_file: .env
        environment:
            TZ: UTC
            DB_HOST: ${DB_HOST}
            DB_DATABASE: ${DB_DATABASE}
            DB_USERNAME: ${DB_USERNAME}
            DB_PASSWORD: ${DB_PASSWORD}
    costs.budget.mysql:
        build:
            context: .
            dockerfile: .docker/mysql/Dockerfile
        image: costs.budget.mysql
        container_name: costs.budget.mysql
        ports:
            - "3306:3306"
        env_file: .env
        environment:
            TZ: UTC
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_USER: ${DB_USERNAME}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
        volumes:
            - ./.docker/mysql/data:/var/lib/mysql
networks:
    default:
        name: costs.network
        external: true

I typically leave the ports at their default values; the exception is when I know I will need to run more than Docker container at a time. I always need to run the Costs to Expect API at the same time as another App so will typically map the ports on the API to 8080 and 3308.

The dockerfiles for each of the services exist in a .docker folder. I typically end up with .docker/app/Dockerfile and .docker/mysql/Dockerfile. The .docker/mysql folder will also contain a data folder, this is the volume for the MySQL data.

The MySQL Dockerfile doesn’t include any configuration, just FROM mysql:8, the example below shows a Dockerfile for a typically Laravel application.

I used to include Composer and PHPUnit but have moved away from the additional complexity as it didn’t really offer any benefits and just made configuration in PPHStorm more compleicated.

FROM php:8.1-apache

COPY . /var/www/html
COPY .docker/app/vhost.conf /etc/apache2/sites-available/000-default.conf

RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd

RUN apt-get update && apt-get install -y \
    zip libzip-dev \
    && docker-php-ext-configure zip \
    && docker-php-ext-install zip

RUN docker-php-ext-install pdo_mysql bcmath

RUN chown -R www-data:www-data /var/www/html \
    && a2enmod rewrite

WORKDIR /var/www/html

PHPStorm, Composer and PHPUnit

PHPStorm works relatively flawlessly with WSL2, well it did and will again without a tweak after the 16th of January.

I store all my project files in WSL2, specifically Ubuntu, the project root for PHPStorm will normally be something like \\wsl$\Ubuntu\home\[user]\Projects\[project_name]. I have a Projects folder inside my home directory and a folder for each project. The Projects folder includes any phar files I might need so as not to duplicate them across projects.

The CLI Interpreter is set to my distro of choice, so in my case Ubuntu.

Composer settings are as defined as below.

  • Path to composer.json //wsl$/Ubuntu/home/[user]/Projects/[project_name]/composer.json
  • Execution, composer.phar
  • Composer.phar location \wsl$\Ubuntu\home\[user]\Projects\composer.phar

PHPUnit settings are defined as below

  • Remote Interpreter
  • Use composer autoloader
  • Path to script /home/[user]/Projects/[project_name]/vendor/autoload.php
  • Test runner default configuration file /home/[user]/Projects/[project_name]/phpunit.xml.dist

This project setup works well for all my projects as if I ever need to use a different version of PHP or MySQL I can update the dockerfiles for each service and rebuild. I recently needed to upgrade an App form PHP5.6 to 8.0, this setup made it easy to upgrade to each version of PHP and MySQL along the way and test at each step.

If I need to use Tailwind, SASS or other tools, I try to use them via WSL2 before going the Windows route.

After reading this you may wonder why I use Windows for development, there are three main reasons, one, I’m comfortable with Windows, two, I play games, three, I build my own PCs. The setup above will work regardless of your operating system of choice.

Don’t stiff clients, upgrade your stuff

Image shows a click with the text "Time to upgrade"

A client recently asked me to setup a Silverstripe site on their server. They were in the process of getting the files and database extract to me and then I would be good to go. I hadn’t used Silverstripe since 2008 but figured, why not? Setting it up on a new server shouldn’t be too much of an issue…oh boy, was I wrong!

After a while, I received the files and a database dump. Everything seemed ok although I was surprised to see an included vendor folder. I checked the composer.json file to see what I was working with and well, I was a little concerned. PHP was set to 5.6 and all but two requirements were set to dev-master and silverstripe/recipe-cms was set as 4.2.*, released sometime in 2018.

Get it working

OK, so the developers had installed Silverstripe in 2018 and never felt the need to upgrade it, not even once. So I thought, I’ll set up a dev environment and get going.
I created a Docker container with PHP5.6, MySQL 5.7, and a few extensions. I copied everything in, including the vendor folder and managed to get a half working website running. It wasn’t quite as easy as described as I needed to work out what extensions I needed and fix a couple of minor bugs, but the site was working.

I thought cool, now I can start upgrading the site. It was at this point I recalled every dependency was set to dev-master. So the first step was to set the correct version for each dependency. Well, the version as of 2018 and get a composer install to work.
I checked the installed.json inside vendor/composer and found the commit hash for each dependency. I then found the related version on GitHub and updated the composer.json. This was tedious work; however, I figured I was working towards getting a working composer.json. When done, I discovered this wasn’t going to work; the provided composer.json did not create the included vendor directory and there was too much stuff missing.

I decided to go back to basics and create a brand-new composer.json including every package listed in vendor/composer/installed.json. Eventually I got to the point where I could run composer install with no vendor directory or composer.lock file and get a working vendor directory. Awesome!

Although this worked, I couldn’t yet start upgrading as there was too much listed in my composer.json. I started checking each package to see if it was a core requirement or a dependency of something else and pruned the composer.json file down to the bare minimum. Several hours later, I again had a working composer.json file.

Upgrade it

A day in and I had a working Silverstripe site, running on PHP5.6 and MySQL 5.7. I was also confident I could clear the “vendor” directory and recreate it. As joyous as I was, I was no further along. I couldn’t put this online as I needed it to be running PHP8.0 at a minimum and MySQL8. Additionally, I was having to use composer 1.10.26 – that also had to change.

I started the upgrade process; I went step by step starting at 4.2.0 all the way up to version 4.10.0. At each release, I would trash the vendor directory and composer.lock file and see if I ended up with a working site. It was slow as I kept needing to tweak things. Every time Silverstripe added support for an updated version of PHP, I would rebuild my Docker container and test again, slowly fixing bugs and correcting dependencies as I went. As soon I was running PHP8, I switched to MySQL 8 and manually updated the database schema.

Stable & Supportable

The site is now sitting on a staging server for the client. There are a few small issues here and there that I need to fix, and I need to continue upgrading to the latest version of Silverstripe, however, for now, this client is happy.

The moral of the story – upgrade your stuff. If you are selling a website to a client, at least have the decency to upgrade it. Handing them a hot mess four years later is disgusting and the “development house” in question should be ashamed of themselves.

I’m not going to name the “development house” as I don’t know if this was a one off. I expect not but it isn’t for me say as I never dealt with them directly, I just had to pick up the mess.