Rewritten
Since jasonloong.com v1.1, the website has been rewritten from scratch! (well, mostly)
I was satisfied with v1.1, but there were still workarounds that led to bigger issues when the site was in production.

The development process was not fully best-practised as well, with many untyped/any
API responses from Directus, slap-on get-it-working-first code, which months later turned into a nightmare to debug when certain quirks happened on my site. 🙈
After getting v1 up, there were many mini projects in between that I’ve written since, which strengthened my experience developing with Nuxt overall.
v1.1 Not fully SSR compatible
As my markdown content uses custom Vue components, it was difficult trying to get a complete SSR-rendered website while using MarkdownIt as my main parser/renderer.
The result, as described in the v1.1 post, was a workaround which rendered a custom HTML component and then rehydrated after the page had been loaded.
While SEO is not critical to this website, the implementation was half-baked.
Nuxt MDC
Everything worked with the Nuxt/MDC renderer (it should, as Nuxt/Content also uses it), but entry.js
's bundle size after building was a no-go. It is just too large for a normal non-interactive website for on-demand/runtime dynamic CMS content.
From my previous experience with MarkdownIt, with such a large bundle size, pretty much means at some point, the Markdown content will be client rendered. Even if it doesn't, having users load 500kb of JS files is not ideal, let alone more bandwidth for my photo-heavy website.

A dead-end till one comment made its way to one of the repo issues: With Nuxt Used It adds 30 thousand lines of code. #377
Ah, yes, let's try that. Bundle size issue gone. Reactive variables work. Async pulling additional data for my photos works as well.
Looking back, while the comment "made sense" to the experienced Nuxt users, it didn't occur to me at the time because I started with Vue development (SPA) and then transitioned to the Nuxt framework, mainly for the improved developer experience. SSR was an afterthought and eventually led to using/testing it as my website.
So the idea of having the "server route" do all the work, instead of just "pulling data", and trust that the hydration magic happens is not a mindset that I have while developing in Nuxt. My brain was wired to think in Vue's SFC style, so most logic should be in the component's markdownRenderer.vue
.
A renewed understanding, appreciation ❤️ of the flexibility, powers of server routes, Nitro and Nuxt.
The site now utilises Nuxt's MDC library to render dynamically pulled CMS Markdown content entirely server-side and hydrate it accordingly if the user navigates on the website.
UI/Layout

Migrated to use Nuxt UI, from DaisyUI
From Pinia to useState
Pinia, the go-to store for most users, I presume. Somehow, it didn’t work for me as expected during this rework. Some components refuse to get the state and are forced to go into client-side hydration, which breaks my layout. Might be the reason why things do not work out as expected most of the time, especially hydration mismatches.
Decided to use Nuxt’s provided useState
, which works as expected when Nuxt is in SSR mode.
If you are like me, having those few “go to” libraries on new projects like “Pinia” store to install, try using useState
if your SSR site is having issues hydrating.
CI/CD, Docker
Other than site development, I also implemented a CI/CD flow in my self-hosted GitLab instance, which helps to push the latest main
branch/image to my host.
v1.1 was built on my development machine, rsync
the new JS files over to my host, with a final SSH
into the host to restart PM2 manager. I tried building Nuxt on my fairly limited DigitalOcean droplet instance, but it would fail due to memory issues.
Now, my new CI/CD builds the website on one of my higher-spec virtual machines, sends it over to a self-hosted Harbour Docker image repository, and with the final deployment pipeline, pulls the latest image of the website. Discord notifications are set up so that I know it's ready to be visited and ensure everything works.
v2

The layout is now as initially imagined, and not compromised due to previous workaround issues.
While there's still some metadata that is not being handled/generated, as long as it is not an issue that will affect the site's intended rendering, SEO-related improvements can be dealt with later.
Hopefully, this will be the last time within the next few years before the site requires a significant rewrite.
- v2 - third time’s the charm right 🥹 (or did I jinx myself by setting up the new CI/CD flow 😂)
- v1.1 - jasonloong.com v1.1
- v1 - New website 2023