DEV Community

Ulises Viña
Ulises Viña

Posted on

Dynamic Website 101

It's well known that static websites have become a thing of the past, so in order to make an attractive website you'll need to make it as dynamic as possible, that means, the less hard-coded content, the better. Today, I'll talk about all the integrations I've made to my website to make it attractive.

Introduction

For starters, you'll need to know the JavaScript and React basics, but we'll not cover that in this post, rather, we're going to immediately talk about design.

Choosing content

When making a website, you need to choose what content will go on it, today we're going to focus on portfolios, in which, you don't want every component to be dynamic, as an example, the Awards component on my website

Awards section on the author's website

This section barely changes, and it doesn't make any sense to create an API to maintain that section, given that changes occur say, once every 3 months, and the changes are minimum, you can just modify the section and re-deploy the website. Same goes for my "About" section.

So, what can we make dynamic?

I chose what content is dynamic in my website following this criteria:

  1. Does the content change regularly?
  2. Can I implement it using an API?
  3. Is the information relevant to the website I'm creating?

When evaluating the third condition, if you're creating a portfolio (or website for yourself) you can consider that everything that is of your liking could be relevant to the website, as a website made for yourself is exactly meant to make people know a little bit more about you.

Creating the dynamic content

For this example, I'll use my portfolio's dynamic colour palette; if you want to follow this pathway, you're more than welcome to do so.

In my website, the whole design changes when a song is played on Spotify, this is thanks to the dynamic colour palette feature, similar to the Monet engine on Android 12 or higher.

Author's portfolio homepage, featuring the dynamic colour palette.

In this case, the album's cover is obtained using the Spotify's API, then, passed onto an Image object in JavaScript, and then, that Image object is used with the ColorThief library in order to create a colour palette consisting of six colours, a primary, a secondary, a tertiary and their corresponding text colours (either #FFF, white or #000, black), the last of which is obtained using a math algorithm rather than a library.

First, the Spotify API is fetched using an API endpoint on my website's end (using Next.js backend)and it's corresponding controller.

The code for the controller goes as follows

const getAccessToken = async () => {
  const res = await fetch("https://accounts.spotify.com/api/token", {
    method: "POST",
    headers: {
      Authorization: `Basic ${process.env["SPOTIFY_AUTH_BASIC"]}`,
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: new URLSearchParams({
      grant_type: "refresh_token",
      refresh_token: process.env["SPOTIFY_REFRESH_TOKEN"],
    }),
  });

  return res.json();
};

export const getNowPlaying = async () => {
  const { access_token } = await getAccessToken(),
    nowPlaying = await fetch(
      "https://api.spotify.com/v1/me/player/currently-playing",
      {
        headers: {
          Authorization: `Bearer ${access_token}`,
        },
      }
    );

  return nowPlaying;
};

Enter fullscreen mode Exit fullscreen mode

As you can see, it obtains credentials from the environment variables and makes a request to the Spotify API using the access token obtained through the getAccessToken() function. The getNowPlaying() function retrieves information about the currently playing song on the user's Spotify account, which is then used to obtain the album cover image.

Once the album cover image is obtained, it is passed onto the ColorThief library which generates a color palette. This color palette is then used to style the website, with the primary color being used for the background and the secondary and tertiary colors being used for accents. This is done using a React Context Provider, and this is the code for it:

import { createContext, useState, useEffect, useContext } from "react";
import ColorThief from "../node_modules/colorthief/dist/color-thief.mjs";

export const MusicContext = createContext();

export const useMusic = () => useContext(MusicContext);

export const MusicProvider = ({ children }) => {
  const [music, setMusic] = useState({ isPlaying: false });

  const musicLogic = () => {
    fetch("/api/now-playing")
      .then((res) => res.json())
      .then((data) => {
        if (!data.isPlaying) return;

        console.log(data);

        const img = new Image(),
          colorthief = new ColorThief();

        img.crossOrigin = "Anonymous";
        img.src = data.albumImage;
        img.addEventListener("load", () => {
          try {
            const palette = colorthief.getPalette(img);

            const primaryBg = `rgb(${palette[0][0]}, ${palette[0][1]}, ${palette[0][2]})`,
              secondaryBg = `rgb(${palette[1][0]}, ${palette[1][1]}, ${palette[1][2]})`,
              tertiaryBg = `rgb(${palette[2][0]}, ${palette[2][1]}, ${palette[2][2]})`,
              primaryText =
                palette[0][0] * 0.299 +
                  palette[0][1] * 0.587 +
                  palette[0][2] * 0.114 >
                180
                  ? "#000"
                  : "#fff",
              secondaryText =
                palette[1][0] * 0.299 +
                  palette[1][1] * 0.587 +
                  palette[1][2] * 0.114 >
                180
                  ? "#000"
                  : "#fff",
              tertiaryText =
                palette[2][0] * 0.299 +
                  palette[2][1] * 0.587 +
                  palette[2][2] * 0.114 >
                180
                  ? "#000"
                  : "#fff";

            document.documentElement.style.setProperty(
              "--primaryBgColor",
              primaryBg
            );
            document.documentElement.style.setProperty(
              "--secondaryBgColor",
              secondaryBg
            );
            document.documentElement.style.setProperty(
              "--primaryTextColor",
              primaryText
            );
            document.documentElement.style.setProperty(
              "--secondaryTextColor",
              secondaryText
            );
            document.documentElement.style.setProperty(
              "--tertiaryTextColor",
              tertiaryText
            );
            document.documentElement.style.setProperty(
              "--tertiaryBgColor",
              tertiaryBg
            );

            setMusic({
              ...data,
              primaryBg: `${palette[0][0]}, ${palette[0][1]}, ${palette[0][2]}`,
            });
          } catch (e) {
            console.log(e);
          }
        });
      });
  };

  useEffect(() => {
    musicLogic();
    const interval = setInterval(() => {
      musicLogic();
    }, 30000);
    return () => clearInterval(interval);
  }, []);

  return (
    <MusicContext.Provider value={{ music }}>{children}</MusicContext.Provider>
  );
};

Enter fullscreen mode Exit fullscreen mode

Conclusion

Creating a dynamic website can be a lot of work, but it's worth it. By making use of APIs and libraries, you can create a website that not only looks good but also provides a great user experience. When deciding what content to make dynamic, remember to evaluate how frequently it changes and whether it's relevant to your website. With the right tools and some creativity, you can create a dynamic website that stands out from the rest.

Top comments (0)