Background
I first launched my website in 2018 and used this free Bootstrap CV theme to quickly setup my profile before i applied for jobs after completing university. I was content after publishing my first iteration but over time grew tired of the design and longed for adding other cool features like a blog , newsletter and a custom backend CMS. Once i got a full time job I found the task too difficult and time consuming to do. I didn't want to get a Wordpress theme and get it up and running quickly. I wanted to build it from scratch while using a Modern tech stack to learn improve my frontend development knowledge. It was time for change and i started building it on January 2021.
Inspiration
I got the inspiration for my site after looking at Brian Lovin's 2020 personal site that is currently open source. You can check it out here. Here is a snapshot of how it looks.
New Stack
My new site is currently built using Next.JS and TailwindCSS for the Frontend. I loved the developer experience of styling web interfaces using Tailwind and the Next.JS being the best React framework to build a Server side rendered apps together with Vercel that provides a neat platform to host your apps and makes CI/CD,Deployment easier for developers . I definitely recommend checking out these frameworks if your are interested in React and CSS.
The Backend is built using Strapi, a really good Headless CMS. There are many Headless CMS that are currently available and I spent quite a lot of time/energy testing them all. However I ended up choosing Strapi since it had a neat interface , was open-source so i could host it on my server and the backend was built in React so adding custom plugins to the interface was easy and Strapi provided good documentation on how to integrate them.
Using Next.JS
I currently love Next.JS as my go to Javascript framework for building fast React web applications. Thanks to it having Automatic Static Optimization you can build both statically generated and server rendered pages. I built the site with a decent local environment setup using Prettier,ESLint for linting while writing with Typescript helped in type checking.
Hosting on Vercel
Vercel is a cloud platform that allows developers to host websites and web services that deploy instantly, and require no supervision and configuration. Some of the main pros include fast refresh, flexible data caching and easy integration with your repos at Github, Gitlab and Bitbucket. It was cool that that Vercel was the company that built the Next.JS framework so they were a first choice for the same. Luckily it has a flexible free plan for hosting static websites and single page applications. I was able to deploy my website to Vercel and setup my domain to the site.
Using TailwindCSS
I've been a huge fan of Tailwind ever since it came out in 2019. By default , it makes the developer think in components as you can easily separate a site's elements that reduces cognitive load during styling and is faster than writing CSS or CSS-in-JS. I especially like the inclusion of styling a Dark Theme of which you can enable by default or use the system default setting. Using next-themes provided an easier abstraction to achieve Dark Mode without flashing while changing themes.
SEO
Every blog post is automatically populated with meta tags using next-seo . This includes title, description ,meta tags ,twitter metadata.
RSS Feed Generation
An RSS feed is auto-generated from your blog post feed. I use RSS to keep up with a few tech blogs, web comics and use 1Feed to sync all the apps i have. So i thought it was a good idea to build one for my site. This is generated through manually after fetching all the posts like below.
// Generate One Item const generateRssItem = (post: Post): string => ` <item> <guid>https://davidamunga.com/blog/${post.slug}</guid> <title>${post.title}</title> <link>https://davidamunga.com/blog/${post.slug}</link> <description>${post.excerpt}</description> <pubDate>${new Date(post.published_at).toUTCString()}</pubDate> </item> ` //Generate Entire Feed export const generateRss = (posts: Post[]): string => ` <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>Blog - David Amunga</title> <link>https://davidamunga.com/blog</link> <description>Thoughts about Development,Design and Products</description> <language>en</language> <lastBuildDate>${new Date(posts[0].updated_at).toUTCString()}</lastBuildDate> <atom:link href="https://davidamunga.com/rss.xml" rel="self" type="application/rss+xml"/> ${posts.map(generateRssItem).join('')} </channel> </rss>`
The rss feed is generated at build time using the getStaticProps function and is saved using the
fs
module to a root rss.xml file in the public folder. Its also fetched again after 6 hours.// Generate RSS export const getStaticProps: GetStaticProps = async () => { const postResponse = await axios.get(`${process.env.NEXT_PUBLIC_BASE_URL}blogs`) const posts = postResponse.data const rss = generateRss(posts) fs.writeFileSync('./public/rss.xml', rss) return { props: { posts }, revalidate: 6 * 60 * 60 } }
Future Plans
As i'm happy how the new design turned out. I hope to make some future additions. I intend to make a richer content view for the blog posts incorporating more embeds from different Media. It would also be great to have some neat micro-interactions/transition animations while sticking to its plain theme. Furthermore, i wish to have it working with Apollo GraphQL with Caching to boost performance on the site.