Programming

Building My Portfolio Website

Building My Personal Portfolio Website: Challenges, Solutions, and Lessons Learned

Bereket Takiso
December 1, 2023
5 min read
Portfolio

Introduction

Creating a portfolio website is an exciting project, particularly when trying for showing your professionalism in IT industry. This blog article details the creation of my portfolio utilizing Next.js for the frontend and Strapi as the backend CMS. I will discuss the challenges I encountered and the lessons I learnt throughout the process. A significant difficulties was getting that images from my backend were shown correctly on the frontend, a common difficulty for many newbie developers.

Project Overview

This Portfolio is a responsive web app that displays my cybersecurity projects, blog posts, skills, certifications, and experiences. Here's the main tech stack I used:

Frontend:

  • Next.js 14.2.10

  • React 18 (dependencies)

  • Tailwind CSS 3.4.1

Backend:

  • Strapi CMS

  • Node.js

Database:

  • Postgres

Media Storage:

  • Amazon S3 (for image and file upload)

Additional libraries:

  • Axios (for API requests),

  • DOMPurify (for sanitizing HTML),

  • Lucide React (for icons),

  • React Syntax Highlighter (for code blocks)

Deployment:

  • Vercel (Frontend)

  • Heroku (Backend)

The website has a dynamic project showcase, a blog system with pagination, a skills section, and a responsive design with dark mode. I used Strapi as a headless CMS to manage content, which made it easy to add new projects or blog posts whenever I wanted.

Key Features of this Portfolio

  • Dynamic project showcase with detailed pages

  • Blog posts with search, and sorting options

  • Responsive design for any device

  • Syntax highlighting for code snippets

  • Image optimization using the Next.js Image component

Project Structure and Technologies

The project is organized into two main directories:

  • Frontend (Next.js)

    : This includes all the app components, pages, and utilities.

  • Backend (Strapi)

    : This contains the API endpoints, configuration, and database setup.

Deployment Workflow Diagram

Below is a diagram that shows the deployment workflow of this website, explaining how the backend, frontend, and media storage connect.


Diagram
Diagram

The Image Display Challenge

Issue:

One of the main challenges I faced was displaying images from the Strapi CMS on the frontend. The image URLs returned from Strapi were relative URLs, meaning they didn't include the full domain. This caused the images not to load properly on my frontend hosted with Vercel.

Solution:

After doing some research and troubleshooting, I found a solution that worked. I had to prepend the Strapi URL to the image paths before displaying them. I used a utility function to format the image URLs by adding the base URL of my Strapi instance:

1// Original code
2const imageUrl = media.data[0].attributes.url; // Get URL of the first media object
3const imageAlt = media.data[0].attributes.alternativeText;
4
5// Updated code with Strapi URL prepended
6const strapiUrl = process.env.NEXT_PUBLIC_STRAPI_API_URL || 'http://localhost:1337';
7const imageUrl = `${strapiUrl}${media.data[0].attributes.url}`; // Get full URL of the first media object
8const imageAlt = media.data[0].attributes.alternativeText;

This made sure that each image request included the full URL, so the images displayed correctly on the frontend. This solution was inspired by a discussion I found on the Strapi forum, where other developers had similar issues.

Content Security Policy Challenges

Issue:

Another problem I faced was Content Security Policy (CSP) violations when embedding YouTube videos, loading external fonts, fetching files from the backend, or using AWS S3 buckets. These errors occurred because my CSP settings were too restrictive and certain sources were not allowed.

Solution:

To solve this, I adjusted the CSP in my Strapi middleware file to explicitly allow these external resources. By updating the CSP directives, I allowed YouTube embeds (frame-src), Google Fonts (style-src and font-src), and media from AWS S3. This fixed the CSP violations and allowed these resources to load correctly.

Example API Calls

Here are examples of how the API calls are structured for different content types:

Projects

1const fetchProjects = async (): Promise<ProjectData[]> => {
2  return apiCall<ProjectData[]>({
3    method: 'GET',
4    url: '/api/projects',
5    params: { populate: '*' },
6  });
7};

Explanation of ?populate=*

The ?populate=* parameter is a query parameter used in Strapi API calls to include all related data in the response. This is useful when you need complete data, including related fields, in a single API call.

Lessons Learned

  1. API Integration

    : When working with a headless CMS like Strapi, you need to make sure your data is formatted correctly before sending it to the frontend. This often means handling relationships between content types and optimizing image URLs.

  2. Environment Variables

    : Using environment variables in both development and production is important to keep sensitive information, like API URLs and database credentials, safe and easy to change.

  3. Deployment Considerations

    : Working with two deployment platforms (Heroku for the backend and Vercel for the frontend) taught me a lot about hosting a full-stack app. Understanding how to set up environment variables and configure CORS policies is really important.

  4. Image Handling

    : Optimizing images isn't just about resizing them. Handling image paths and making sure they are fetched correctly from the backend to the frontend can be challenging, but tools like the Next.js Image component make it easier.

Building a Portfolio website was a rewarding experience that tested my skills in both frontend and backend development. From setting up Strapi as the CMS to deploying on multiple platforms, I learned a lot about creating and maintaining a full-stack app. Solving the challenges with displaying images on the frontend taught me how important it is to manage URLs and optimize content delivery.

Tags

#Portfolio#Website

Author

Portfolio Picture

Bereket Takiso

Share

Article Info

Published
December 1, 2023
Read Time
5 min read
Category
Programming