The popular new way for hosting “static site” is using the JAMStack platform. I have used others in the past, but currently I have been using Cloudflare Pages for two years exclusively.
It is good, but it has its drawbacks.
Every new post / page that I push (via git) will trigger a new build. Sometimes the build fails.
I found it bizarre that even pure static hand-coded HTML still requires a build. And when a build fails, by default, I got no alert, so I was sometimes surprised when I happen to go to the website and saw that the morning's push did not show up.
Maybe there is a way to get an alert somewhere along the workflow.
Each build takes time.
It's gotten faster, but still time to spend waiting, since I need to check that the build succeeds.
The new way is not always better than the old way. Just a different set of trade offs.
The “old” way, which is still popularly used today, that I did was using an HTTP server (Caddy, Apache, NGINX, Lighttpd, etc) + static files.
To deploy, all we need to do is upload the static files to the server and the new content is instantly up. It is actually very convenient, but it has its drawbacks too.
Security is on us.
If we misconfigure the HTTP server or late in patching the OS, then that opens up risk. So we need to have the process to keep them always updated.
On a JAMStack platform-as-a-service / PaaS, we focus on our app's / website's security only. The rest is taken care of by the platform security experts.
Load balancing is on us.
It is up to us to set load balancing up front and this costs extra. Plus it requires additional skill.
And I think this is the allure of the new PaaS, someone will take care of the auto-scaling for us.
I am in the beginning stage of setting up a new project. For some reason, I was drawn to retry the old way of doing things and rented myself a server.
There are inconveniences. But it is not rocket science. And there is something in the familiarity of the process and the simplicity of it that made me think: this might be good for me in the long run.
Or maybe it was just nostalgia.
At the start of building my previous startup attempt, I made bleeding-edge decisions (at least bleeding-edge to me personally, since I “bled” in the process).
You probably are familiar with “tech debt” and “choose boring technology”, but this post is not about those. I am happy with the technical stack that I ended up shipping and this post is about the journey and the decision making process.
A common thread is this: I prioritised business goal over technical familiarity.
In 2011/2012 period, I tried building a startup on the side. Go language was pre-1.0, but I chose Go over the languages that I already knew at the time: Python and Ruby.
My business goal was to have a product that would not cost prohibitively to run with fast performance. Server cost back then was not as affordable as now, so Go ticked the boxes for me, although that meant I had to learn a new language. Fortunately, Go was really easy to pick up and be productive in.
Fast forward to end of 2021 / early 2022 – a different startup attempt. I wanted to use Go again and this time my business goal was to minimise operations and this led me to 'serverless'.
There were several options for serverless + Go and Google Cloud Functions gave me a fairly balanced trade-off. Initial trial worked well, but then I found out that the networking side of thing added operational friction to get going.
Another consideration was that for the functionality that I wanted to build on the client side, the product would have better interactivity if I used a lot of JS on the browser. And to build that, I had to upgrade my rudimentary JS skill.
So if I had to use a lot of JS anyway, I might as well switched to JS and Cloudflare. And with that, I focused backend development in JS for Cloudflare Workers and frontend development in JS + React for Cloudflare Pages.
When I had built sufficient functionality for a minimum viable product (MVP), I had my doubts about the sustainability of what I had built. Was it robust enough to meet my goal of minimising operations?
At about the same time, the React library that I depended on switched from JS to Typescript (TS) in its new version. My web app could still work with the old version, but that got me into investigating TS.
Interesting. How hard can it be to rewrite into TS? (*)
I rewrote the code that was relevant to the aforementioned library from JS to TS in roughly a week. Given that I was learning as I stumbled along, I was happy with the one week delay.
And then I sort of “saw the light at the end of the tunnel”: migrating my app from JS to TS would minimise potential operations issue for me.
The business trade off was clear, improving the robustness of the product can pay back for itself in the long run, despite the schedule change.
So I rewrote the MVP in TS while deprioritising the rest of the product backlog. Unexpected benefit was that I was more productive coding in TS than when I was in JS.
A bit later in the project and being more comfortable with TS, I could confidently refactored the codebase into microservice-like model.
Data was at Supabase. Documentation was a bit lacking in a handful of places, but their product served me really well.
Cloudflare had everything else I needed but I added AWS Cloudfront as my image CDN and Imagekit to serve video. I added Cloudfront because Supabase object storage was in AWS and it was simpler to set up than Cloudflare. I used Imagekit, because it was also easier to use than Cloudflare. I wrote about Imagekit here.
That's it for the most part. Happy building!
(*) Related but completely different context: How hard can it be?
The past 12 months have been an interesting period. I left corporate job, took a break, and pursued building a product.
I had several ideas that I was interested and eventually I settled on developing digital marketing platform for small businesses. The specific problem space already had a few deep pocketed players, so that serves as market opportunity validation. I just had to find a differentiated go-to-market strategy that works for me.
I built a rough prototype quickly, showed it to some people and gathered some feedbacks. Based on potential users feedbacks, I adjusted the product roadmap and started building. I put in crazy hours, more than when I was in corporate. Learning as I built, I juggled priorities and wish list and in about four months, I had a minimum viable product ready.
And yet something bugged me on the technical side; under the hood, the MVP (minimum viable product) was badly fragile. I know MVP is meant to be put together as soon as possible, but my goal was that viable = sustainable. I did not have outside investor and I had enough runway, so I decided to rewrite the platform. That was a tough decision, but in the end, I was super glad I did it.
Then I applied for Google login authorised app status and this took longer than I envisioned due to my shortsightedness. (The Google Cloud Trust and Security Team was very patient with me. Thank you folks!) Developing the marketing content and marketing video also took more time than I planned.
All done, I soft-launched. And boy was I surprised with the things that broke down when new users tried the platform, but I fixed them quickly and I had not had any problem again, so far.
The platform was running well. On technical side, it seems performant and sustainable.
Despite all that, I decided to shutdown the platform.
It is a long story, but to keep it short, let's say it is because I do not see “product-market fit” – at this time – with what I wanted to do. This conclusion is not ideal, but the personal journey has been rewarding.
Let me explain from the perspective of “Fail Fast, Fail Often” – as one of the authors, Ryan Babineaux outlined in 5 Tips to Succeed by Failing Fast.
I did all those.
And in the process, I learned a ton. And I had fun. I think I succeeded in “failing fast”, so it is a happy conclusion for me, at least for now.
All things considered, I am truly blessed to have had this opportunity. And now, on to the next thing.
Related: If you are into tech stack, I wrote about the stack that I used here.
The Great Bubble Barrier is a cool idea! Below video gives a brief overview of how it works and its benefits.
Visit their website to learn more: TheGreatBubbleBarrier.com.
It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better.
The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood; who strives valiantly; who errs, who comes short again and again, because there is no effort without error and shortcoming; but who does actually strive to do the deeds; who knows great enthusiasms, the great devotions; who spends himself in a worthy cause; who at the best knows in the end the triumph of high achievement, and who at the worst, if he fails, at least fails while daring greatly, so that his place shall never be with those cold and timid souls who neither know victory nor defeat.
~ Teddy Roosevelt, from the “Citizenship In A Republic” speech, April 23, 1910
Few months ago I was revamping my hand-coded website project and learned of a new framework called Astro. It was still in beta at the time, but it fits my needs well, so I decided to use it.
Since then, Tiny Rocket has gone through several iterations and has a few useful features to help Astro users get up and running with their website project.
Check it out and please star the GitHub repo to help more people discover it. Thanks.