Designing a Customizable, SEO-Optimized Personal Website With React + Next.JS
For the past couple of years, my personal website has been hosted on a Heroku free dyno. It was Node.JS with an Express backend and a EJS front-end. It worked well for the most part, but there were several downsides.
- After 30 minutes of no use, my dyno would go to sleep, leading to high load times since the server needed to restart
- Any content changes required redeploying the site
- An Express backend is overkill since its only purpose was to route users to each page
While none of these issues are earth-shattering, it was definitely a sub-optimal setup, particularly since slow loading time is a bad user-experience and results in poor SEO.
At first glance, these seem counter to each other. This is where React comes in.
React is an increasingly popular JS framework which makes it easy to build dynamic webpages that run entirely on the client. With React, I can host my data in an outside database and fetch it on the client-side after the user requests the page. Since all the logic is client-side, I can serve static files, eliminating my backend.
React was particularly appealing because of its component-based approach to development. There are an incredible number of components from the web ready to be imported. It’s also simple to create and style your own components. This makes development time significantly easier since I could import complicated components (like timelines) rather than spend time making them myself. It was also helpful in making sure my design was consistent across the site since all I had to do was reuse the same components.
There is, however, one huge downside to React: SEO.
Search Engines and SEO
SEO is incredibly important for a personal website because when somebody searches your name, you want your site to be the first one they see. The way search engines like Google determine which site to show the user is by indexing your site.
During indexing, Google’s bots download your webpage and crawl through the content. They look at the images, links, text, and metadata on the site in order to extract keywords and determine what type of site it is. They use this predict what kinds of queries the site will be relevant to. Site responsiveness (this is where my initial Heroku site was lacking), keywords, in-going and outgoing links are all important parts of the indexing process.
Next.JS has a solution for this: incremental static regeneration
Static Rendering, SSR, and Incremental Static Regeneration
There are two traditional ways of serving websites: static rendering and server-side rendering (SSR).
Static rendering is when all HTML is generated before the site is deployed. This is what happens when you upload an HTML file to a hosting site or use a framework like Jekyll.
SSR is what my old website on Heroku did. The client would make a request to the server. The server would parse the request, construct the HTML, and return it to the user. Each request regenerated the HTML (disregarding caching).
Incremental Static Regeneration is a mix between the two of these. It’s inspired by the stale-while-revalidate (SWR) caching mechanism. With SWR, a server caches the HTML to send to the client. When the client requests the content, the cached content is delivered. Once the cache reaches its expiry limit and a new request comes in, the server rebuilds the site, still serving the dirty site until the rebuild is complete. When the rebuild finishes, the clean site is put into the cache and is ready to be served to users.
This results in zero-downtime and I can still generate static HTML with site content that automatically updates itself.
With React + Next.JS as my stack, the only thing left is hosting. Since Next.JS requires a server, static options like Github Pages or Firebase hosting won’t work. Heroku also wouldn’t work because of the downtime issue. As the creators of Next.js, Vercel was the obvious choice because they have built-in support and optimization for it.
On Vercel, you can host Next.JS sites entirely for free. On top of this you get SSL encryption, asset compression, cache invalidation, and CDNs to deliver all the static assets for the site. What this does is make the website scalable, fast, and always update-to-date.
The last piece of this stack is the Database. I’ve deliberately left this to the end because as the “backend” of my website, the frontend is entirely agnostic to where the data is stored so long as the format is the same. In other words, it makes no difference from a user-experience perspective, but it makes a huge difference from a maintenance and developer-experience perspective.
Rather than going for something flexible like Firebase, I decided to use Airtable. Airtable is a powerful spreadsheet alternative. With an intuitive GUI and simple API, it’s the perfect content-management system (CMS). Although its more limiting than Firebase, using Firebase would require either building a GUI or dealing with the Firebase GUI (which is not meant for manually editing the database).
Airtable makes it easy to quickly add and remove content from the site. Its API provides JSON for Next.JS to use while pre-rendering, meaning I could always migrate to a different database in the future. Another huge benefit is Airtable’s rich text field support which allows me to inject and render arbitrary markdown into designated locations and render it as pure HTML. In other words, it fit my requirements perfectly.
Clearly migrating from one type of website to another is a significant amount of work. So just to recap, what did I gain from all of this?
- Free hosting with zero down-time
- Automatic website updates (except for structural changes or new images)
- CDN delivery
- An easy-to-use CMS GUI
- SEO Optimization
- Asset compression, SSL, Scalability, etc
Overall, it was worth the effort. You can check out my site at anmolparande.com to see what the end result looks like. Thanks for reading!