Creating the Linktree Page of a User

Creating the LinkTree page of a user | LinkTree Project

This tutorial is a part of the Series ‘Complete FullStack LinkTree Project with MERN‘. This Project covers beginner to Intermediate level implementation of MongoDB, Express, ReactJS, NodeJS, and NextJS.

Project Walkthrough

Users can signup on the LinkTree website and start creating their LinkTree immediately. They get a user profile editing page, an edit or customize links page, a Dashboard to edit and track the links, and many more.

I’ve created a YouTube series on this Project in 6 parts. This Code snippet is from the 5th part where we create a LinkTree page itself for a single user.

Frontend

import React from "react";
import LinkTreeCard from "./LinkTreeCard";
import { AnimatePresence, motion } from "framer-motion";
 
const LinkTree = ({ data }) => {
  const { name, avatar, bio, links } = data;
  return (
    <>
      <section className="relative">
        <img
          className="w-20 absolute rounded-full left-1/2 -translate-x-1/2 mt-2"
          src={avatar}
          alt=""
        />
        <h2 className="text-center text-lg font-bold pt-28">
          {name ? name : "No Username"}
        </h2>
        <p className="text-center pb-5">{bio}</p>
        <div className="flex flex-col justify-center max-w-7xl m-auto md:my-5 w-full md:w-2/5">
          <AnimatePresence>
            {links.map((link, index) => (
              <motion.div
                key={index}
                initial={{ opacity: 0, y: 40 }}
                animate={{
                  opacity: 1,
                  y: 0,
                  transition: { delay: index * 0.1 + 0.5 }
                }}
              >
                <LinkTreeCard
                  title={link.title}
                  url={link.url}
                  image={link.icon}
                />
              </motion.div>
            ))}
          </AnimatePresence>
        </div>
      </section>
    </>
  );
};
 
export default LinkTree;
import Link from "next/link";
import React from "react";
 
const LinkTreeCard = ({ title, url, image }) => {
  return (
    <>
      <span className="w-full">
        <Link
          className="flex flex-row items-center p-2 rounded-xl text-white bg-indigo-400 hover:bg-indigo-300 mb-3 mx-2 hover:translate-x-1 hover:translate-y-1 transition-all duration-500"
          target="_blank"
          href={`https://${url}`}
        >
          <img
            className="bg-white rounded-md p-1 w-11 mr-5"
            src={image}
            alt=""
          />
          <h4 className="md:text-lg">{title}</h4>
        </Link>
      </span>
    </>
  );
};
 
export default LinkTreeCard;
import Link from "next/link";
import React from "react";
 
const SocialTree = ({ social }) => {
  const { facebook, twitter, instagram, youtube, linkedin, github } = social;
  return (
    <>
      <div className="social flex flex-row justify-center my-4">
        <Link
          className="bg-white rounded-full p-2 hover:bg-zinc-100 transition-all duration-500 hover:scale-110 shadow border border-gray-70 mx-1 select-none"
          target="_blank"
          href={`https://facebook.com/${facebook}`}
        >
          <img className="w-6" src="/svg/facebook.svg" />
        </Link>
        <Link
          className="bg-white rounded-full p-2 hover:bg-zinc-100 transition-all duration-500 hover:scale-110 shadow border border-gray-70 mx-1 select-none"
          target="_blank"
          href={`https://instagram.com/${facebook}`}
        >
          <img className="w-6" src="/svg/instagram.svg" />
        </Link>
        <Link
          className="bg-white rounded-full p-2 hover:bg-zinc-100 transition-all duration-500 hover:scale-110 shadow border border-gray-70 mx-1 select-none"
          target="_blank"
          href={`https://youtube.com/${facebook}`}
        >
          <img className="w-6" src="/svg/yt.svg" />
        </Link>
        <Link
          className="bg-white rounded-full p-2 hover:bg-zinc-100 transition-all duration-500 hover:scale-110 shadow border border-gray-70 mx-1 select-none"
          target="_blank"
          href={`https://linkedin.com/${facebook}`}
        >
          <img className="w-6" src="/svg/lnkdn.svg" />
        </Link>
        <Link
          className="bg-white rounded-full p-2 hover:bg-zinc-100 transition-all duration-500 hover:scale-110 shadow border border-gray-70 mx-1 select-none"
          target="_blank"
          href={`https://github.com/${facebook}`}
        >
          <img className="w-6" src="/svg/github.svg" />
        </Link>
        <Link
          className="bg-white rounded-full p-2 hover:bg-zinc-100 transition-all duration-500 hover:scale-110 shadow border border-gray-70 mx-1 select-none"
          target="_blank"
          href={`https://twitter.com/${facebook}`}
        >
          <img className="w-6" src="/svg/twt.svg" />
        </Link>
      </div>
    </>
  );
};
 
export default SocialTree;
import React, { useState, useEffect } from "react";
import { useRouter } from "next/router";
import LinkTree from "../components/LinkTree";
import Link from "next/link";
import SocialTree from "../components/SocialTree";
import ShareButton from "../components/ShareButton";
 
const Handle = () => {
  const router = useRouter();
  const [data, setData] = useState({});
  const [userFound, setUserFound] = useState(false);
 
  const [social, setSocial] = useState({
    facebook: "",
    twitter: "",
    instagram: "",
    youtube: "",
    linkedin: "",
    github: ""
  });
 
  useEffect(() => {
    if (router.query?.handle) {
      fetch(`http://localhost:8080/get/${router.query.handle}`)
        .then((res) => res.json())
        .then((data) => {
          if (data.status === "error") return toast.error(data.error);
          if (data.status === "success") {
            setData(data.userData);
            setSocial(data.socials);
            setUserFound(true);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    }
  }, [router.query]);
 
  if (!userFound) {
    return (
      <div className="flex justify-center items-center h-screen">
        <div className="not-found px-3 ">
          <h1 className="font-bold text-lg">User Not found 🙁</h1>
          <p>If you're looking for a page, double check the spelling.</p>
          Create your own
          <Link
            className="bg-indigo-600 px-2 ml-2 text-white hover:bg-indigo-400 transition-all duration-500"
            href="/apply"
          >
            {" "}
            LinkTree
          </Link>
        </div>
      </div>
    );
  }
 
  return (
    <div>
      <ShareButton />
      <LinkTree data={data} />
      <SocialTree social={social} />
    </div>
  );
};
 
export default Handle;

Backend

// Added user data grabbing to previous code in index.js
 
app.get("/get/:handle", getUserData);
const User = require("../models/user");
 
const getUserData = async (req, res) => {
  const handle = req.params.handle;
  try {
    const user = await User.findOne({ handle: handle });
    console.log(user);
    const userData = {
      name: user.name,
      avatar: user.avatar,
      bio: user.bio,
      links: user.links
    };
    const socials = user.socialMedia;
    return res.json({ message: "found", userData, socials, status: "success" });
  } catch (err) {
    console.log(err);
    return res.json({ status: "error", error: err.message });
  }
};
 
const getUserSocials = async (req, res) => {
  const handle = req.params.handle;
  try {
    console.log(handle);
    const user = await User.findOne({ handle: handle });
    const socials = user.socialMedia;
    return res.json({ message: "found", socials, status: "success" });
  } catch (err) {
    return res.json({ status: "error", error: err.message });
  }
};
 
module.exports = { getUserData, getUserSocials };

Summing up

I hope this part of the tutorial on the Fullstack LinkTree Project was helpful to you. If you faced any problems while following the video or the source code snippets, comment below and I’ll reply as soon as possible. See you soon.

IndGeek provides solutions in the software field, and is a hub for ultimate Tech Knowledge.