td204

Web development, one post per year since 2002

2022 in review: the year I adopted nothing

I did not add a single new tool to my stack in 2022. Same bundler, same CSS approach, same framework versions. One new project, and it started from the same skeleton as the previous one.

It shows up in the numbers too. 2022 is my quietest year on GitHub since I started pushing there: roughly 680 commits, against 1,150 the year before and 1,700 in 2019.

For a while that felt like a gap in the story. It is not. 2019 to 2021 was three years of replacing things, and at some point you have to use what you built rather than keep rebuilding the workshop. So instead of a new tool, here is the practice I standardised this year.

The four tests I now write before any feature work

Nobody has ever approved a budget line called "unit tests". So I stopped asking, and instead write four tests on every project in the first hour. About twenty minutes total, and they have caught more production bugs than everything else I do.

1. Every public route returns something that is not a 500. Cheap, broad, catches the "I renamed a view" class of bug across the whole app.

it('renders every public page', function (string $uri) {
    $this->get($uri)->assertSuccessful();
})->with([
    '/',
    '/contact',
    '/nieuws',
    '/over-ons',
]);

Add a URI every time you add a page. It is a checklist that runs itself.

2. The thing behind the login is actually behind the login. Whatever is protected is what ends up unprotected after a refactor.

it('keeps the dashboard behind a login', function () {
    $this->get('/dashboard')->assertRedirect('/login');
});

it('lets a logged-in user in', function () {
    $this->actingAs(User::factory()->create())
        ->get('/dashboard')
        ->assertSuccessful();
});

3. The one form the business runs on. Every project has one: the quote request, the booking, the order. Test that it validates and that it does the thing.

it('stores a booking and mails the office', function () {
    Mail::fake();

    $this->post('/booking', [
        'name'  => 'Jan',
        'email' => 'jan@example.com',
        'date'  => '2022-10-01',
    ])->assertRedirect('/bedankt');

    expect(Booking::count())->toBe(1);
    Mail::assertSent(BookingReceived::class);
});

Mail::fake() is the line people forget. Without it, the first person to run the suite mails the client's office.

4. The calculation nobody can check by eye. VAT, proration, shipping bands, a discount that stacks. Boundaries only.

it('applies the volume discount at exactly 10 items', function (int $qty, string $expected) {
    expect(Cart::for($qty)->total()->toString())->toBe($expected);
})->with([
    [9,  '€ 90,00'],
    [10, '€ 85,00'],
    [11, '€ 93,50'],
]);

Nine, ten, eleven. That is where the off-by-one lives.

Four tests will not give you a coverage badge. They give you the thing you actually want at 17:00 on a Friday: permission to deploy.

The one thing that did change: how designs arrived

If I look at what actually varied between 2020 and 2022, it is not my stack. It is the file the designer sends. Layered PSDs, then a Figma link, then an XD file, then a PSD again from a designer who never moved.

For a while I treated that as a nuisance. It is worth saying plainly what it actually is: the handoff format is the designer's tool choice, not mine, and building anything that depends on it is building on somebody else's decision. What I need out of a design is the same in every format, and it is not the file: it is the spacing scale, the type scale, the colour values and the breakpoints.

I now ask for those four things explicitly, in text, whatever the file is. That question has saved more time than any tool I adopted in the three years around it.

In short

Added no new tools at all. Standardised the four tests I write on every project, and watched the design handoff format change three times.

The year in commits

Commits by month in 2022: 682 in total, peaking at 92 in Feb.
Jan 2022: 90 commits J Feb 2022: 92 commits 92 F Mar 2022: 73 commits M Apr 2022: 76 commits A May 2022: 40 commits M Jun 2022: 63 commits J Jul 2022: 19 commits J Aug 2022: 54 commits A Sep 2022: 39 commits S Oct 2022: 62 commits O Nov 2022: 56 commits N Dec 2022: 18 commits D