5 min read

How I created this website

How I connected Notion, Figma and Next.js to build an ultimate porfolio website with an amazing DX and CMS.

How I created this website article cover image
Published: 27 Dec 2022
Last updated: 05 Jun 2023

This one is going to get technical, but bear with me. At least I can say I warned you.

In late 2022 I was in my last year of my master’s degree and started thinking about what to do after. Obviously I needed to get a job and to get a job in UX Design I needed a portfolio. I assembled three of my previous projects, got all the screenshots and wrote a short case study about each. Then it was time to publish my portfolio somewhere on the internet. So why did I not just use a premade template on any of the popular website builders like Wix, Sqaurespace, Webflow or even just a Wordpress site?

As a designer with a software engineering background, I felt like my portfolio website could also show off my skills and so I decided to design it myself. The decision to code it myself too came about when I was thinking about moving my case studies from Notion, my writing tool of choice to some publishing platform that would allow me to have full control of the design of the website. As I already had the content in Notion I did not want to have to copy it every time I would make a change and I wasn’t ready to give up the excellent writing experience of Notion to some website builder’s integrated CMS. So I started googling and found https://github.com/souvikinator/notion-to-md, an amazing little library that transforms my Notion documents into Markdown, which I can then render on my website with full control of the layout and visuals with https://github.com/mdx-js/mdx.

Design

Frameworks and libraries

The choice of other libraries and frameworks was not a very evidence based one. I just chose the tools that I already used and liked. Not pro’s and con’s list, no data backed decision making. I just love working with these tools and my personal website is one of the project, where I can just choose what I want to get the best DX (Developer eXperience) possible. I recently found an open-source project, that scaffolds a full-stack, typesafe Next.js app, it’s called https://github.com/t3-oss/create-t3-app, can absolutely recommend, it’s a joy working with the T3 stack.

I added a couple more libraries like HeadlessUI and Framer Motion and hosted the whole thing on Vercel, which was a seamless experience. On Vercel I also connected Axiom and Highlight.run for monitoring and user analytics.

Notion integration

To get content from Notion I used https://github.com/makenotion/notion-sdk-js and https://github.com/souvikinator/notion-to-md and because I wanted to cash all my images I also wrote a this code to extract image URLs from the exported Markdown, download the images and replace the URLs in the Markdown source to local ones.

I’ve setup a database inside of Notion that is filtered by post type into Blog articles and Projects. The system is very flexible and I like the fact that I can work on anything inside of Notion and when I’m ready to publish I just tick a checkbox and redeploy my website.

Custom Figma integration

As I was updating my case studies with more designs I got tired of exporting frames from Figma and pasting them to Notion whenever I made a change to them. Notion is great in that you can just paste a Figma link and it created a preview right in the document. But MDX does not know how to handle those and so they are just rendered as urls. So I though.. Figma has an API. Why could I not just paste my Figma links to Notion and then call the Figma API when building the site to obtain a rendered PNG image of the frame and replace the original link to the frame with a link to the rendered image?

Well that’s exactly what I tried and got it working in a few hours, but then I stumbled on a limitation. The urls of the rendered images from the Figma API have an expiration time of 1 hour. And I don’t want all my images to disappear or to have to call the API periodically. But then I thought. I’m statically generating all of my pages anyway. To I could just download the PNG from the Figma API provided url at build time. With this approach I could also use the Vercel Image Optimization, which is just an added bonus.

I needed to jump through a couple of hoops, but got it working eventually. Here’t the code powering this Figma-Notion automation.

Performance

With the power of Nexj.js’s SSG (Static Site Generation), Vercel Image Optimization and couple other tricks which I spent a few days implementing, I finally got the ultimate lighthouse score

Feel free to dive into the source code https://github.com/tomastrejdl/tomastrejdl.xy to get some inspiration as I did with other people’s repositories when building my website. The most helpful to me were in no particular order https://github.com/leerob/leerob.io, https://github.com/delbaoliveira/website.

And of course, I cannot forget about the mandatory Lighthouse score. Tested on the live published site on desktop and mobile. Proof here.