Photo credit: Thought Catalog
It's been an interesting few evenings to rebuild www.mikenikles.com:
Let's first talk about v1.0
The previous version was a proof of concept. I wanted to run
Ghost.org on Cloud Run (https://cloud.run), with Sapper
as a static site generator for the frontend, so that the Ghost database did not have to be accessed at runtime.
The architecture looked like this:
What were the challenges?
Publication process
To publish a new blog post, I had to:
- Start the Cloud SQL databaes used by Ghost.
- It's worth noting I have could left that turned on, but the point was not to have a database at runtime ;-)
- Log in to the Ghost instance.
- Write the post and upload assets.
- Asking for reviews was tricky. I would have to give reviewers access to Ghost and they would see the blog post displayed in Ghost, not the way it will look once deployed.
- Publish the post.
- Wait for the static website to be generated and deployed to Firebase Hosting.
- Shut down the Cloud SQL instance.
As I mentioned well before I developed v1.0, this was over-engineered and overly complex.
Operating costs
The operating costs were about CAD $40 per month:
Throughout the first half of 2020, the blog had ~2,000 unique visitors per month with ~5,200 page views.
I wanted to find a more cost effective way to provide my content to others.
Google Analytics
I used Google Analytics and Firebase Performance tracking. While the insights are interesting, I rarely looked at more than number of visitors, the country they are from and which blog posts they read. The various scripts I needed to get this to work also came at a performance cost I want to avoid in v2.0.
The goals for v2.0
Before starting the project, I defined the following goals:
- Open
- Best practices
- Automation
- Low operating costs
Open
I want all aspects of my website to be open. The source code
including project management, pull requests, issues, etc.
Each blog post will be released as a pull request. Anyone can access drafts and provide feedback. This also gives me the flexibility to potentially allow for community contributions such as translations etc.
In addition, I will make the website's analytics available publicly as part of a project later in 2020. Stay tuned for that by following me on Twitter @mikenikles.
Best practices
As it has always been the case, my personal website is a place for me to experiment with new technologies.
If I get asked "How would you ...?" in relation to web development, I want my answer to be "Have a look at
www.mikenikles.com".
A perfect Lighthouse score, fully accessible, top SEO ratings, works without JavaScript, etc.
Automation
For anyone who's worked with me they know that automation is near and dear to me. "Don't document what you can automate!"
The focus is on using NPM scripts where necessary and connect it all via GitHub Actions.
Each PR provides a preview URL and once merged, a production deployment happens within seconds.
To create a new blog post and all necessary directories, I use npm run generate
and answer a few questions.
Operating costs
As close to $0 as possible and no database since it's all static content - simple.
What's new in v2.0?
Architecture
It's a lot simpler:
Diagram source: https://excalidraw.com/#json=5406435517136896,jY4N1Wo4Vgqn45E9uxUqPA
All we've got is:
-
Gitpod.io for my cloud-based development environment.
- Get 30% off your Gitpod subscription with my coupon code
mikenikles
.
- Get 30% off your Gitpod subscription with my coupon code
- GitHub for the blog posts, source code and workflow automation.
- Vercel for hosting.
The publication process now looks like this:
- Write the blog post and add assets.
-
git push
it to GitHub and open a pull request. - Share the draft URL with reviewers; iterate on the post.
- Merge the PR.
- Deployment to production then happens automatically.
Interactive blog posts written in mdsvex
This is arguably a bit of a nice-to-have. It is so nice though that I have to point it out!
I write this blog post in mdsvex
which is basically Markdown with Svelte mixed in wherever I want.
An example taken from https://svelte.dev/examples:
<Clock />
Note: The above clock only renders on my blog at https://www.mikenikles.com/blog/my-personal-website-v2-0.
In the blog post file, the following is what I write:
<script>
import Clock from "./clock.svelte";
</script>
...
Another example, taken from https://svelte.dev/examples:
<Clock />
I'm looking forward to taking advantage of that as I get back into more frequent blogging.
Draft preview URLs
Have a look at the recently closed blog post pull requests, open one and find the preview URLs to see how the post looked when it was in draft.
With the blog post's content available in the pull request, reviewers can comment on individual lines and I can pick up the conversation right there in the correct context. No more back & forth via emails or copy & paste from shared Google Docs.
What's next?
Personal website & blog
I track the v2+ project on GitHub. The focus is going to be on small enhancements and experiments as I see fit.
Book: Cloud Native Web Development
On June 28, 2020, I (will release) released my book Cloud Native Web Development.
It's two decades of web development experience packed into 200+ pages and 19 pull requests. It's a hands-on guidebook from zero to production and anything in between!
Use coupon code DEV
for a 25% discount!
👋