Here’s practical experience from me running the tech side of a startup while sharing the author’s values.

Server-side rendering (the normal kind from 1990s):

1. It is glorious. Everything that 37signals has to say about it is true.

2. However. I really miss React-style components as an abstraction. There are many ways around it that we use depending on the case (plain CSS classes, our own tiny Go/HTML component library, HTML custom tags), but we’re yet to produce something as ergonomic for more complex compositions.

3. We’ve added Hotwired Turbo for smoother page updates. I find it’s a lot more orderly than htmx, but we do miss some things that htmx would offer.

CSS:

1. We started out with just plain CSS, using BEM and CUBE to structure it and manage complexity.

2. That still got us questioning the DIY nature of the U (utilities) part of CUBE — it got increasingly complex and random, and really just like every program grows a broken LISP interpreter inside, every custom CSS utilities library grows a broken copy of Tailwind inside. So we adopted the actual Tailwind for utilities. Tailwind is truly glorious, both for sheer productivity of writing the code, but also as a language for describing styling at just the right amount of detail — more powerful than CSS properties alone (hover:color-red-700, disabled:cursor-default), but more constrained than full CSS.

3. Tailwind introduces a build step, though, which sucks (and slows down the build by the whole second! My m2 Air can probably do a 60s supercomputer-level nuclear explosion simulation during that time.) Thankfully, part of our startup is doing custom themes for each client, for which actual Tailwind sucks even more (themes are edited at runtime, and you wouldn’t want to run actual Tailwind with its million Node dependencies on your server), so we’ve implemented a subset of Tailwind in Go, just the things we actually used, and it runs at runtime, eliminating any build steps for themes.

4. Bottom line: Tailwind is absolutely glorious as a shared design vocabulary. Non-tech people were able to adopt it and handle theming thanks to it. The actual implementation of Tailwind seems unacceptably slow, but I hear a Rust compiler is coming.

JavaScript:

1. Plain old JavaScript is great, but needs some structure. We found that structure in Hotwired Stimulus, which we absolutely love.

2. But again, I do feel the desire for React-style rendering occasionally. We embed our widgets on customers’ e-commerce sites, and a chunk of HTML rendered based purely on data coming from an API with live updates is a perfect case for React.

3. Needless to say, running code on other people’s e-commerce sites is where I would never dare use a React-based stack, because I’d spend the rest of my life doing due diligence on the dependencies. (Our competitors are much less responsible about this, and it works out for them too, so this is more of a principles thing.)

4. This is probably the case where an in-house 500-line implementation of React-style rendering would be preferable to anything else. We already have a 100-line version, but it lacks many desirable features.

Bottom line: Yes, you can (and should) run a modern startup based on a pragmatic server-side rendered stack, but you definitely want to add just a few modern things: something like Hotwired, something like Tailwind, some solution for more powerful components in your templates, and something like Preact for certain use cases.