Really impressive demo. First, this is for single-page applications. Second, there is an API for multi-page applications. Check it out in Chrome Canary and look at the code. I discussed this with my team yesterday. The demo is built on Astro. All that is shipped to the browser is 301kB. Of that 291kB is images. Less than 5.5kB for the document, CSS, and JS. CSS is powering the transitions and only a bit of JS intercepts the navigation event, loads the fragment of HTML, injects it into the DOM, and adds the necessary classes to trigger the animations.

This is a truly impressive demonstration. With very minimal effort, one can use an SSG like Astro— which can run as an SSR too— and deliver a fully working application that requires no JavaScript but progressively enhances to dynamic page transitions with easy— something that is extremely difficult even for SPA libraries— and asynchronous page loading. Only 150 lines of JS are in this project— 150 lines that ship to the browser.

For an old curmudgeonly standards guy like myself, this gives me some hope that we can get back to the days of the largest assets we send to the browser are images instead of hundreds of kilobytes of JavaScript.

Source: Bramus

Wrote this five years ago. Then it was Bootstrap and a bunch of JavaScript ninjas that didn’t know HTML/CSS. Now it’s Tailwind and a bunch of React ninjas that see HTML as an implementation detail and CSS as fundamentally broken.

Between the various CSS-in-JS solutions and the use of massive UI frameworks— looking at you MUI— we have taken frontends that could be lightweight, fast-loading, and enjoyable and made them into monstrosities of slowness.

I was looking at a website for a development agency in Atlanta last night and my 8 year old laptop got so hot the fans had to spin up. The website wasn’t even doing much beyond showing some content with some simple animations. I could understand not being able to run the latest games on my laptop but content-centered websites shouldn’t be doing this.

When every new website on the internet has perfect, semantic, accessible HTML and exceptionally executed, accessible CSS that works on every device and browser, then you can tell me that these languages are not valuable on their own. Until then we need to stop devaluing CSS and HTML.

Mandy Michael

Preach! It’s all I see these days in job descriptions. JAVASCRIPT! Ninja preferred. Rockstar acceptable. And then they produce crap frontend code. Their HTML and CSS is restricted to Bootstrap at best, custom crap with style attributes all over the place at worst. When I was their age, the emphasis of frontend was on the other side of the triangle: HTML and CSS. Without these, your JavaScript means nothing. Even if you are embedding your CSS and HTML in your JavaScript. Shudder.

Astro Build Performance

Sixty-five seconds just to build out the first pages of the #tech pages. Why? Because they are reliant on a complex function that gets a tag map. So let’s understand how pages are built for a route, from what I gather.

