New with Sveltekit, mdsvex, Tailwind, Cloudflare Pages

Picture of the author with a metal dragon sculpture in the desert

This week I built and released a new version of this website (you can find the source code for this project on Github).

While the old version of this site was built in Haskell with the Servant web framework and Elasticsearch as its data store, the current site is now deployed to Cloudflare as a set of static pages using Sveltekit

This change is not a commentary on the old stack the site was built with. I love Servant and the previous project was loads of fun to build and hack on over the years. I’d used and remained a fan of Elasticsearch for the last 7 years and for a simple database with amazing search functionality, Elasticsearch often makes a lot of sense. On my old site in particular, I was pretty happy with how I’d used servant-client to automatically generate a simple Elasticsearch client, which leveraged the automatic client generation that comes as a benefit of specifying an API as a Servant type.

Deploying that project, however, also meant that I needed to have a server to deploy it and an Elasticsearch server to connect, which ultimately meant keeping an Elasticsearch instance running for years. Now, obviously, running a stack like this for a website with fewer than 3 dozen static pieces of content is overkill. The only reason to do it would be for fun (and maybe some street cred?) and I must admit it was fun for a few years. There’s a corollary here though: when this work stops being fun, then we should do something different.


This summer I’d started playing with Sveltekit and eventually came to really like it. As my readers will no doubt be aware, the web frontend ecosystem is currently dominated by React, a fact which appears to cause much chagrin in the Svelte world. I was fully never won over by React (an admission that may alienate some of my readers…). Of course, the industry has bought into it hard, so I am clearly in the wrong here.

By way of a small explanation here, I always felt that the hardest part of frontend web development is state management and the earliest versions of React punted on this question. As a result, I saw not handling “the state problem” as the original sin of React. Moreover, the solutions which emerged over the years, such as Redux and then React hooks, were never compelling to me. In other words, I never looked at the organization and design of React apps and thought, “Yes! I want to write apps like this!”

As a result, I’d kind of resigned myself to never doing any frontend again, so I was honestly surprised to find Sveltekit compelling. State management in Svelte for a particular component is solid and easy to understand and there are also React-hook-like global state managment tools available as well (although I tend to think global state should be a last resort and the emphasis on it for a “functional” frontend framework like React always puzzled me). Moreover, Svelte’s routing by directory structure made a lot sense to me and in my view cleanly solves the routing problem, another core problem for a frontend application to solve upfront in my view.

Beyond routing and state-management, the design of Sveltekit with its heavy emphasis on server-side-rendering was outside of my comfort zone because I’m used to building a separate backend for an SPA-style frontend. My assumption relied on an obvious frontend/backend split born out of years working on these projects in a business setting: there is client-side (browser) and server-side, and mashing the client-side to be also sort of server-side confused me (and has faint echoes of Rails or Django for my ears). Thus, the server-side-rendered focus of Sveltekit took me a bit to get comfortable with and I had to try to distinguish where in my codebase was I doing “backend” things and where was I doing “frontend” things.

That latter distinction is important because “backend” is the domain of talking-to-databases and other activities that typically include secret information such as database passwords and API keys, etc. These are things I’d never want to leak out onto the frontend, so in part I’d grown used to the backend/frontend separation as a hard security boundary. Working with Sveltekit was uncomfortable for me in this way because that line was grayer than I’d been accustomed to.

Ultimately, in this project I found that this ambiguity was fine: there are no secrets in this project! Moreover, if needed, I could always call out to a separate backend using Sveltekit’s +page.server.js files.

Deploying to Cloudflare Pages

My goal with this rewrite had been to get away from managing servers, so ultimately what I needed was a static site where I could write markdown and have it automatically deployed to a host like Cloudflare or others. I didn’t want to use a static site generator, however, not because I have anything against those tools, but my personal project is an area for me to explore and challenge myself.

Here again Svelte had a great story: using a Cloudflare adapter I could build and deploy my site there in a single step. Further, to get a deployment to Cloudflare working automatically, I followed this guide and had this app deploying to Cloudflare Pages from commits to main in maybe five minutes!

I had actually expected to spend a couple hours building a deployment pipeline, but instead I just created an app inside Cloudflare, connected it to my Github repo, and clicked through a couple of screens of options. It was shocking how easy this was.

Admittedly, there are loads of ways to achieve the same goal so this isn’t meant as an advertisement for Sveltekit and Cloudflare. I wanted to build this site using Sveltekit and in this particular area, I was pleasantly surprised how easy it was to deploy it as a static set of pages on Cloudflare using the Cloudflare adapter with Sveltekit.

Tailwind Is Fine for a Non-expert

Finally, I decided to rely on tailwindcss and Flowbite-svelte to make something generic-looking with as little styling effort as possible.

It’s been more than 10 years since I gave up on being a competent CSS practitioner but even as a hack I can still sympathize with the experts who may have reservations about Tailwind and friends. However, these tools are invaluable for me to get something clean-looking as fast as possible: they’re as beneficial as CSS frameworks like Bootstrap were in the distant past.

Of course, I am not an expert CSS-author and I am also pretty aesthetically hobbled, so even if I could fluently craft stylesheets, I don’t think anyone would appreciate the styles I came up with! You can see that on this site as well: the design and presentation is “good enough” in my view (sorry ¯\_(ツ)_/¯ ).

This is all to say: I wanted to put in as little effort as possible on styling and Tailwind aided me incredibly this goal.


I think I spent maybe a day getting this app working on my local and then probably a day making sure it looked passably okay, and then five minutes deploying the thing. That’s pretty rad!

Now, I can write markdown files and commit them in here directly and I’m saving $12/mo on my last Digital Ocean droplet, which served me faithfully for many, many years but which it has finally come time to say goodbye to.

In total, this new app is built on the shoulders of a massive heap of dependencies, and I’m sure keeping them up to date in years to come may be some effort, but the work feels like a great direction and I’m pretty happy with the result. Also, you can’t beat the developer experience of deploying to main and having a robust Cloudflare-backed site updated 30 seconds afterward!

Tags: Sveltekit,Cloudflare,mdsvex,tailwindcss