Each section has 'why not' and 'when should you', so really it's a "Do (only) when" recommendation.
I don't see sufficient justification for "Don't use serial"--the some weird behaviors links to a 404 page.
The "Don't use varchar(n) by default" reasoning is similarly weak.
This post doesn't doesn't give enough detail reasoning to be self-evident, and other than the quality of formatting could be a collection of anyone's blog posts. Some recommendations seem to be solid, but mixed with the arbitrary ones loses some of its recommendation strength.
Enforcing UTC inside the system and converting to the correct time zone for display purposes is fine though. Makes a lot of sense when the recorded time zone isn't relevant in itself, booking systems for example.
Use UTC + convert to local time for display if the time is a global event, i.e. something that happens at the same time everywhere. E.g. an online meeting, conference start time, missile launch schedule, etc.
Use time + timezone if the time is always local to a particular user and should follow their time zone. E.g. wake up alarm, eat breakfast schedule,
The problem is these definitions are already a bit fuzzy and it's not always clear which type it is even to the person creating it.
There's also "char", with quotes, as a special type. It's always 1 byte.
The other types have overhead. A single-byte bytea will actually use 2 bytes, char(1) will use at least that much, and bit(8) will use 7 bytes. Smallint is strictly better for representing small numbers.
A good reason not to use it is that 49::"char"::int == 49, but 49::"char"::smallint == 1. In other words, int casts directly interpret the value as an integer, but smallint (and bigint) casts interpret it as an ASCII character, '1', which they then convert to the integer 1.