I completed all the backlogs for this blog development about a month ago. Well, honestly the changes were more like gradual instead of abrupt. But at this point, I see it had undergone some serious changes that I think it's proper to label this as a big update. Let's see the improvements.

 

Quick update overview:

  • Registered a new domain name
  • Switched from Single Page Application (SPA) to Fullstack Static Site Generator (SSG)
  • Introduced subscription support via RSS feed
  • Implemented unread comment notifications
  • Integrated MathType for math and chemistry formulas in the editor
  • Added web traffic analytics powered by Cloudflare
  • Other improvements and bug fixes

 

Registered a new domain name

 

Now in addition to the old domain at stacked-stories.pages.dev (Stacked Stories) and stacked-control.pages.dev (Stacked Control), I registered a new domain so you can also access Stacked Stories at blog.gofhilman.my.id and Stacked Control at control.gofhilman.my.id.

 

There are several reasons I made this change. First, to prevent my blog from being flagged as an unsafe site when sharing Cloudflare Pages domain links on social platforms like LinkedIn. Second, to enhance search engine indexing on platforms such as Google and Bing. And I think it looks more professional when we rent a custom domain. I only spent USD 0.74 (IDR 13,000) per year to rent it. And that actually is the only price I need to pay for running this fullstack blog.

 

Switched from Single Page Application (SPA) to Fullstack Static Site Generator (SSG)

 

I think this is the most important update. Back then when using SPA, the blog loading time was super slow since I used a free plan server in a Platform as a Service so it would sleep (inactive) if it's not been used for several minutes. There was also a problem when bot crawlers tried to analyze the page because they need to execute the javascripts and wait for several seconds to get the content of the page. If they wait too long, they'll stop the process and fail to index it.

 

My solution to these problems is to switch the blog (the user front end) from SPA to fullstack SSG. Static Site Generator means the app will prerender all pages (routes) at the build time. To prerender the routes in React Router Framework Mode, we can modify react-router.config.ts, for example:

 

import type { Config } from "@react-router/dev/config";
import { getPublishedPosts } from "./app/api/postsApi";

export default {
  // Config options...
  // Server-side render by default, to enable SPA mode set this to `false`
  ssr: false,
  async prerender() {
    const { posts } = await getPublishedPosts();
    return ["/", "/rss.xml", ...posts.map((post: any) => `/${post.uri}`)];
  },
} satisfies Config;

 

The next thing we do is to adjust the routes to accomodate this prerender process, for example, by adding the normal route loader on top of clientLoader.

 

Not everything in this blog is prerendered, which is why I refer to it as a fullstack SSG. For an instance, the post filtering and pagination, the comment section, and the authentication are still processed by using the fetch method because we need a backend server to do that. The combination of using static pages directly served from a CDN for time-critical components and a backend server for the rest is what makes this blog unique.

 

Maybe there is a question,

 

So do we have to deploy the user frontend manually whenever we finished created a new post?

 

The answer is no. In Cloudflare Pages, we can use a deploy hook to trigger the API through a webhook request. In my case, I created a webhook for my Stacked Stories blog (the user front end) and connected it to the back end via Stacked Control (the admin front end). Whenever I want to rebuild the blog and prerender all routes, I simply click the “Deploy posts” button, as shown in the image below.

 

 "Deploy posts" button