Hello, blog!
Published: .

It has been many years since I had my own custom website. For a long time, I had theetrain.ca pointing to a straightforward about.me page that acted as a small link farm. And I could continue to have that since it served its purpose well; corroborate my identity whenever I meet people or hand out business cards.
My main motivation for starting my own custom site was to own my own content and start writing again. If you’re reading this, then mission accomplished! I have a few articles published on Medium that I hope to migrate here and take proper ownership of my writings. They’re still published if you would like to check them out at medium.com/@theetrain.
I could have chosen a tailor-made framework for blogging such as Ghost, Astro, or WordPress, but I decided to use SvelteKit since I’m a Svelte ambassador and want to remain connected to the project’s latest features. I eventually want to make my own UI library and hope this website could serve as a testing ground for that, and I may blog more about those ambitions in the near future.
How I chose tools for my custom blog
That brings me to this website; here is a breakdown of the tools I’ve selected for its initial build:
- SvelteKit: to prerender pages and serve a robust site that benefits users with or without JavaScript enabled or available.
- mdsvex: author content using markdown and as-needed Svelte components, and prerender code fences.
- Content Collections: rather than roll
my own, I went with an opinionated library that closely resembles Astro
content collections; that way I only need to maintain content in my
/blogroute and use a streamlined API to find and serve pages. - Sugar.css: a minimal CSS framework that primarily acts as a classless library. I’m aligned with its goal of emphasizing HTML, accessible layouts, and that “design is based on rules rather than feelings”.
- fontless: a Vite plugin that handles the very difficult challenge of providing fallback fonts and sizing them in such as way to prevent layout shifts during font swap.
SvelteKit aligns very closely with my values as a front end developer;
optimize as much as possible at build time, and deliver a great user experience
without compromising heavily on developer experience. It’s particularly great
for building Node.js applications; all routes are server-rendered by default,
forms are first-class patterns, and navigating with plain anchor links will
progressively enhance to client-side navigation once the page hydrates. Users
with degraded connections can still request or mutate information since those
actions still process server-side.
“Svelte” can be interpreted in multiple ways; for me it’s about:
- Reducing authored code to the smallest amount that gets served to users.
- Reducing your supply chain footprint.
- Reducing your mental load while solving problems
- Reducing your attempted solutions to the ones that benefit users most (this includes accessibility linting).
Less is less, and that is good.
Style and typography
This site’s design is a work in progress that I decided to improve iteratively from a functional base; which is why I chose Sugar.css.
fontless is particularly helpful, right as I was finishing up my initial
site design (as well as this blog post) I realize it paragraphs of text were
unpleasant to read. I applied a unitless line height of 1.8 and went through
the toil of setting up my preferred font Lexend and its @font-face declarations, downloading and serving the font myself, choosing a fallback font,
measuring and resizing the fallback font to avoid layout shifts. It’s a whole
ordeal, but fontless allows me to achieve all of that in one CSS rule:
body {
/* To prevent layout shifts on short pages. */
overflow-y: scroll;
font-family: 'Lexend', Helvetica, Arial, sans-serif;
font-size: 110%;
} I only needed to define 'Lexend', sans-serif;, really, but I explicitly
ordered some preferred system fonts and let fontless handle all the rest. I
also added a toggle to allow users to switch between a serif and sans font. The
toggle sets data-font-style on the <html> tag, and my CSS is very
straightforward while fontless handles all the @font-face rules at build time:
:root {
/* Variables and other stuff */
&,
&[data-font-style='serif'] {
font-family: 'Source Serif 4', serif;
}
&[data-font-style='sans'] {
font-family: 'Lexend', Helvetica, Arial, sans-serif;
}
} Security and maintenance
Build time optimizations are great! What’s not so great is my SBOM; at the time of this writing, this project has 463 total dependencies; which includes transitive dependencies. I generally prefer to keep this number under 500, which is particularly challenging to do in larger applications. Maybe I can go into more detail in a future blog post.
Importantly, even though a fraction of the named exports from a fraction of this project’s dependencies may end up on production, I don’t want my development machine to fall victim to a supply chain attack for the rest of my installed packages. You’re welcome to measure your own project’s dependencies by running either one of these commands:
# npm
npm ls --all | grep -v deduped | grep -v "UNMET OPTIONAL" | wc -l
# pnpm
pnpm list -r --parseable --depth Infinity --no-optional | wc -l Accessibility considerations
Every front-end related blog post should touch on accessibility. My site covers a lot of what should be considered as ‘basics’, such as, but not limited to:
- Add
aria-current="page"to links when their link corresponds to the active page. When a link’s page is current, also sethref="#main"to skip to the main content rather than request a new page. - Underline most links, particularly within body content.
- Use a 7:1 contrast ratio for text-to-background contrast.
- Ensure text size adapts to browser preferences.
- Provide alternative text to images.
- Omit pseudo element content from bloating screen reader or Braille output, particularly for interaction labelling such as breadcrumb links and toggle buttons.
In short, automatic accessibility tests should pass as a baseline. Some novel implementations I have include:
- A skip link as the first interactive element.
- An icon next to links representing the current page.
- External links revealing “(external)” as text on hover or focus.
- A 3-mode theme switcher and font style toggle that remains disabled with
aria-busy="true"until JS hydrates the page, in order to signal a imminent interactivity. I hope to follow up with<noscript>representations.
Of course there’s a lot more that can be done. If you notice any issue with this site’s usability, I’d greatly appreciate a new issue at theetrain-website repository.
Last, but not least, this website is my garden. LLM use has been very limited to a few queries or debugging sessions, and hardly any code was generated or put to use via agents or autocomplete. More practically, this site’s content dictates its design and functionality needs. From the content, I work backwards to their solution on how to best serve information and promote the points I want people to most easily reach.
This website is open source for your educational interests, and you’re welcome to reference its code for your own work: github.com/theetrain/theetrain-website.