단 2시간 만에 페이지와 같은 최소 링크 트리를 만든 방법.

계획



소셜 링크 페이지를 만들 수 있는 linktree 및 유사한 사이트를 사용하는 많은 사람들을 보았지만 매우 미니멀하고 깨끗한 것이 필요했기 때문에 나만의 소셜 링크 페이지를 만들기로 결정했습니다!

참고: 가능한 한 프로세스를 설명하려고 노력했지만 아직 블로깅 초보자이므로 어떤 부분에서 이상하게 보이더라도 개선할 수 있는 부분을 알려주세요. 당신에게서 듣습니다.

설계



작은 아바타, 이름, 약력 및 모든 소셜 링크를 멋진 호버 효과가 있는 아이콘으로 표시한 디자인은 나에게 꽤 명확했습니다. 필요한 경우 쉽게 사용자 정의할 수 있도록 만들고 싶었기 때문에 모든 색상, 아이콘 목록, 이름, 약력 및 아바타 링크가 포함된 구성 파일을 구현해야 한다는 것을 알았습니다. 다음과 같습니다.

// config.js 
export const config = {
    avatar: 'https://avatars.githubusercontent.com/u/68690233',
    bgColor: '#18181b',
    textColor: '#d4d4d8',
    iconColor: '#d4d4d8',
    name: 'ashish',
    description: 'solo developer by day, overthinker by night.',
    links: [
        {
            slug: 'github',
            type: 'url',
            link: 'https://github.com/asheeeshh/'
        },
        {
            slug: 'discord',
            type: 'hover',
            text: 'asheeshh#7727'
        },
        ...
    ]
}


다른 아이콘과 구별하기 위해 discord에 type: 'hover'를 어떻게 사용하고 있는지 확인하고 이유를 알기 위해 계속 읽으십시오.

기술 스택



