<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: x-t</title>
    <description>The latest articles on DEV Community by x-t (@xt).</description>
    <link>https://dev.to/xt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55724%2Fb55425c5-c970-490d-9b50-5160bb366dec.jpg</url>
      <title>DEV Community: x-t</title>
      <link>https://dev.to/xt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xt"/>
    <language>en</language>
    <item>
      <title>The Hitchhiker's Guide to over-engineering your site</title>
      <dc:creator>x-t</dc:creator>
      <pubDate>Tue, 08 Mar 2022 16:18:50 +0000</pubDate>
      <link>https://dev.to/xt/the-hitchhikers-guide-to-over-engineering-your-site-42ob</link>
      <guid>https://dev.to/xt/the-hitchhikers-guide-to-over-engineering-your-site-42ob</guid>
      <description>&lt;p&gt;Do you have a personal site? If you dabbled with computers in your lifetime, there's a really high chance that you do. Maybe it's not hosted, you've watched &lt;a href="https://www.youtube.com/watch?v=6Ct6emxVR9w&amp;amp;list=PL6291918FE7103470"&gt;a video on HTML&lt;/a&gt; when you were 10 and decided to make something of it, maybe it's a simple &lt;a href="https://neocities.org/"&gt;Neocities&lt;/a&gt; page, a &lt;a href="https://www.blogger.com/about/"&gt;Blogspot&lt;/a&gt; site or even a &lt;a href="https://pineapplevsbrowser.weebly.com/"&gt;Weebly&lt;/a&gt; cookie-cutter homepage. Whatever it is, it's a nice feeling to know that you have a corner of the internet that's yours.&lt;/p&gt;

&lt;p&gt;While nowadays hosting infrastructure for your site is hard and expensive, as each user requires more and more bandwidth, for 99.99% of us, this doesn't matter. Most of our personal sites are relatively obscure, with free hosting tiers covering all traffic, to accidentally create and host another Wordle with millions of active daily users isn't on our schedule.&lt;/p&gt;

&lt;p&gt;But infrastructure costs aside, there's another good cost that's associated with creating and maintaining a website - time for development. Sometimes we are limited in the amount of tools that we can use to make sites, for example, if all you have is Neocities, you're essentially left with plain old HTML, CSS and JS, all hand-written. While for small, simple sites this is more than enough, for larger projects, this is nowhere near ideal. Committing to hand-writing hundreds of lines of JS is going to end up in buggy and slow code, which is why nearly everyone, including small sites, have migrated to using libraries, as even the most basic ones (&lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;, &lt;a href="https://alpinejs.dev/"&gt;Alpine&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;, &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;) can increase productivity and decrease stupid bugs ten-fold. Or if you used &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt; before the days of &lt;a href="https://github.com/features/actions"&gt;CI/CD&lt;/a&gt;, you had plain HTML or &lt;a href="https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll#plugins"&gt;minimal Jekyll&lt;/a&gt; at your disposal.&lt;/p&gt;