function doComplexThing() {
	const things = [];
	// do the thing

	// return the data
	return data;

The getStaticPaths method returns an array of pages and their data. This is called once. So that complex function? Not really a problem here. Then Astro renders each page that getStaticPaths returns. The problem is that I need that complex function’s data here too. Without calling it here, we build these pages in 10 seconds. With it, 65.

export async function getStaticPaths() {
	const things = doComplexThing();
	return => ({
		params: {
			tag: thing

Okay, now we have options. We could just put that data in the paths’ props. But it is used by a component in the page that is rendered. We could pass that data as a prop to that component. But it would be easier to call it inside the component. 65 seconds. And that’s just a fraction of the pages that need to build.

And that leads to an old trick from my PHP days. Caching the data of a function and returning it the next time we try to access it.

export let cachedThings: any[] | undefined = undefined;
export function doComplexThing() {
	if (cachedThings) return cachedThings;
	const things = [];
	// do the thing
	// cache it
	cachedThings = things;

	// return the data
	return data;

Now when we call doComplexThing() the first time, it runs the complex code. But then we hit it hundreds of more times and returns the cache.

There are many reasons to love the return of blogs. Folks taking the time to make a well-reasoned argument without truncating it to 140 characters is one of the biggest. And boy, William makes a great point here. Aside from the obvious spelling mistakes.

Front Matter CMS

With the relaunch of Finley, I am. a couple of weeks ago I shifted from using a CMS to everything-is-code. My blogging days stretch back to the mid-2000’s and my having built my own blogging tool called Blog Wizard. Various versions of that powered several blogs until I launched Finley, I am. in 2015 on Ghost.

Simply put, I am used to having a CMS. Code is great, but certain things are nicer with a CMS. Managing data things, specifically. The week with the relaunch I had imported all the articles from Ghost 1-to-1. Same tags and everything else. Last Sunday I started refactoring the tags. Because everything-is-code and I realized that I could build something cool if my tags were better. As detailed in the linked article, I merged and deleted a ton of tags. Over 300 tags in over 400 posts.

That brings us to Front Matter CMS. First, it’s a plugin for VS Code. Many CMSs exist for SSGs like Astro that write code. This sits alongside your Markdown post, living in the sidebar of Code. For SEO-minded folks, it provides SEO status info— like title, slug, article length, keyword management, etc. For me, it’s the publishing date, draft status, and very much the tag management for articles I love. Autocomplete on tags will help you remain consistent on your tag use, which I then use for finding similar posts.

And it helps you manage. The Dashboard shows all published posts and easily helps you find and edit your drafts. Taxonomies? Yeah, merging, renaming, deleting, and more. And remember, everything-is-code, so changing merging “video” into “videos” results in 10 changed files that you then commit and push.

If you use Hugo, Jekyll, Astro, or other SSGs that use front matter for metadata around posts, go grab Front Matter CMS and give it a shot.

Nothing too big, but I tweaked the “Other Posts You May Enjoy” section to sort by number of matches, not just date. Before it found all posts with one or more of the current post’s tags, but didn’t change the default order of reverse chronological. Now it sorts by number of similar tags, then date. So a post with 3 matches from last year will rank higher than a post with 2 from last week. Nothing ground breaking, but hopefully will help surface more relevant posts.

export async function getSimilarPosts (post: CollectionEntry<'posts'>): Promise<CollectionEntry<'posts'>[]> {
	const excludedTags = ['notes', 'links', 'featured', 'videos', 'quotes']
	const similarTags = => !excludedTags.includes(tag))

	return (
		(await getPosts(filteredPost => (
			filteredPost.slug !== post.slug && => similarTags.includes(tag)).length > 0
		))).map(post => ({,
			similarTagCount: => similarTags.includes(tag)).length
		})).sort((a, b) => {
			if (a.similarTagCount > b.similarTagCount) return -1
			if (b.similarTagCount > a.similarTagCount) return 1

			if ( > return -1
			if ( < return 1

			return 0

Amazing to see the React crowd come around to realize that SSRs and Island Architecture leads to faster applications and better UX. Y’all just reinvented PHP with a bit of jQuery sprinkled in.

That’s fine, but while you are recognizing this, please stop using terms like monolith and calling React “modern” while also calling PHP + progressive enhancement not.

I added a new type of post called reposts. In my Article component— used to render each article in multiple modes (eg. list, full, snippet)— I already include all tags as classes. I use this in lists to add the icons— look at the Ramblin’ section of the homepage.

<article data-mode={mode} data-draft={draft} class={`b--post ${ => `tag-${tag}`).join(' ')}`}>

So adding a new post type is just a tag. With the class tag-repost, I can now add the icon. But I also wanted to show the original post embedded. To do this, I added an optional string called originalPostSlug to my Content Collection. And this gets added to the Article component.

let originalPost: CollectionEntry<'posts'> | undefined = undefined
if (originalPostSlug) {
	originalPost = (await getCollection('posts')).find(post => post.slug === originalPostSlug)

Now I have the original article. So now we display it after the content.

<div class="b--post--content">
  <Content />
    originalPostSlug && originalPostSlug && (
      <div class="b--post--repost">
        <Article post={originalPost} mode="list" />

You can see it in action here.


So many good points here. The gist? React is not a framework. Next.js barely is. Rails, Laravel, and other far more mature frameworks provide you with the majority of what you need to build an application, leading to you writing less code.

But come on: we’re living in the 2020s and if you’re not at like 95% “framework does it for you” for things that aren’t business logic, then you’ve lashed yourself to a very bad mast ‒ you’re stuck building rote infrastructure instead of working on your app, likely creating a bunch of nasty attack surfaces along the way.

What to expect from your framework

I’m a roll-my-own kinda guy. In the itch the get this blog back in working order I considered both flat-file HTML and building a custom blogging app in PHP. Yeah, I’m a glutton at times. My point is I landed on Astro because I didn’t need a CMS and flat-file is just better for a site like this. Even though I have spent much of my career fighting the urge to reinvent wheels, I have largely used frameworks like CodeIgniter, Laravel, and Rails to get the job done better. Why? They handle the stuff that 1) I don’t want to handle and 2) I don’t know to handle.

React, well:

I would argue that React in itself gets you basically nowhere. It’s a templating language with benefits.

The hard part of an application— and I’ve built React applications for the better part of the last decade— is not the UI layer. HTML and CSS. It ain’t hard. No, the hard part is the business logic. The amount of reinventing routing in every app, reinventing connecting to APIs, the list goes on.

React itself is a templating language. It’s a good one. Half of what drew me to Astro— what powers this new blog— is the JSX syntax and components. But as Johan says, nearly every major framework has this now. Laravel, CraftCMS, Rails. This is standard. Plus they do everything else.

Once you start hitting the cursed parts of your application, the places full of dragons and cobwebs and sweary code comments, React won’t be there to hold your hand. It’ll shrug and say “add a Provider or something, idk.”

So why do we not just use these tried and true frameworks? They feel dated. Maybe many companies switched to mostly JavaScript engineers that don’t know anything other. Instead of hiring folks that can solve problems no matter the solution, they hired specialists. Same reason I warned years ago against hiring folks that listed jQuery on their résumé instead of JavaScript.

It might feel retro or oldtimey and maybe not as fun while you’re building, but your application will be better for it.

Now when you look at it like that, it makes you wonder why we give these people such a large stage while the very quiet majority don’t get a voice at all. The very quiet majority are out there building more than 90% of the web, after all.

Even a slight change in that dynamic would likely have a massive positive impact.

The (extremely) loud minority by Andy Bell

This is something bothering me a lot lately. There seems to be a sense that the majority are using JavaScript-heavy solutions for all the things, but the statistical truth is they are in the minority.

Even if you discount that: considering React has been around for a decade now, < 4% share of the top 10 million websites is pathetic, considering how much we are made to feel like it is the “biggest framework” (well, at least in bundle size, that’s true).