How to build a Private Link Sharing App Using Next.js

Priyankar Pal - Jul 24 - - Dev Community

Introduction

In one of my recent projects, I needed to manage user permissions to access private & sensitive contents. But while implementing the solution, I struggled a lot.

After researching the problem, I found a solution that resolved the issue. That’s when I thought of writing this article.

In this article, we will be building a private link-sharing app using Next.js and Permit.io. Through the implementation, we will explore how to handle access requests, manage approvals, and enforce permissions to protect sensitive data.

Prerequisites

To build this application, we will be using Next.js with “Permit Share-If,” which simplifies permission management. “Permit Share-If” is a suite of prebuilt, embeddable UI components that make access sharing in applications a breeze.

Before moving on to the main part, make sure you know the basics of Next.js structure. If you want, you can read more from here

To implement Permit.io into the Next.js application, you first need to set up Permit.io. Let’s begin

Building a private link-sharing app

Setup Next.js project

To get started, let’s create a Next.js project.

  • Open a terminal and paste the command to create a new Next.js project.


npx create-next-app@latest .


Enter fullscreen mode Exit fullscreen mode
  • Next, we’ll Install the required dependencies


npm install @permitio/permit-js dotenv permitio


Enter fullscreen mode Exit fullscreen mode
  • Now we will create a.env file to store ENV & JWT secrets.


// .env
ENV=<permit env key>
JWT=<your JWT key>


Enter fullscreen mode Exit fullscreen mode

Now that the app is ready to go, we’ve successfully built the project.

Add the Access request Element

To create an access request element, you first need to create a user management element. Let’s create it.

  • Go to the Elements section of the permit dashboard
  • Click on “Create Element.” option Under the User Management

user management element

  • Set up the user management element by following these steps:
    • Add a name, i.e. “User Management.
    • Choose the RBAC role
    • Move the admin role from the ”Hidden Roles” section to “Level 1 - Workspace Owner.
    • And last, create the element.

User management creation is complete; let’s jump onto the next part.

  • Click on the Elements option
  • Under the Access request, click on “Create Element.”

Access request element

  • Choose the user management element you want to connect.
  • Customize the element as needed

Implement the Access Request Element within the application.

  1. Create a component called Linklist for our project
    • The Linklist component displays a list of links and provides an option to delete any of them.
    • The components render an unordered list with a delete button.


// src/components/Linklist.jsx
const LinkList=({ links, deleteLink }) => {
    return (
        <ul>
            {links.map((link, index) => (
                <li key={index}>
                    <a href={link} target="_blank" rel="noopener noreferrer">{link}</a>
                    <button onClick={() => deleteLink(index)}>Delete</button>
                </li>
            ))}
        </ul>
    );
};

export default LinkList;


Enter fullscreen mode Exit fullscreen mode
  1. Create a component named Linkform for adding links by users.


// src/components/Linkform.jsx
import { useState } from 'react';

const LinkForm=({ addLink }) => {
    const [url, setUrl] = useState('');

    const handleSubmit = (e) => {
        e.preventDefault();
        if (url) {
            addLink(url);
            setUrl('');
        }
    };

    return (
        <form onSubmit={handleSubmit}>
            <input className='text-black'
                type="url"
                value={url}
                onChange={(e) => setUrl(e.target.value)}
                placeholder="Enter URL"

                required
            />
            <button type="submit">Add Link</button>
        </form>
    );
};

export default LinkForm;



Enter fullscreen mode Exit fullscreen mode

Here, when a user triggers the Add Link button, it will add links.

  1. Now we have to create another component for user management named UserManagement.jsx


import React from 'react'

function UserManagement() {
  return (
<iframe
title="Permit Element user-management"
src="https://embed.permit.io/user-management?envId=e0ffba3632274e8085d92c793d34f0c1&darkMode=false"
width="100%"
height="100%"
/>
  )
}

export default UserManagement;


Enter fullscreen mode Exit fullscreen mode
  1. Now we have to create another components for access request named AccessRequest.jsx


import React from 'react'

function AccessRequest() {
  return (
 <iframe
            title="Permit Element AR"
            src="https://embed.permit.io/ar?envId=e0ffba3632274e8085d92c793d34f0c1&darkMode=false&tenantKey=default"
            width="100%"
            height="100%"
            style={{ border: 'none' }}
        />
  )
}

export default AccessRequest;


Enter fullscreen mode Exit fullscreen mode
  1. Next, Create another component for Dashboard that will use Permit Share-If


// src/components/Dashboard.jsx

'use client';
import permit, { LoginMethod } from '@permitio/permit-js';
import 'dotenv/config';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

const Dashboard = () => {
    const router=useRouter();
    const [authenticated, setAuthenticated]=useState(false);

    useEffect(() => {
        const login=async () => {
            try {
                await permit.elements.login({
                    loginMethod: LoginMethod.frontendOnly,
                    userJwt: process.env.NEXT_PUBLIC_JWT,
                    tenant: 'default',
                    envId: process.env.NEXT_PUBLIC_ENV,
                });
                console.log('Login successful');
                setAuthenticated(true);
            } catch (err) {
                console.error('Login error:', err);
            }
        };

        if (process.env.NEXT_PUBLIC_JWT&&process.env.NEXT_PUBLIC_ENV) {
            login();
        } else {
            console.error('JWT token or ENV variable is not defined.');
        }
    }, []);

    useEffect(() => {
        if (authenticated) {
            router.push('/links');
        }
    }, [authenticated, router]);

    return (
     <AccessRequest />
     <UserManagement />

    );
};

export default Dashboard;


Enter fullscreen mode Exit fullscreen mode

Here we have implemented auth, redirection & rendering now let’s understand a little bit about these
Authentication Handling
: a login function that tries to authenticate the user using permit.elements.login.Uses process.env.NEXT_PUBLIC_JWT and process.env.NEXT_PUBLIC_ENV from environment variables for authentication.

If authentication succeeds, it updates the state to indicate that the user is authenticated. Logs a success message or an error message if authentication fails.

Redirection: When authentication is successful, the component redirects the user to the /links page.

Rendering: Displays two different iframe by calling the components that embeds access request element from Permit.io.

Now we have to call the AccessRequest component on the page.js file



import Dashboard from '../components/Dashboard';

export default function Home() {
  return (
    <div>
      <h1>Private Link Sharing App</h1>
     <Dashboard/>

    </div>
  );
}



Enter fullscreen mode Exit fullscreen mode

Lastly, implement the link page route that will handle the link page.



// src/app/links/page.jsx
'use client';
import LinkForm from '@/components/Linkform';
import LinkList from '@/components/Linklist';
import { useState } from 'react';

const Links=() => {
    const [links, setLinks] = useState([]);

    const addLink=(url) => {
        setLinks([...links, url]);
    };

    const deleteLink = (index) => {
        setLinks(links.filter((_, i) => i!==index));
    };

    return (
        <div className='p-5'>
            <h1>Manage Links</h1>
            <LinkForm addLink={addLink} />
            <LinkList links={links} deleteLink={deleteLink} />
        </div>
    );
};

export default Links;



Enter fullscreen mode Exit fullscreen mode

With that, our application is fully complete.

Conclusion

By reading this guide, you have understood how to create a private link-sharing app using Next.js and Permit.io. You read about making access requests, approving the users, and permissions to be implemented to protect your private information.

Also, if you have any questions, feel free to write them in the comments.

Happy Coding!

. . . . . . . . . . .