그것은 단지 단일 페이지 앱이었기 때문에 지금은 매우 편안하기 때문에 NextJS를 사용하기로 결정했습니다. 내가 사용한 모든 프레임워크와 라이브러리는 다음과 같습니다.
  • 넥스트제이에스
  • 순풍
  • React-Tooltip
  • React-Hot-Toast
  • Simple-Icons

  • 앱 만들기



    먼저 프로젝트에서 사랑받는 명령 create-next-app , initialized tailwind CSS를 사용하여 다음 프로젝트를 빠르게 시작하고 필요한 다른 모든 라이브러리를 설치했습니다.

    다음 단계는 Avatar.jsx , Icon.jsxIconBar.jsx 와 같은 필요한 모든 구성 요소를 만드는 것입니다.

    구성품


  • Avatar.jsx - 앱의 아바타 구성 요소입니다.
  • Icon.jsx - 개별 아이콘 구성 요소.
  • IconBar.jsx - 앱의 가로 아이콘 모음 구성 요소입니다.

  • 이제 이 파일의 내용에 대해 논의해 보겠습니다.

    다음은 내 Avatar.jsx 파일의 코드입니다. 순풍 클래스가 있는 다음 이미지 구성 요소입니다.

    // Avatar.jsx
    
    import Image from 'next/image'
    
    export default function Avatar() {
        return (
            <Image src="https://avatars.githubusercontent.com/u/68690233" alt="Avatar" width={100} height={100} className="rounded-full"/>
        )
    }
    


    아이콘의 경우 Simple-Icons를 사용하고 있는데 정확히 필요한 브랜드 아이콘이 많기 때문입니다. 먼저 슬러그를 이용하여 SVG 아이콘을 얻기 위한 파일GetIcon.js을 생성했습니다. 다음과 같이 보입니다.

    // GetIcon.js
    
    import SimpleIcons from 'simple-icons';
    
    export default function GetIcon(slug) {
        const icon = SimpleIcons.Get(slug).svg
        return icon;
    }
    


    보시다시피 아이콘의 <svg></svg> 태그를 문자열로 반환합니다. 다음 단계는 문자열을 내 Icon.jsx 구성 요소가 수행하는 jsx 구성 요소로 변환하는 것입니다.

    // Icon.jsx
    
    import GetIcon from "../libs/GetIcon";
    import { config } from "../config";
    
    export default function Icon(props) {
        return (
            <div dangerouslySetInnerHTML={{__html: `${GetIcon(props.icon)}`}} className="w-[30px] h-[30px] hover:scale-[1.15]  duration-300 ease-in-out" style={{fill: `${config.iconColor}`}}></div>
        )
    }
    


    config를 사용하여 아이콘 색상을 설정하고 있음을 알 수 있습니다. 아이콘 슬러그를 소품으로 사용하여 GetIcon()를 사용하여 jsx 구성 요소로 변환되는 문자열로 svg를 반환하는 dangereouslySetInnerHTML에 전달합니다.

    마지막 구성 요소는 모든 아이콘을 가로로 쌓고 jsx 구성 요소로 반환하는 IconBar.jsx입니다.

    // IconBar.jsx
    
    import Icon from "./Icon";
    import { config } from "../config";
    import ReactTooltip from 'react-tooltip';
    import { useEffect, useState } from "react";
    import toast, { Toaster } from 'react-hot-toast';
    
    export default function IconBar() {
        const [isMounted, setIsMounted] = useState(false)
        useEffect(() => {
            setIsMounted(true)
        }, [])
        const handleClick = (e) => {
            navigator.clipboard.writeText(e.target.closest('[data-tip]').dataset.tip)
            toast.success("Copied to clipboard!", {
                duration: 2000,
            })
        }
        const icons = config.links.map(
            (icon) => {
                if (icon.type == "url") {
                    return (
                        <div className="text-center items-center cursor-pointer" key={icon.slug}>
                            <a href={icon.link} target="_blank" rel="noopener noreferrer" >
                                <Icon icon={icon.slug} />
                            </a>
                        </div>
                    );
                } else if (icon.type == "hover") {
                    return (
                        <div className="text-center items-center cursor-pointer" key={icon.slug}> 
                            <a data-tip={icon.text} key={icon.slug} onClick={handleClick}>
                                <Icon icon={icon.slug} />
                            </a>
                            {isMounted && <ReactTooltip place="top" type="dark" effect="float"/>}
                        </div>
                    )
                } else {
                    return;
                }
            }
        )
        return (
            <div className="flex flex-wrap w-full h-full gap-5 justify-center items-top">
                <Toaster 
                    toastOptions={{
                        style: {
                            background: `${config.textColor}`
                        }
                    }}
                />
                {icons}
            </div>
        )
    }
    


    config.js 파일에 있는 배열을 icons로 매핑하여 반환된 div에서 최종적으로 사용되는 <div></div> 구성 요소로 변환합니다. 또한 discord에는 URL이 없지만 discord 아이콘에 대한 툴팁을 만들기 위해 사용한 태그React-Tooltip가 있습니다. 그래서 위와 같이 디스코드 아이콘에 type: 'hover'를 추가했습니다.

    discord 태그가 복사되었다는 알림을 표시하기 위해 React-Hot-Toast 라이브러리를 사용했습니다.

    부품 조립



    마지막 단계는 내 파일index.js의 모든 구성 요소를 조합하여 앱을 완성하는 것이었습니다. 다음과 같습니다.

    // index.js
    
    import Avatar from "../components/Avatar"
    import IconBar from "../components/IconBar"
    import { config } from "../config"
    import Head from "next/head"
    
    export default function Home() {
      return (
        <div className="flex flex-col justify-center items-center w-screen h-screen p-6" style={{backgroundColor: `${config.bgColor}`}}>
          <Head>
            <title>{config.name}</title>
            <meta name="description" content={config.description} />
            <link rel="icon" href={(process.env.NEXT_PUBLIC_CLOUDIMG_TOKEN) ? `https://${process.env.NEXT_PUBLIC_CLOUDIMG_TOKEN}.cloudimg.io/${config.avatar}?radius=500` : `${config.avatar}`} />
          </Head>
          <div className="flex flex-col justify-center align-center w-full lg:w-1/2 md:w-1/3 h-[80%] lg:h-1/2 md:h-1/2 items-center">
            <div className="w-full h-full flex flex-col justify-center items-center">
              <Avatar />
              <h1 className="text-center text-xl font-[600] mt-3" style={{color: `${config.textColor}`}}>{config.name}</h1>
              <h1 className="text-[${config.textColor}] text-center text-md font-normal mt-5" style={{color: `${config.textColor}`}}>{config.description}</h1>
              <div className="w-full h-1/4 mt-5 lg:mt-3 md:mt-3">
                <IconBar />
              </div>
            </div>
          </div>
        </div>
      )
    }
    


    조립 후 테일윈드를 사용하여 약간의 스타일을 지정하면 앱이 다음과 같이 표시됩니다.



    앱 배포



    Vercel을 사용하여 NextJS와 가장 잘 작동하는 앱을 배포하고 사용자 정의 하위 도메인을 추가했습니다. 이 사이트는 현재 https://ayyy.vercel.app/https://ayyy.asheeshh.ninja/에서 운영 중입니다.

    결론



    이것이 앱을 만드는 전 과정이었고, 만드는 데 대략 2시간 정도 걸렸고, 현재는 이미 소셜 링크 페이지로 사용하고 있습니다.

    원하는 경우 자신만의 페이지를 만드는 데 자유롭게 사용할 수 있으며 소스 코드는 MIT 라이센스here에 따라 사용할 수 있습니다.

    읽어주셔서 감사합니다 <3

    좋은 웹페이지 즐겨찾기