image description
URL shortening API landing page

URL shortening API landing page

Api
Web App
Frontend Mentor
LIVE URL

URL shortening web application, built using NextJs using TypeScript.

The application utilizes the API to shorten user-provided URLs and displays the shortened URL in a clean, user-friendly interface and web accessible way. The application also includes form validation and error handling to ensure that the input can't contain and invalid url.

The most difficult thing while building this project was getting the margins and paddings correctly positioned. It also took some time to get the local storage to work without causing a Next.js hydration error. My solution to this was as follows:

 

  if (typeof window !== "undefined" && window.localStorage) {
    initialValue = JSON.parse(localStorage.getItem("linksArray") ?? "[]") || [];
  }

  const [linksArray, setLinksArray] =
    useState<Array<{ shortLink: string; originalLink: string }>>(initialValue);

  useEffect(() => {
    if (typeof window !== "undefined" && window.localStorage) {
      localStorage.setItem("linksArray", JSON.stringify(linksArray));
    }
  }, [linksArray]);

 

And to prevent the Hydration error by waiting the dom to load in the UrlShortener component and rendering the links array when dom is loaded.

{domLoaded && (
          <div className={styles.links}>
            {linksArray.map((item) => (
              <div
                className={`${styles.linkItem} ${styles.flexLinks}`}
                key={item.shortLink}
              >
                <p className={styles.url}>{item.originalLink}</p>
                <div className={styles.seperator}></div>
                <div className={`${styles.ctaItems} ${styles.flexLinks}`}>
                  <p className={styles.shortenedUrl}>{item.shortLink}</p>
                  <button
                    type="submit"
                    className={`${styles.copyBtn} ${
                      lastClicked === item.shortLink ? styles.copied : ""
                    }`}
                    onClick={() => handleCopyClick(item.shortLink)}
                  >
                    {lastClicked === item.shortLink ? "Copied!" : "Copy"}
                  </button>
                </div>
              </div>
            ))}
          </div>
        )}