# 2023 Homepage Rebuild

<div class="full-w-child">

**TLDR**: I redesigned and rebuilt my blog with [zaduma], [Astro],
[Solid.js][solid], [Tailwind], [MDX], [Shiki Twoslash][shiki-twoslash], [Vercel
OG][vercel-og] on Edge Functions, [Astro Image][astro-image], [Plaiceholder]

</div>

[zaduma]: https://github.com/hasparus/zaduma
[astro]: https://astro.build/
[solid]: https://www.solidjs.com/
[tailwind]: https://tailwindcss.com/
[mdx]: https://mdxjs.com/
[shiki-twoslash]: https://shikijs.github.io/twoslash/
[vercel-og]:
  https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation
[astro-image]: https://docs.astro.build/en/guides/integrations-guide/image/
[plaiceholder]: https://plaiceholder.co/

## Motivation

I've survived a couple of years without redesigning my website, a nice score for
a person building user interfaces daily. Until now. Surprisingly, I'm not
motivated by the framework churn and the hype for Astro, nor frustration with
the tech debt decay and dependency drift of my previous homepage codebase.

Neither am I pursuing better performance metrics. Going from a static website
built with Gatsby to a static website built with Astro gets me less JavaScript
shipped, shorter build times, and frees me from using GraphQL to read a markdown
file, but it's not a _huge_ change from the visitor's perspective.

I had fun building my previous homepage. It was over-engineered, and it had
everything: fp-ts, backlinks, a Roam-inspired force graph of notes, custom
Gatsby plugins, you name it.

On [my old website](https://old-hasparus.netlify.app/) I handwrote and animated
an actual SVG sandwich for the menu icon. And then I overengineered it to work
without JavaScript with `#menu-id:target ~ &` trick.

import Hamburger from "../src/own/2023-homepage-rebuild/Hamburger.astro";

<aside>
  You've made some of my friends laugh, but it's time for you to go, my dear
  icon.
  <Hamburger style="margin-top: 4px" />
</aside>

**[Fun is over](/posts/2022-and-change.mdx). I'm a boring person now, and I want
simplicity.**

I'm trying to do something more basic, more classic. I'm choosing simpler tech
and almost minimal design.

## Design

To get to that _boring and classic_, I chose a grayscale color scheme and
centered layout. I've spent
[some time](https://twitter.com/darylginn/status/1620371874609008640?s=20&t=pwuhIlc1LPfcH4K_xarZkg)
thinking about typography. I'm not completely satisfied, but I settled on the
standard Inter and a personal touch of
[Brygada 1918](https://fonts.google.com/specimen/Brygada+1918).

I'm slowly starting to consider removing Brygada and going with just one font,
but I do find the current state of things quite passable, and I can't keep
fiddling with it ad infinitum.

Centered layout is practical. It allows me to use the left side for a table of
contents, and the right side for `aside`s with comments and tangentially related
notes.

## Tech Stack

### Zaduma

I've built an Astro starter, called [Zaduma] to work on all the features I want
in isolation, and not when I'm writing a blogpost.

[Aleksandra] had a Gatsby site too, so now we're collaborating on the starter.
We'd like Zaduma to be a minimalistic starter for technical weblogs and
documentation pages. We've added some personal touches like a grain overlay and
[Shiki Twoslash][shiki-twoslash], assuming that TypeScript is already a most
popular programming language.

[aleksandra]: https://aleksandra.codes

### Astro

We went with [Astro], firstly because it just fits, and SSG is fair choice for a
blog. Secondly, because I started before Next 13 was announced, and Astro was
first on my list of new things to learn. We want to ship less JavaScript, and
get nice perf out of the box.

### Solid.js

For the components framework, we're taking [Solid], because it's absurdly good,
especially coming from React. It still doesn't have enough of an ecosystem, and
until very recently it lacked equivalents of accessible foundations style
libraries like Radix UI, but I won't need much here. I'm fine with writing my
own command pallette instead of downloading `cmdk`.

### Tailwind CSS

[Tailwind] gets us a nice set of design tokens, and it's popular enough we can
use it in a public starter. Combined with the VSCode Extension, it becomes
arguably the best CSS-in-JS library, with an added benefit of not being a
CSS-in-JS library, so you can use it in your old Rails projects and on your
mom's Wordpress website.

If you're not a person who builds design systems and frontend tooling daily, and
you don't have time to check out every CSS solution, stick with Tailwind.
Atomic&nbsp;CSS gets us the best performance and a surprisingly small number of
footguns. It's just good.

<aside>
Read more:
[React 18 CSS-in-JS Library Upgrade Guide: `<style>`](https://github.com/reactwg/react-18/discussions/110)
[@sebmarkbage on Atomic CSS](https://twitter.com/sebmarkbage/status/1529622371333709825)
</aside>

[Vercel OG][vercel-og] takes care of social card pictures. It was a bit of an
investment to set it up on Vercel Edge Functions with Astro, but I feel it will
pay off.

## Performance

### Metrics

There are some perf improvements that could have been done on my old site, but
it was still all green.

import TableCellImage from "../src/own/2023-homepage-rebuild/TableCellImage.astro";

<Table class="hsp--measurements">
  <thead>
    <tr>
      <td>Mobile with Gatsby</td>
      <td>Desktop with Gatsby</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <TableCellImage src="/2023-homepage-rebuild/old-mobile.png" />
      <TableCellImage src="/2023-homepage-rebuild/old-desktop.png" />
    </tr>
  </tbody>
</Table>

With Astro, Astro Image and [Plaiceholder], we top that. Turns out a
black-and-white website with little to no content is pretty fast. May not be
much to celebrate, but getting a [FCP](https://web.dev/fcp/) under one second,
and 4x100 scores on [web.dev/measure](https://web.dev/measure/) makes me smile a
bit.

<Table class="hsp--measurements">
  <thead>
    <tr>
      <td>Mobile with Astro</td>
      <td>Desktop with Astro</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <TableCellImage src="/2023-homepage-rebuild/zaduma-mobile.png" />
      <TableCellImage src="/2023-homepage-rebuild/zaduma-desktop.png" />
    </tr>
    <tr>
      <TableCellImage src="/2023-homepage-rebuild/zaduma-with-image-mobile.png" />
      <TableCellImage src="/2023-homepage-rebuild/zaduma-with-image-desktop.png" />
    </tr>
  </tbody>
</Table>

### Preloading fonts

Preloading Inter helps me get away with `font-display: block`. I realize it's
silly, and I should use `swap`, but my eyes strongly prefer invisible text over
Flash Of Unstyled Text.

<style>
  {`.preloading { font-size: 0.75rem !important; padding-top: 0; padding-bottom: 0; }`}
</style>

```astro class="preloading"
---
import interPath from "@fontsource/inter/files/inter-latin-variable-wghtOnly-normal.woff2";
---

<link rel="preload" href={interPath} as="font" type="font/woff2" crossorigin />
```

### Caveats

[Zaduma] was my first Astro project, and unsurprisingly, I had to confront my
application developer habits with MPAs. Displaying a shared UI element which
state depends on `localStorage` (like a color scheme toggle) is a hard problem.
I wrote about it
[in zaduma repo](https://github.com/hasparus/zaduma/blob/main/docs/tradeoffs-and-limitations.md#trade-offs--limitations).
Even [Astro docs](https://docs.astro.build/en/getting-started/) have this issue,
so I ended up pivoting to a command palette.

---

If you end up [generating](https://github.com/hasparus/zaduma/generate) your
website with Zaduma, please let me know what you think and if you encountered
any bugs. Thank you for your attention 🙏
