Ebb and flow
I’ve been thinking a lot about work-life balance lately. I used to see it as a balancing scale that should remain on the same position at all times. However, I believe a better mental model is to see it as ebb and flow.
by sebastian de deyne
I’ve been thinking a lot about work-life balance lately. I used to see it as a balancing scale that should remain on the same position at all times. However, I believe a better mental model is to see it as ebb and flow.
I occasionally send out a dispatch with personal stories, things I'm working on, and interesting links I come across.
Backlinks, or bi-directional liks, are becoming table-stakes for productivity apps since they’ve been popularized by Roam. It’s a simple concept: when you create a link from page A to page B, page B will also reference page A. With traditional hyperlinks, page B wouldn’t know about page A unless you explicitly link it back.
Backlinks allow a graph of knowledge to grow organically. When you create a doc for Orders, and mention Products, a Products page will be created or updated with a backlink. Even when not actively documenting Products, readers can get an idea of what they entail because of the linked references.
Sometimes you want to spin up a process, but the port it wants to bind to is already in use. Or a port isn’t listening to a process as you expected. lsof is a debugging life saver in these situations.
In most projects, we use git flow to some extent — depending on the project and team size. This includes feature branches.
Feature branches (or sometimes called topic branches) are used to develop new features for the upcoming or a distant future release. When starting development of a feature, the target release in which this feature will be incorporated may well be unknown at that point. The essence of a feature branch is that it exists as long as the feature is in development, but will eventually be merged back into develop (to definitely add the new feature to the upcoming release) or discarded (in case of a disappointing experiment).
Working on a project with a lot of interdependencies between features with a bigger team comes with a new set of challenges dealing with git.
We’ve recently set up a new guideline: if it’s not directly tied to your feature, don’t put it in your feature branch.
Today, we’re launching a new Spatie package: Laravel Google Fonts. I’ve written about Google Fonts before. It’s a great font catalog, but the service has it’s downsides. First, fonts are hosted on a different domain than your app, so the browser needs to do an additional DNS lookup. Second, it’s Google. Privacy-minded visitors might not appreciate the trip to Silicon Valley.
Tl;dr: We use !important because it solves annoying specificity issues. Despite being overkill in most situations, we haven’t come across any practical drawbacks from globally enabling it.
If you want to learn more about how we came to that conclusion and how CSS specificity works, read on!
File watchers are powerful tools. We take them for granted because they’re often baked in, like Webpack rebuilding when you save a file.
Sometimes I’m in an environment without auto-reloading to my disposal. Yesterday, I was working on a CLI tool. The workflow was modify code, save changes, switch to terminal, run the tool, and look at the output. It’s not that bad, but I’d prefer a shorter feedback loop.
I haven’t used Google Fonts in production for a long time. I use the service for development, and strip out all references to Google before going live. I do this for performance, and my visitors’ privacy.
Last year, I read Atomic Habits by James Clear. I first heard of James Clear during Justin Jackson’s Laracon 2019 talk in New York, when he quoted:
Every action you take is a vote for the type of person you wish to become.
No single instance will transform your beliefs, but as the votes build up, so does the evidence of your identity.
This is why habits are crucial. They cast repeated votes for being a type of person.
I picked up the book a while later. It was a great read and I got through it pretty quick! However, the key metric for a book like this is: did it have an impact on my daily life or mental models?
I’ve been using Alpine often lately. Ryan has written a lot of good stuff on Alpine, but his reusable components post is what really got me kickstarted.
You should be careful to not abstract too early. If you are finding it difficult to manage your Alpine component from the
x-dataattribute, this one is definitely for you.
The way this article builds up was very helpful: only use the level of abstraction you need:
x-spreadTo execute a piece of code when the viewport is a certain size, the first thing that comes to mind is adding a resize event listener to the window object. This is one way, but not always the best. Sometimes the lesser known window.matchMedia API is a better fit.
1 Apr 2021 via freek.dev
Freek wrote about cleaning up inactive user data from Oh Dear:
You want to keep only as little personal data as needed for privacy reasons. You should only collect and keep the absolute minimum of data needed to run your application. This keeps your user’s privacy safe and minimizes the risks for you as a company if a security breach happens.
This is a really good initiative, I can’t even imagine how much data I have scattered across hundreds of trial accounts on the internet…
I can’t count the amount of times I’ve defined an object type with unknown string keys and a specific value type.
type Scores = {
[key: string]: number;
}
And despite using it all the time, I can’t for the life of me remember the [key: string] syntax.
Today, my problems are solved. Apparently TypeScript has a built in Record type that does exactly that:
type Scores = Record<string, number>;
I’ve used HasOne relationships for 1:1 relationships, but those are rare. I haven’t considered using them to scope down relationships, like having one default payment method in a set of n methods.
<?php
class User extends Model
{
public function paymentMethods(): HasMany
{
return $this->hasMany(PaymentMethod::class);
}
public function defaultPaymentMethod(): ?HasOne
{
return $this->hasOne(PaymentMethod::class)
->whereDefault();
}
}
$user->defaultPaymentMethod;
After reading Tim’s post, I have a feeling there are some places where I needed this but didn’t think of it at the time…