2024 Blog Site Update - Server components galore!
Web Development
Next.js
TailwindCSS
Notion
February 28, 2024
Time for another update to the personal blog! The last blog update was really getting my hands dirty with Tailwind, but this time around I opted to use a design system that was built with Tailwind to help with consistency. Let’s chat about the updates:
Tech Stack
Framework: Next.js 14
CSS Framework: Preline Design System (TailwindCSS)
CMS: Notion
CI/CD: Vercel
Updates
Design System (Preline.co)
Hey there! Last time I revamped the blog, I had a grand plan. I meticulously crafted the layout and design on Figma, deciding on fonts and colors in advance. I was super excited, thinking I'd made something pretty awesome. But when I finally got it all together, it didn't quite hit the mark. There was too much empty space and not enough imagery. With only a weekend to get everything done, I couldn't tweak it as I'd have liked. I just had to roll with it and hope I'd get a chance to jazz it up later.
This time, I decided to take a different route and use a design system. I was on the hunt for one that came with a full component library and was easy to customize. Here's what I was specifically looking for:
- Uses Tailwind as the CSS framework
- Has a basic component library
- Doesn't resemble all the other design systems (Material, ant, etc.)
- Is easy to customize
- Comes with premade layout templates and examples
- Is open source (FREE!)
Ultimately, I settled on the Preline design system. It ticked almost all my boxes. There were a couple of downsides to Preline, though:
- The components are mostly HTML with Tailwind for styling, and most don't come with built-in functionality.
- Most components are geared towards marketing sites, dashboards, and forms.
But, having created design systems for clients in the past, I'm pretty comfortable coding my own components. Plus, if I needed any extra ones, I could just whip them up myself.
I used the Prisma Figma file to make the layout, then built out my custom components. This approach seriously sped up the development process. I managed to knock out all the features in a single weekend. I've gotta say, I'm really impressed with this design system and would absolutely use it again.
Server Components
The latest version of React has just introduced Server components as a beta feature and Next.js jumped right on board with version 14. This interesting feature allows you to choose whether to render a component on the server or have it render on the client side. So, what does this mean for you? It means that data fetched from API’s can be called on the server and sent straight to the front end, rather than the client calling the API and generating the component. This means that data can be prefetched and the layout created on the backend, relieving some of the load on the client. Isn't that neat?
I have to admit, it took me a little while to really grasp the concept. Merging server-side and client-side code was a bit of a curveball for me, as I'm a big fan of keeping architectures layered (maybe it's my Java roots showing, and boy, those early days were a handful!). Honestly, I'd be a tad cautious about using this in a corporate context, unless it's for a quick marketing site. I'd just be a little concerned about things potentially getting a bit untidy. But overall, I really do believe this is moving us in the right direction. I mean, I was totally gobsmacked when I first saw this:
1// Async on a component!!!! 2const BlogPage = async () => {}
Reading List
I've recently rediscovered how much I love diving into a good book! College turned reading into more of a chore for me - it was all about studying, after all. But now, I've found the joy in cozying up with a book just for the fun of it again. For this new version of my website, I thought it'd be really nice to share the books I'm engrossed in and give everyone a peek into what I'm currently reading.
Data
For my book list, I've found a fun and efficient way of keeping track of all the books I've read - I use Notion! I've created a handy little Database in Notion, cleverly named “Reading”. It's a one-stop-shop for everything I want to read, and it doesn't matter the format - comics, articles, ebooks, you name it. Whenever the reading bug bites, I simply add my choice to the database and it organizes itself based on my pre-set tags for different media types. To make things even easier, I've set it up to sort by reading status. So, whether it's a "want to read" or a "read", they automatically pop up on their respective filtered tabs.
To grab data from a Notion Database, you'll first need to locate the DB ID. Here's where you can find it:
- Webapp - Just head over to the DB view and pick up the 1st hash from the URL.
- App - Navigate to the DB view ⇒ tap the share button ⇒ Copy the invite link. This link is the URL. Snag the 1st hash from there.
Once you've got your hands on the ID, you're all set to query it using the Notion API:
1export const getBooks = async (year: string, state: string, type: string,) => { 2 const books = await notion.databases.query({ 3 database_id: process.env.BOOK_DB_ID || '', 4 filter: { 5 and : [ 6 { 7 property: "Media Type", 8 select: { 9 equals: type 10 } 11 }, 12 { 13 property: "State", 14 select: { 15 equals: state 16 } 17 }, 18 { 19 property: "Date Finished", 20 date: { 21 after: `${year}-01-01` 22 } 23 }, 24 { 25 property: "Date Finished", 26 date: { 27 before: `${year}-12-31` 28 } 29 }, 30 ] 31 }, 32 sorts: [ 33 { 34 property: "Date Finished", 35 direction: "ascending", 36 }, 37 ], 38 }) 39 40 const allBooks = books.results; 41 return allBooks.map((book) => { 42 return getBookMetadata(book); 43 }); 44} 45 46export const getBookMetadata = (book: any) => { 47 const coverFile = book.properties.Image.files[0] 48 const coverURL = coverFile.type === 'external' ? coverFile.external.url : coverFile.file.url 49 const bookData = { 50 title: book.properties.Title.title[0].plain_text, 51 cover: coverURL, 52 review: book.properties.Review.select?.name 53 } 54 55 return bookData; 56}
In this code, I've filtered the "Reading" database down by Media type, state, and a date range. Then, to keep things neat, I've sorted it all by the date finished. Next, I process the data to pluck out the necessary metadata - that's where getBookMetadata()
steps in. Just a friendly reminder, some of the datatypes have unique schemas, so make sure to peek at the docs.
UI
For the UI bit, I whipped up a neat CSS grid and added some basic pagination controls for the local data. I've showcased each book with its title, a reading status tag (if it's a current read), and a rating. Feel free to take a trip down memory lane and check out what I've read in previous years.
Looking ahead, I'm thinking about adding affiliate links to each of the books and maybe even a more in-depth review. But hey, it's pretty great as it is for now!
Conclusion
I've managed to pick up quite a lot about where web development is headed in 2024, although who knows? I might be behind the times in a month or so. I've got a long list of enhancements I'm hoping to tackle throughout the year. But for now? I'm pretty satisfied with how things turned out.
Latest from the Blog
Currently Reading
![Chad Avatar](/_next/image?url=https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F8732d4dd-8d29-482c-8c1a-be6bca59b748%2Fab6ec887-7179-4ba3-8947-be3bc6a4ff54%2FIMG_3816.jpeg%3FX-Amz-Algorithm%3DAWS4-HMAC-SHA256%26X-Amz-Content-Sha256%3DUNSIGNED-PAYLOAD%26X-Amz-Credential%3DAKIAT73L2G45HZZMZUHI%252F20240908%252Fus-west-2%252Fs3%252Faws4_request%26X-Amz-Date%3D20240908T012509Z%26X-Amz-Expires%3D3600%26X-Amz-Signature%3D42dfd9538ef807997a6ba05dec3542b5ca0165db8b322083785e10ad3720e7d4%26X-Amz-SignedHeaders%3Dhost%26x-id%3DGetObject&w=828&q=75)