DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for DIY linktree with Next.js
Jason Behnke
Jason Behnke

Posted on • Updated on

DIY linktree with Next.js

Introduction

Recently, I've been noticing the use of link aggregation services like linktr.ee, ContactInBio, Campsite, etc. become more prevalent so I thought I'd try my hand a replicating it.

For this project, I'm going to use Next.js (which is 100% overkill) because I've been looking for an excuse to check it out. This is going to be a quick and fairly dirty build, so there is tons of room for improvement.

Getting started

First, we need to create a new project. I used yarn, but you can use NPM if you like and if you'd like to read up on Next.js check out these docs.

yarn create next-app
Enter fullscreen mode Exit fullscreen mode

Select default and name it something, then cd into that directory.

Now we'll conjure up the dev server and the boilerplate site with this command.

yarn dev
Enter fullscreen mode Exit fullscreen mode

Open up http://localhost:3000 and make sure you have something that looks like this.

welcome default page

Head section

In the index.js file located in the pages directory go ahead and change the <Head> section to whatever you want it to be. I changed it to what the pseudo username would be.

<Head>
  <title>dev01d</title>
  <link rel="icon" href="favicon.ico" />
</Head>
Enter fullscreen mode Exit fullscreen mode

Profile section

Next, we'll clear out the <main> section and replace it with the first element which is the profile picture and "username". We'll leave the default CSS alone because it has most of the stuff we need.

You should now have something like this. (CSS replaced with "..." so the code block is readable)

import Head from 'next/head'

export default function Home() {
  return (
    <div className="container">
      <Head>
        <title>dev01d</title>
        <link rel="icon" href="favicon.ico" />
      </Head>

      <main>
        <img className="image" src="IG profile image" />
        <h3 className="description">@dev01d</h3>
      </main>

      <style jsx>{`
       ...
     `}</style>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

For the profile image, I just opened the browser dev tools and grabbed my Instagram profile pic URL.

Great! We now have the profile section but your image probably isn't a circle so let's add some CSS for that. Add this anywhere in the <style jsx> section.

.image {
  border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

Link section

Ok cool, that looks nice. For the links, we're going to use a grid class and utilize the default CSS with some changes but before we get to the CSS let's get build some link elements.

They're going to be <a> tags and we're going to style them with the existing card class. This is the general structure I landed on.

<div className="grid">
  <a href="https://fake.address" className="card">
    <h3>Buy Prints</h3>
  </a>
</div>
Enter fullscreen mode Exit fullscreen mode

Now your index.js should look something like this, but with your info of course.

import Head from 'next/head'

export default function Home() {
  return (
    <div className="container">
      <Head>
        <title>dev01d</title>
        <link rel="icon" href="favicon.ico" />
      </Head>

      <main>
        <img className="image" src="URL of your IG profile image" />
        <h3 className="description">@dev01d</h3>

        <div className="grid">
          <a href="https://fakewebsite.com" className="card">
            <h3>My Website</h3>
          </a>
          <a href="https://github.com/dev01d" className="card">
            <h3>Github</h3>
          </a>
          <a href="https://medium.com" className="card">
            <h3>Medium</h3>
          </a>
          <a href="https://www.twitch.tv" className="card">
            <h3>Twitch</h3>
          </a>
        </div>
      </main>

      <style jsx>{`
       ...
     `}</style>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Let's pause and talk about CSS

Everyone has their own way that they like to approach CSS, and this is just the way I decided to do it. If you find a different way to accomplish this or improvements, please drop it in the comments.

Resume tutorial

The changes and additions I made to are pretty minor. Let’s start with the .grid class, all we need to do is reduce the margin-top attribute to 1rem

.grid {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;

  max-width: 800px;
  margin-top: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

next is the .card we'll change margin to 0.5rem, text-align to center, and background to #fafafa to keep it a light color

.card {
  margin: 0.5rem;
  flex-basis: 45%;
  padding: 1.5rem;
  text-align: center;
  background: #fafafa;

  color: inherit;
  text-decoration: none;
  border: 1px solid #eaeaea;
  border-radius: 10px;
  transition: color 0.15s ease, border-color 0.15s ease;
  min-width: 350px;
}
Enter fullscreen mode Exit fullscreen mode

Then for the link's label h3 tag, we need to change the default margin in .card h3 from margin: 0 0 1rem 0;to margin: 0 3rem 0 3rem;

Next, for our friends using smaller screens, we want to make sure the links aren't clipping over the edge. We'll add a media query to accommodate them, which should be in the ballpark.

@media (max-width: 350px) {
  .card {
    min-width: 275px;
  }
  .card h3 {
    margin: 0 3rem 0 3rem;
    font-size: 1.25rem;
  }
}
Enter fullscreen mode Exit fullscreen mode

Done!

There we go, we've got our own DIY link aggregator. Now all you need to do is buy a cleverly short domain name, host it somewhere like vercel.com for free, and throw it up on your Instagram profile.

finished screenshot

Ideas for further improvement

The CSS could use a bit of a tweak, a tree shake, and could probably use an a11y audit, but I'll leave that up to you since this is sort of a quick and dirty tutorial.

The code for this project can be found here.

Top comments (0)

🌚 Browsing with dark mode makes you a better developer by a factor of exactly 40.

It's a scientific fact.