Next.js 13 is a significant update, introducing the "app directory" with React server components. It packs very powerful features focused on performance and security, but was also relatively unstable for some time with a slight learning curve.
The update allows me to handle a lot of things server-side (image generation, fetching and prefetching data, localization), making things faster and more secure. Like in good old PHP days. 🐘
Certain aspects of the sollution still leaves me somewhat frustrated (the lack of in-built internalization sollution, for instance), but ultimately I'm happy for the switch.
A point of frustration with Next.js 13. The previous versions had an in-built solution for providing multiple language versions of your site - it worked out of the box and very well.
Next.js 13, however, listed i18n as a "not planned feature". This prompted the community to find its own sollutions, leading to further instability and breaking updates.
After some months the team finally shared a guide on how you can implement i18n on your own. Unfortunately I still find it quite incomplete.
Here's the list of things I miss from the guide:
Majority of Next.js sollutions (including the official ones) expects a "root layout" directly under the app folder that includes at least the <html />
. The i18n sollution by Next.js prevents that.
✅ My solution: Keep root layout and provide the locale parametr through custom header.
One of the solutions requiring the root layout. No custom 404 page for you with the provided guide. This includes localization itself - user of any language will see the error message only in english, not in the language of their choice. 🤷
✅ My solution: Use root layout with custom header as described above.
The provided solution makes the homepage (https://www.cibulka.codes) just a contentless redirect to the subpath with the suitable (negotiated) locale for the user (https://www.cibulka.codes/en).
I'm still trying to figure out how hurtful is this for SEO. Currently I believe that it somewhat is (according to my reports in Google Search Console) and it can be fixed only with additional configuration:
<head />
: <link rel="alternate" hreflang={YOUR_LANG} href={YOUR_LANG_URL} />
At least one, probably 2 redirects are happening on the first load.
cibulka.codes > www.cibulka.codes > www.cibulka.codes/en
Due to language negotiation this is hard to cache (if you want to avoid using the cookies as I do). The lag usually stays around 700ms - which is not great not terrible, I suppose.
I love Markdown and I am obssesed with MDX! Here's my reasoning:
A brilliant library Contentlayer turns the MDX files to JSON files during the build step (and creates their TypeScript definitions right away). This works especially well with Next.js 13 and server components, which allows you to leave most of the bulk on the server (and send to the client only the actual content).
Creating and maintaining one's CV can be a bit of pain. Duplication is one of the issues: Is your PDF portfolio in sync with your web CV? In all the language versions?
For this reason I've created an automated page generating my CV in print-friendly format. The content comes from MDX files, that are shared between the website, public API and the CV.
The PDF version of the CV is automated by a Puppetteer-powered script. For now I run it manually through NPM script - and whenever I finally learn the GIT actions, this will probably be automated as well. 💪
One of the features of Next.js 13 is an ability to "intercept routes" - the same URL can act differently on direct load or if requested from an app.
This is especially useful for modals: You want to see a content from URL in the temporary dialogue (without resetting the state of the UI under it), but you want to allow the usage of back/forward buttons. Having separate URLs for the important pieces of content is obviously good for SEO as well.
It was a bit tricky to implement for me: Most of the guides expect the existence of the root layout (which is incompatible with the guidelines for i18n, as written above). I also found the syntax a bit confusing. Ultimately I made it work nonetheless. :)
Nothing special here, just wanted to have a bit more control on how the video is handled (and frankly it was just fun). There are however still some things to polish (allowing the user to change the time, for instance).
My portfolio also contains my shot at Tetris game. Give it a try, even if it's a bit addictive! 🍭 Or check the repo of the project.
You know the drill.
npm install
npm run dev # For development
npm run build && npm start # For production preview
PDF is generated with Puppetteer right from http://localhost:3000, so the page must be available on that link during the build time. Whenever it is, run:
npm run cv