&lt;p&gt;We live in a very, very different world now. A world where computing resources have become as cheap as water, and thus, you can join the dark side and totally over-blow your blog into a brilliant masterpiece of complexity. This guide will be based off my real website, &lt;a href="https://zxyz.gay/"&gt;zxyz.gay&lt;/a&gt; (&lt;a href="https://github.com/x-t/x-t.github.io"&gt;GitHub&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Always think big.
&lt;/h2&gt;

&lt;p&gt;What do you want your homepage to have? A bio? Some contact info? That's clearly not good enough. Try several services, several pages. A simple blog? Make it two. One JS framework? Make it three.&lt;/p&gt;

&lt;p&gt;Here's the layout of my site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontpage&lt;/li&gt;
&lt;li&gt;Guestbook&lt;/li&gt;
&lt;li&gt;OS Reviews&lt;/li&gt;
&lt;li&gt;URL Shortener&lt;/li&gt;
&lt;li&gt;Blog
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yOjWKbIJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/484da487f443dfeebd8fab5af3864c5c15932bb5-328x185.png" alt="Language layout of the zxyz.gay site - TypeScript 45.4%, HTML 29.6%, JavaScript 15.8%, CSS 5.8%, Nunjucks 2.6%, Shell 0.5%, Ruby 0.3%" width="328" height="185"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short this makes 3 backends, 2 frontend frameworks (3 if you count Jekyll) and 3 languages. Does anyone need this much stuff? Probably not, but, if we can add it, then, why not?&lt;/p&gt;

&lt;h2&gt;
  
  
  If it wasn't enterprise, it is now.
&lt;/h2&gt;

&lt;p&gt;The mindset of enterprise-level software is always the best to follow. For example, &lt;a href="https://sentry.io/"&gt;Sentry&lt;/a&gt; is a good service for crash reports, so - add it to every single file of your site. Even if there's barely anything in there that could fail, add it anyway, can't be too sure.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Yeah, I can see this being Google-scale"
&lt;/h2&gt;

&lt;p&gt;Nowadays, nearly all developer tools are open sourced and available for anyone with an internet connection, so, make use of them. Use &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; for everything, even your static site, because, why not? Hell, throw in some &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; in there too.&lt;/p&gt;

&lt;p&gt;Another trend you can take advantage of is making your site into a monorepo. You can use &lt;a href="https://nx.dev/"&gt;Nx&lt;/a&gt; or &lt;a href="https://turborepo.org/"&gt;Turborepo&lt;/a&gt;, both free, turn your semi-simple site into something straight out of Facebook's arsenal. Don't forget to not include any docs, no one else should be able to host it, only you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3dkph2li--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/74688d8982cafe6b0f0250c98572d41690e88b80-2048x2032.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3dkph2li--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/74688d8982cafe6b0f0250c98572d41690e88b80-2048x2032.jpg" alt="Flatbed truck carrying 4 small bricks." width="800" height="794"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is your ideal site configuration.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remember - your computing resources don't matter.
&lt;/h2&gt;

&lt;p&gt;As I said previously, computing resources are &lt;em&gt;cheap&lt;/em&gt;. A lot of it is free now, too. This means you can do whatever crazy stuff you want and you can totally get away with it.&lt;/p&gt;

&lt;p&gt;For hosting, any free static file service will do, many of them have quotas that are far beyond what you'll even care to reach, so, it doesn't matter that much.&lt;/p&gt;

&lt;p&gt;For backend, many free sites like &lt;a href="https://www.deta.sh/"&gt;Deta&lt;/a&gt;, &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt;, &lt;a href="https://northflank.com/"&gt;Northflank&lt;/a&gt;, &lt;a href="https://www.koyeb.com/"&gt;Koyeb&lt;/a&gt;, &lt;a href="https://glitch.com/"&gt;Glitch&lt;/a&gt;. Make as many services for your sites as you desire without even entering in your credit card.&lt;/p&gt;

&lt;p&gt;For source code, GitHub hosts anything and everything, a whole lot of it without any limits whatsoever. I have 40+ repos, one of them being 5 Minecraft worlds, with all the world files and even the server JARs included. It's essentially cloud storage, for free. Blow up your site with files, what's the worst that could happen?&lt;/p&gt;

&lt;p&gt;For building, CI/CD pipelines are really, really cheap and really, really fast. GitHub Actions has 2000 free minutes on private repositories and unlimited free minutes on public repositories. Create tens of pipelines, use several compilers, upload to a multitude of hosting services, it's all free.&lt;/p&gt;

&lt;p&gt;For coding, &lt;a href="https://gitpod.io/"&gt;GitPod&lt;/a&gt; has 50 free hours of private Visual Studio Code workspaces. This is not only convenient, as you get to install less stuff on your computer and the Google Cloud container will most certainly be faster than your machine, it will also allow you to code on your projects from your Chromebook or your iPad. But most importantly, you can have 10 services and run them all without blowing your fuse. Thus, you're free to over-engineer even more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real world example - stupid me.
&lt;/h2&gt;

&lt;p&gt;Now, I didn't really want to over-engineer my site. It just sort of happened, I wanted to learn several technologies and adding pages to my site was fun, so, it just ended up like this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontpage
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4oexjvQm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/940b2e8e2b80939355a2b95727786f502ea39ff9-2624x1686.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4oexjvQm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/940b2e8e2b80939355a2b95727786f502ea39ff9-2624x1686.png" alt="Frontpage of cmp.neocities.org" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The magnum opus, the self-made Carrd. Many years of iteration, ending up in a design that's questionable at best and a codebase with so many compromises you really couldn't count them all.&lt;/p&gt;

&lt;p&gt;Technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt; - build tool. Bundles all JS modules.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://vanilla-js.com/"&gt;Vanilla HTML&lt;/a&gt;, CSS - Simple enough&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://alpinejs.dev/"&gt;Alpine&lt;/a&gt; - Simplest framework I found, used for the guestbook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hosting providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Pages - main host&lt;/li&gt;
&lt;li&gt;Neocities - mirror&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Guestbook
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m_vKMdgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/ce284aea99108dad5a081cdfac48aea05c9dfe7c-1100x752.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m_vKMdgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/ce284aea99108dad5a081cdfac48aea05c9dfe7c-1100x752.png" alt="Screenshot of the guestbook from zxyz.gay" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read about the infrastructure and its history in detail in my &lt;a href="https://dev.to/xt/hosting-a-guestbook-how-hard-can-it-be-3pff"&gt;other blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/"&gt;Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hosting providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fly.io/"&gt;Fly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  URL Shortener
&lt;/h3&gt;

&lt;p&gt;I don't really use it for anything, it's more of a joke, so I tried to slim it down to the bare essentials with a hosting provided that would be willing to just work.&lt;/p&gt;

&lt;p&gt;Technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Express&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.deta.sh/docs/base/about/"&gt;Deta Base&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hosting providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deta&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  OS Reviews
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_DiPA6un--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/a51410b84e326fb0ed2f183bd0a00f4d34814ea8-1100x752.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_DiPA6un--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/a51410b84e326fb0ed2f183bd0a00f4d34814ea8-1100x752.png" alt="Screenshot of zxyz.gay/reviews" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's essentially a blog, but with its infrequent updates, and the fact that it was made before the blog, it ended up being a simpler Markdown-flavored site. With styling being primarily made with Tailwind, I got the final design in under a day, which is rather simple, yet pleasant.&lt;/p&gt;

&lt;p&gt;One of the downsides of Jekyll is the fact that it takes 4-10 minutes to build the entire site, generating hundreds of images scaled differently for mobile and desktop devices and many Ruby dependencies that take... a really, really long time to install.&lt;/p&gt;

&lt;p&gt;Since it's the same static site as the frontpage, I just build it and deploy it into a subdirectory of the site, which is then mirrored to Neocities.&lt;/p&gt;

&lt;p&gt;Technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hosting providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Pages&lt;/li&gt;
&lt;li&gt;Neocities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Blog
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NnnpurYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/ad3d2a0a67b614bd277a9a6e571b96d5c5bf157a-1100x752.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NnnpurYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/ad3d2a0a67b614bd277a9a6e571b96d5c5bf157a-1100x752.png" alt="Screenshot of blog.zxyz.gay" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The blog is pretty boring, the amount of boilerplate that Vercel and Sanity have done made it a really easy project to get started on. A headless CMS allows for quicker build times, skipping the image optimisation. With new features like &lt;a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration"&gt;on-demand incremental static generation&lt;/a&gt; in Next, it also means that updating or creating a post can be done in seconds rather than minutes, unlike the Jekyll setup.&lt;/p&gt;

&lt;p&gt;But ultimately this does leave you with two billing accounts to worry about - the usage quotas for Vercel and Sanity. While their free tiers are generous, you might want to think twice about the amount of vendor lock-in you're signing up on if you plan your blog to have thousands of viewers. Which, for this tutorial anyway, is rather perfect.&lt;/p&gt;

&lt;p&gt;Technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/"&gt;Next&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sanity.io/"&gt;Sanity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TailwindCSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hosting providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;Sanity&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  And now - you're a master-class over-engineer.
&lt;/h2&gt;

&lt;p&gt;Remember, being a 10X engineer doesn't mean that your 10X will be towards good quality engineering, but rather totally incoherent, unreadable code that 20 people will later have to try and maintain.&lt;/p&gt;

&lt;p&gt;Take these tips as do or do not do's, on one hand I can see that this is a total mess and I should probably spend some time trying to simplify it. But on another hand, it's rather fun to learn to use that many tools in the real world. I'm not trying to make a new unicorn, I just wanna learn.&lt;/p&gt;

&lt;p&gt;So go make something, chances are - it won't be good, but, it doesn't matter. Start up &lt;a href="https://en.wikipedia.org/wiki/Microsoft_FrontPage"&gt;Microsoft FrontPage&lt;/a&gt; and make your own next site. It's only one $300 monthly AWS bill away!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hosting a guestbook, how hard can it be?</title>
      <dc:creator>x-t</dc:creator>
      <pubDate>Fri, 11 Feb 2022 14:19:33 +0000</pubDate>
      <link>https://dev.to/xt/hosting-a-guestbook-how-hard-can-it-be-3pff</link>
      <guid>https://dev.to/xt/hosting-a-guestbook-how-hard-can-it-be-3pff</guid>
      <description>&lt;p&gt;Ah, the good old internet. &lt;a href="https://en.wikipedia.org/wiki/Yahoo!_GeoCities"&gt;Geocities&lt;/a&gt;, GIFs, &lt;a href="https://thewikion.neocities.org/wiki/banners.html"&gt;banners&lt;/a&gt;, view counters and one of my favorite things - guestbooks. Things that undeniably, died out. And no real wonder, the barrier to overcome for web development has gotten higher, the amount of people on the web increased by several orders of magnitude, many introduced in the late 2000s with touchscreen devices that couldn't be used for any kind of development. Social media took the place to provide a polished, easy experience for anyone's internet presence, without having to worry about code, hosting, scaling, design, accessibility or anything else.&lt;/p&gt;

&lt;p&gt;The design of social media doesn't allow these old tropes to exist. Geocities was made for the older internet, failing to scale to the new one for billions more users. GIFs couldn't be plastered anywhere anymore, as they looked terrible, companies got good at design and not triggering epileptic seizures from anyone daring enough to double-click the Internet Explorer icon. View counters don't make sense anymore, while analytics for pages exist, it is unquestionably inflated by the fact that clicking a profile is easier than finding a page. And guestbooks, well, have been replaced with just posts. Twitter, Facebook, Reddit and everything else is structured into posts and replies. A guestbook in a Twitter profile would really just be a simple reply.&lt;/p&gt;

&lt;p&gt;But the beautiful thing about being a web developer is you can make whatever you want. And while guestbooks nowadays are more popular in just &lt;a href="https://fauna-nextjs-guestbook-eight.vercel.app/"&gt;coding demos&lt;/a&gt;, there are groups of people that specifically want to bring back the &lt;a href="https://neocities.org/"&gt;old web&lt;/a&gt;. And you could say, I'm in one of them. &lt;a href="https://zxyz.gay/guestbook.html"&gt;I made a guestbook afterall&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's actually pretty simple
&lt;/h2&gt;

&lt;p&gt;A guestbook is a really primitive form of user interactivity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NjeeTW8J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/99ba8548df5431c12e886541caa3eb5ea22c627a-802x382.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NjeeTW8J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/99ba8548df5431c12e886541caa3eb5ea22c627a-802x382.jpg" alt="Graph: A form that allows anyone to post in your database ↔️ Database with all your posts" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's definitely simpler than a comment section, it's just some logic and a database. And for the old web, as well as my old website, it worked pretty well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UK5Fu_hR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/d2ec11da2d94b00cbb82e5f7a950408d6828f967-2656x1566.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UK5Fu_hR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/d2ec11da2d94b00cbb82e5f7a950408d6828f967-2656x1566.png" alt="A screenshot of the 2018 guestbook." width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the first generation of the guestbook from 2018. The amazing front-end design aside, the structure was rather simple.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hzq6jJ7o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/98768cb2b82f4e52d27fea540985ecf5969f2069-1322x852.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hzq6jJ7o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/98768cb2b82f4e52d27fea540985ecf5969f2069-1322x852.jpg" alt="Graph: DigitalOcean (at the top), MySQL ↔️ PHP" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what nowadays we'd call server-side rendering. A single DigitalOcean VPS, running Debian with a MySQL process and a PHP-FPM server running on Nginx. The &lt;a href="https://github.com/x-t/ok-guestbook"&gt;source code&lt;/a&gt; is as simple as the infrastructure. (Source code uses JSON files instead of a MySQL database, the actual code used on the server was in private git repositories and lost to time.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;comments);
foreach ($arr_cmts as $comment) {
    echo "[" . $comment-&amp;gt;time . "] " . htmlspecialchars($comment-&amp;gt;name) . ": " . htmlspecialchars($comment-&amp;gt;data) . "\n";
}
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fact that it was a full server meant that I had quite little to worry about the usage of the database and PHP. Things like compute and bandwidth costs wouldn't need to be accounted for, it's just a flat $5/mo for the virtual machine and some usage quota, that's it.&lt;/p&gt;

&lt;p&gt;As there was barely any traffic, the server was also used for a multitude of other things, like a &lt;a href="https://ioquake3.org/"&gt;Quake 3&lt;/a&gt; server, my friend's website, an analytics engine that tracked essentially nothing but search engine bots, it was quite a lot to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  When money strikes
&lt;/h2&gt;

&lt;p&gt;But all good things must come to an end, and this &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt; VPS was one of those. I had a $50 credit from the &lt;a href="https://education.github.com/pack"&gt;GitHub Student Developer Pack&lt;/a&gt;, which ended in less than a year. And I wasn't gonna start paying that much for a server that wasn't actually used a whole lot for anything else than learning, so for the lack of any users for the site, I nuked it. Moved the site to GitHub Pages. For more about the actual move, you can read the blog post from 2018.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jamstack
&lt;/h2&gt;

&lt;p&gt;Nowadays it's easier to get a back-end site host for free. &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt; has many Javascript server-side frameworks supported, all with the help of &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS Lambda&lt;/a&gt;. And if you're still thinking of learning LAMP, the shady market of things like &lt;a href="https://infinityfree.net/"&gt;Infinityfree&lt;/a&gt; will get you a full LAMP stack for free, with some limits.&lt;/p&gt;

&lt;p&gt;However, a few years back, I decided to go with &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;, as the backend offerings I wasn't that interested in and I could get a free github.io subdomain, plus it would be hosted straight from a GitHub repo, without the need of a website like &lt;a href="https://neocities.org/"&gt;Neocities&lt;/a&gt;. This meant that I embarked on the &lt;a href="https://jamstack.org/"&gt;Jamstack&lt;/a&gt; journey, even if I didn't know what it meant back then. And while Jamstack has many advantages, such as speed, any server content becomes exponentially more difficult. Thus the guestbook was abandoned for quite a couple of years before trying again.&lt;/p&gt;

&lt;h2&gt;
  
  
  A redesign that prompted new ideas
&lt;/h2&gt;

&lt;p&gt;In 2021, I totally redesigned my site from the ground up using the styling of the very old internet, aided with &lt;a href="https://en.wikipedia.org/wiki/Claris_Home_Page"&gt;Claris Home Page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RaEyMQL5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/ec61c86d33dedc2b6ace62d07e9b03a91f230eed-2656x1566.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RaEyMQL5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/ec61c86d33dedc2b6ace62d07e9b03a91f230eed-2656x1566.png" alt="The homepage of the Claris Home Page-designed website." width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This meant that I could redo with the old internet tropes. Serif fonts, banners, GIFs, bad HTML and something that I knew I'd be able to do now - a guestbook.&lt;/p&gt;

&lt;p&gt;Of course, I would not move the site out of GitHub Pages, which meant that I was stuck on Jamstack and couldn't just plop it back in with the same PHP code, so, ideas had to be made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Welcome to Azure
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IuTshh4N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/e812571fb27262db2ee4ca2bd1c0a2cb804b50d0-752x232.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IuTshh4N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/e812571fb27262db2ee4ca2bd1c0a2cb804b50d0-752x232.jpg" alt="Graph: Azure Cosmos DB ↔️ Azure Functions ↔️ GitHub Pages" width="752" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The way the Jamstack infrastructure works is it consists of 3 layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The database, to hold all guestbook posts&lt;/li&gt;
&lt;li&gt;The API layer, to allow safe insertions/retrievals of guestbook data&lt;/li&gt;
&lt;li&gt;The frontend, to render all the guestbook data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The database was held up by &lt;a href="https://azure.microsoft.com/en-us/services/cosmos-db/"&gt;Azure Cosmos DB&lt;/a&gt;, a free &lt;a href="https://www.mongodb.com/"&gt;MongoDB&lt;/a&gt;/SQL-compatible database, I used MongoDB for it, which worked pretty well. However, it was really slow, unsure why.&lt;/p&gt;

&lt;p&gt;The API layer was a Go serverless application written primarily by me, running on the &lt;a href="https://azure.microsoft.com/en-us/services/functions/"&gt;Azure Functions&lt;/a&gt; serverless runtime on Windows.&lt;/p&gt;

&lt;p&gt;For the front-end, a new HTML file was created, which would download the JSON from the API and display all posts, with some clever local caching strategy to cut down on the amount of API requests sent by every visitor. Also, since it's Jamstack, it used a client-side form, since there was no real backend server to just hand off the form to.&lt;/p&gt;

&lt;h3&gt;
  
  
  It was slow
&lt;/h3&gt;

&lt;p&gt;A fetch would be fast if it took 7 seconds, more often than not it'd be a cold start which would take anywhere from 12 to 30 seconds to actually see the content. It was completely free, so I didn't complain that much.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Cloud - old friends return
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wpvD_Hol--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/09a194c2e1a261ad57e74035ec32cda2b98f6b01-462x642.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wpvD_Hol--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/09a194c2e1a261ad57e74035ec32cda2b98f6b01-462x642.jpg" alt="Graph: (Group: Google Cloud Compute Engine, Go (golang), PostgreSQL) ↔️GitHub Pages" width="462" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided to take out the &lt;a href="https://cloud.google.com/free"&gt;free trial of Google Cloud&lt;/a&gt;, and instead of doing something useful with its' offerings, I just spun up a Compute Engine VM with RHEL. While the guestbook Go code was made to work on serverless and MongoDB, I migrated it over to Postgres and ran it as a systemd socket. The frontend stayed on GitHub Pages, so while the backend structure almost looked similar to the one before, it wasn't the same. Still, this showed me how it'd be great to not have vendor lock-in for your projects.&lt;/p&gt;

&lt;p&gt;The fact that it was written in Go and not in JavaScript with a weird Azure library meant that I was able to just run the same code without a rewrite. In fact, if I had hosted a MongoDB database instead of Postgres, it'd be a drop-in replacement.&lt;/p&gt;

&lt;p&gt;But the credits, just like on DigitalOcean, would end, and I'd return back to the Azure solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free tiers galore
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kcXLoSin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/c668514fa276e27dd4fdaeb4f28eb9560e4efc49-562x422.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kcXLoSin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/c668514fa276e27dd4fdaeb4f28eb9560e4efc49-562x422.jpg" alt="Graph: GitHub Pages ↔️ (Fly.io ➡️ Supabase)" width="562" height="422"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d_c4C0bX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/94f25e70f5708f3a2866207d6b98d71afad91c1e-562x472.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_c4C0bX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/94f25e70f5708f3a2866207d6b98d71afad91c1e-562x472.jpg" alt="Graph: GitHub Pages ↔️ (Fly.io ➡️ Nhost)" width="562" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The beautiful thing about startups is the venture capital investments. This means less money they need to stay afloat from the users, which ends in some truly spectacular free tiers. I ended up splitting the infrastructure in two, one way for fetching and another for making posts.&lt;/p&gt;

&lt;p&gt;For the fetching, I first used &lt;a href="https://supabase.com/"&gt;Supabase&lt;/a&gt;, which is a &lt;a href="https://firebase.google.com/"&gt;Firebase&lt;/a&gt; alternative, but then I ended up with the problem that 7 days of inactivity would just freeze the database, so I migrated to &lt;a href="https://nhost.io/"&gt;Nhost&lt;/a&gt;, which provides a free Postgres database backed by &lt;a href="https://hasura.io/"&gt;Hasura&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the posting, I needed some custom logic, such as an &lt;a href="https://www.hcaptcha.com/"&gt;hCaptcha&lt;/a&gt; checker, so that was replaced with a client-side form and a &lt;a href="https://fly.io/"&gt;Fly&lt;/a&gt; container.&lt;/p&gt;

&lt;p&gt;This sped things up significantly. Not as fast as the GCP solution, but still significantly faster. At this point I also migrated from the Go project to a Typescript/Express stack inside a monorepo, which would be much easier to maintain than the aging Go code.&lt;/p&gt;

&lt;h2&gt;
  
  
  But, startups aren't perfect
&lt;/h2&gt;

&lt;p&gt;Nhost, while working perfectly fine, had a major flaw when I was migrating the site from a really awful vanilla JS frontend to the &lt;a href="https://alpinejs.dev/"&gt;Alpine&lt;/a&gt; framework. The uptime.&lt;/p&gt;

&lt;p&gt;I'm unsure if they were just freezing the containers like a serverless cold start or the servers just keep going down, several times I wouldn't be able to fetch any messages. Sometimes it'd return with a "Service temporarily down", other times it'd just hold the HTTP connection and provide the guestbook JSON 5 minutes later. Considering I don't monitor the uptime, and it was happening constantly while I was just developing the site, I just took a random guess that when I'm not developing on it, the database would be down just as much, so I decided to migrate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good timing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mylKC2PA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/58070732a936f918ac66ceee01a1d24aa99e1d08-482x232.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mylKC2PA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.sanity.io/images/sve18r2v/production/58070732a936f918ac66ceee01a1d24aa99e1d08-482x232.jpg" alt="Graph: Fly.io ↔️ GitHub Pages" width="482" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just as I was trying to find suitable alternatives to host the guestbook on, Fly announced that they'd be making 3 GB of volume data free, thus meaning that running a PostgreSQL database for free was now possible.&lt;/p&gt;

&lt;p&gt;Both the database and the backend API now run on Fly, both cost $0, are always-on, have significantly better uptime than Nhost and are crazy fast. With a simple hack like:&lt;/p&gt;

&lt;p&gt;allows the frontend to fetch the guestbook as it is loading the Javascript to render it at the same time. It's faster than anything before, and even when all of the above solutions cost $0, this one might be the cheapest as you get the most.&lt;/p&gt;

&lt;p&gt;While it is lacking in resources (128MB RAM, 1GB disk), you get 100GB+ of free bandwidth, a full unrestricted VM (not just an user) with Postgres, so while it is a little more effort to administrate, it's actually more powerful than Nhost or even Supabase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;However simple a guestbook is in schema, in the modern age of the web it is actually quite some effort to host. And mind you, I am not even doing things properly. It's just two VMs in Europe - one with the Express server, another with Postgres. There's no high-availability, no edge, nothing fancy. These things cost money, and I want the guestbook to stay free. And through many design iterations, I found Fly to have the best solution for hosting a Jamstack guestbook in terms of free allowance, speed and control.&lt;/p&gt;

&lt;p&gt;A simple Twitter profile looks like a way simpler investment now, doesn't it?&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
