Skip to content

Web Frontend Code Quality

Follow these rules to write high-quality frontend code. We’ll assume the framework is React, but most of this applies to any HTML/CSS/JS on the web.


For this reference, I’ll be using Tailwind for simplicity (still broadly applicable to any CSS framework).

This is a bit of a pet-peeve of mine, and I even see it in starter kits.

Here are two example components:

<div className="flex flex-col gap-1">
<label htmlFor="email">Email</label>
<input name="email" />
</div>
<div className="grid gap-1">
<label htmlFor="email">Email</label>
<input name="email" />
</div>

Both of these work fine, they’re just unecessary. In the worst case, nested grid layouts can behave in unexpected ways, especially when elements change size. A cleaner, and less expensive method:

<div className="space-y-1">
<label htmlFor="email">Email</label>
<input name="email" />
</div>

The space utility applies margin to the children elements to space them out, avoiding the need for flexbox / grid.

Another pet-peeve. Once you see it, you can’t unsee it. Here’s a Tailwind snippet that makes nested borders concentric and pixel perfect.

<div class="rounded-(--card-radius) p-(--card-padding) outline [--card-padding:--spacing(3)] [--card-radius:var(--radius-4xl)]">
<img class="aspect-square rounded-[calc(var(--card-radius)-var(--card-padding))] object-cover outline" src="" alt="" />
</div>

While a bit verbose, this is nice because:

  1. Declaring the variables looks very intentional, which helps maintainers understand things
  2. It’s parametric, so when the theme is updated, the code doesn’t need to be

cn (usually shadcn’s wrapper for classnames or twMerge) is a great utility for composing styles. However, I’ve seen it misused for creating variations of components. We actually have a tool for that, it’s called cva (class-variance-authority).

Here’s an bad example of creating component variants:

function badgeVariants(value: string): string {
return cn(
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium",
value === 'open' &&
'border-emerald-200 bg-emerald-50 text-emerald-700',
value === 'responded' &&
'border-yellow-200 bg-yellow-50 text-yellow-700',
value === 'ignored' &&
'border-gray-200 bg-gray-50 text-gray-700',
);
}

Here’s a tidier version that can also benefit from strict type checking:

const badgeVariants = cva(
'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium',
{
variants: {
status: {
open: 'border-emerald-200 bg-emerald-50 text-emerald-700',
responded: 'border-yellow-200 bg-yellow-50 text-yellow-700',
ignored: 'border-gray-200 bg-gray-50 text-gray-700',
},
},
}
);

It also makes it far easier to define complex variants, without complex and error-prone boolean logic. Read the cva docs for more info.

This is the best guide for why and how to remove unnecessary effects from React code: https://react.dev/learn/you-might-not-need-an-effect

There are plenty of problems that can be introduced through using the ‘quick hack’ of a useEffect to fix things. After all, React is a functional paradigm. The docs link above goes through it best, but in summary:

You probably don’t need a useEffect.

Data fetching should probably use a library like tanstack-query or RSC (if ya retarded).

There are still valid use-cases:

  1. Interacting with external APIs is fine, like the browser geolocation API - this is what side effects are for (even Tanstack uses them under the hood).
  2. Timers, cleanups, animations, transitions, etc.

Some useEffect is still necessary.

We need to use it in the right places, and avoiding incorrect usage.

Not necessary, unless performance intensive. Having it in may lead to slightly worse performance. Useful if you need to maintain referential equality, i.e. you’re passing the function reference to a useMemo dependency array and you don’t want the reference to change on every re-render. React compliler actually optimises code past the need for useMemo and useCallback these days, so they’re certainly less useful than they once were.

Accessibility screen readers forced colours reduced motion