Published on

Over-engineering thvu.dev

6 minutes read - ––– views
Authors

Read on to learn how I bootstrapped this site from template starter to the current over-engineered state. I called it over-engineered because I think I over-killed the site by optimizing the Lighthouse score, CSP headers, and all the service integrations I squeeze in it 😅

Table of Contents

Get started

Template

I use @Tim's awesome starter template to bootstrap the project. The template is feature-rich, easy to customize, and easily the best starter for Next.js blogging out there.

Hosting

Hosted on Vercel, with domain from Google Domain.

Enhancements

Blogging

I enhance the current writing feature with mdx-embed. For me, it is always nice to have the ability to embed examples from CodePen. To have this I need to add CodePen to MDX components:

import { CodePen } from "mdx-embed";

const MDXComponents = {
  // ... other components
  CodePen,
};

And it is done! I also added a new feature, which is Real-time page view count using PlanetScale (More on this later in Guestbook section below)

Guestbook

This feature is inspired by Lee Robinson's guestbook and was fun to work with. I learned from him how to set up and use PlanetScale for serverless database (previously using redis with Upstash).

My tweak in the implementation is authentication for guest users. I used next-auth to integrate with Github, Google, and Line to provide authentication.

Authentication with next-auth

Install

yarn add next-auth

Configure providers

Create a [...nextauth].js file in pages/api/auth:

import NextAuth from "next-auth";

export default NextAuth({
  providers: [
    /* ...providers */
  ],
});

Be sure to check with the design guideline to implement the login buttons correctly. Details on how to integrate with each provider are also available on next-auth's documentation. Below is a summary for my providers:

ProvidersWhyDesign guideline
GoogleMost common login OAuth is a must haveGoogle
GithubFor developersGithub
LineMy current employer 😎Line

Custom Sign In page

To override the default /signin page, create a custom page and refer it in [...nextauth].js:

export default NextAuth({
  // ... other configs
  pages: {
    signIn: "/auth/signin",
  },
});

With Google Analytics

View a page

Check out the Next.js official example with-google-analytics. It covers almost everything you need to integrate GA into your Next.js app.

Get pageviews

I use this to display all views for my site.

I use this snippet to get pageviews. Notice that now Google is rolling out GAv4 that removed the View panel. Therefore, if you want the snippet to work, in your Google Console you need to create a Universal Analytic Property and use its ID:

  • From your Analytics Admin, click on Create Property
  • Enter the property name and click on Show advance options
  • Enable Create a Universal Analytics property. Check both Create both a Google Analytics 4 and a Universal Analytics property and Enable enhanced measurement for Google Analytics 4 property

SSG with DatoCMS

Instead of using the /data directory for projects data, I decided to integrate with DatoCMS for some Jamstack vibes. The process is quite simple:

  • Register a new account at DatoCMS
  • Add DatoCMS integration in Vercel
  • Fetch the GraphQL API in getStaticProps

I found everything I need in the Next.js cms-datocms example and DatoCMS documentation. Working with DatoCMS graphql is a nice experience, as I have never worked with graphql before.

Tips with environment variables: Make use of the Vercel CLI. After added an integration, you can use vercel env pull to get the ENV variables to your local .env file. I found this to be pretty handy when integrating services.

🎧 Now Playing with Spotify

Another feature stolen from Lee 😄. See his article to learn how to set things up with Spotify API.

The Music Equalizer component is my touch, which is also available on CodePen as a CSS-only version. The visual is taken from Instagram story's music equalizer.

 

The end result ✨

Lighthouse score

The generated site already has a very high Lighthouse score. I added PWA and perfected the bars. Lighthouse report is available here.

What I improved compared to the starter project:

  • PWA: Better icons, manifest
  • SEO: Added robots.txt

PWA

The easiest way to implement PWA support in a Next.js project is to use next-pwa.

favicons

I use https://realfavicongenerator.net to generate the icons.

manifest.json

To get the perfect score for PWA, ensure the following in icons:

Content Security Policy

Websites I use to get CSP rating:

If you are implementing CSP for your site, my suggestion is to start with super strict CSP (lockdown) and build from there.

Monitoring with Sentry

Sentry with Next.js is a delightful experience. The steps are:

  • Go to https://sentry.io to register for a free tier account.
  • Add Sentry integration to Vercel.
  • Install the package and run the wizard:
yarn add @sentry/nextjs
npx @sentry/wizard -i nextjs

I only want Sentry in production. To do this, in my next.config.js:

module.exports = isDevelopment
  ? nextConfig
  : withSentryConfig(nextConfig, SentryWebpackPluginOptions);

withSentryConfig has to be the farthest wrapper to ensure that your source maps include changes from all other Webpack plugins.

Conclusion

And there you have it, my over-engineered site, my sweet home on the internet. I learned a lot from other people while building this site. I hope you learned something from this post too. I will continue to upgrade this site in the future, hopefully with more original ideas. Stay tuned for future posts!

The source code of this site is available on Github.