diff --git a/src/components/profile/UserAccountLinking.js b/src/components/profile/UserAccountLinking.js
new file mode 100644
index 0000000..d8e2724
--- /dev/null
+++ b/src/components/profile/UserAccountLinking.js
@@ -0,0 +1,213 @@
+import React, { useEffect } from 'react';
+import { Menu } from 'primereact/menu';
+import GenericButton from '@/components/buttons/GenericButton';
+import { signIn } from 'next-auth/react';
+import Image from 'next/image';
+import useWindowWidth from '@/hooks/useWindowWidth';
+import { useNDKContext } from "@/context/NDKContext";
+import { useToast } from '@/hooks/useToast';
+import { useRouter } from 'next/router';
+import { useSession } from 'next-auth/react';
+
+const LinkAccountsCard = ({ session }) => {
+    const isNostrLinked = session?.user?.pubkey && !session?.user?.privkey;
+    const isGithubLinked = session?.account?.provider === 'github';
+    const isEmailLinked = Boolean(session?.user?.email);
+    const windowWidth = useWindowWidth();
+    const { ndk, addSigner } = useNDKContext();
+    const { showToast } = useToast();
+    const router = useRouter();
+    const { update } = useSession();
+
+    // Check for email verification success
+    useEffect(() => {
+        const checkEmailVerification = async () => {
+            if (router.query.emailVerified === 'true') {
+                await update(); // Update the session
+                showToast('success', 'Success', 'Email verified successfully');
+                // Remove the query parameter
+                router.replace('/profile', undefined, { shallow: true });
+            } else if (router.query.error === 'VerificationFailed') {
+                showToast('error', 'Error', 'Email verification failed');
+                router.replace('/profile', undefined, { shallow: true });
+            }
+        };
+
+        checkEmailVerification();
+    }, [router.query, update, showToast, router]);
+
+    const handleGithubLink = async () => {
+        if (!isGithubLinked) {
+            try {
+                await signIn("github", { 
+                    redirect: false,
+                    // Pass existing user data for linking
+                    userId: session?.user?.id,
+                    pubkey: session?.user?.pubkey,
+                    privkey: session?.user?.privkey || null
+                });
+            } catch (error) {
+                console.error("Error linking GitHub:", error);
+                showToast('error', 'Error', 'Failed to link GitHub account');
+            }
+        }
+    };
+
+    const handleNostrLink = async () => {
+        if (!isNostrLinked) {
+            try {
+                if (!ndk.signer) {
+                    await addSigner();
+                }
+                const user = await ndk.signer.user();
+                const pubkey = user?._pubkey;
+                
+                if (pubkey) {
+                    const response = await fetch('/api/user/link-nostr', {
+                        method: 'POST',
+                        headers: {
+                            'Content-Type': 'application/json',
+                        },
+                        body: JSON.stringify({
+                            nostrPubkey: pubkey,
+                            userId: session?.user?.id
+                        })
+                    });
+
+                    if (response.ok) {
+                        showToast('success', 'Success', 'Nostr account linked successfully');
+                        // Refresh the session to get updated user data
+                        await update();
+                    } else {
+                        throw new Error('Failed to link Nostr account');
+                    }
+                }
+            } catch (error) {
+                console.error("Error linking Nostr:", error);
+                showToast('error', 'Error', 'Failed to link Nostr account');
+            }
+        }
+    };
+
+    const handleEmailLink = async () => {
+        if (!isEmailLinked) {
+            try {
+                const email = prompt("Please enter your email address:");
+                if (email) {
+                    const response = await fetch('/api/user/link-email', {
+                        method: 'POST',
+                        headers: {
+                            'Content-Type': 'application/json',
+                        },
+                        body: JSON.stringify({
+                            email,
+                            userId: session?.user?.id
+                        })
+                    });
+
+                    if (response.ok) {
+                        showToast('success', 'Success', 'Verification email sent');
+                        // The user will need to verify their email through the link sent
+                    } else {
+                        throw new Error('Failed to initiate email linking');
+                    }
+                }
+            } catch (error) {
+                console.error("Error linking email:", error);
+                showToast('error', 'Error', 'Failed to link email');
+            }
+        }
+    };
+
+    const MobileCard = () => (
+        <div className="bg-gray-800 rounded-xl p-6 flex flex-col items-start w-full h-[420px] border border-gray-700">
+            <h2 className="text-2xl font-bold mb-6 text-white">Link Accounts</h2>
+            
+            <div className="flex flex-col gap-4 w-full">
+                <GenericButton
+                    label={isGithubLinked ? "Github Linked" : "Link Github"}
+                    icon="pi pi-github"
+                    onClick={handleGithubLink}
+                    disabled={isGithubLinked}
+                    className={`w-full min-w-[240px] border-none ${
+                        isGithubLinked 
+                            ? "bg-gray-600 opacity-70 cursor-not-allowed" 
+                            : "bg-[#24292e] hover:bg-[#2f363d]"
+                    }`}
+                />
+
+                <GenericButton
+                    label={isNostrLinked ? "Nostr Linked" : "Link Nostr"}
+                    icon={<Image src="/images/nostr.png" width={20} height={20} alt="Nostr" className="mr-2" />}
+                    onClick={handleNostrLink}
+                    disabled={isNostrLinked}
+                    className={`w-full min-w-[240px] border-none flex items-center justify-center ${
+                        isNostrLinked 
+                            ? "bg-gray-600 opacity-70 cursor-not-allowed" 
+                            : "bg-[#6B4E71] hover:bg-[#6B4E71]/80"
+                    }`}
+                />
+
+                <GenericButton
+                    label={isEmailLinked ? "Email Linked" : "Link Email"}
+                    icon="pi pi-envelope"
+                    onClick={handleEmailLink}
+                    disabled={isEmailLinked}
+                    className={`w-full min-w-[240px] border-none ${
+                        isEmailLinked 
+                            ? "bg-gray-600 opacity-70 cursor-not-allowed" 
+                            : "bg-[#4A5568] hover:bg-[#4A5568]/80"
+                    }`}
+                />
+            </div>
+        </div>
+    );
+
+    const DesktopCard = () => (
+        <div className="bg-gray-800 rounded-xl p-6 flex flex-col items-start w-full max-w-[400px] mt-2 border border-gray-700">
+            <h2 className="text-2xl font-bold mb-6 text-white">Link Accounts</h2>
+            
+            <div className="flex flex-col gap-4 w-full">
+                <GenericButton
+                    label={isGithubLinked ? "Github Linked" : "Link Github"}
+                    icon="pi pi-github"
+                    onClick={handleGithubLink}
+                    disabled={isGithubLinked}
+                    className={`w-full border-none ${
+                        isGithubLinked 
+                            ? "bg-gray-600 opacity-70 cursor-not-allowed" 
+                            : "bg-[#24292e] hover:bg-[#2f363d]"
+                    }`}
+                />
+
+                <GenericButton
+                    label={isNostrLinked ? "Nostr Linked" : "Link Nostr"}
+                    icon={<Image src="/images/nostr.png" width={20} height={20} alt="Nostr" className="mr-2" />}
+                    onClick={handleNostrLink}
+                    disabled={isNostrLinked}
+                    className={`w-full border-none flex items-center justify-center ${
+                        isNostrLinked 
+                            ? "bg-gray-600 opacity-70 cursor-not-allowed" 
+                            : "bg-[#6B4E71] hover:bg-[#6B4E71]/80"
+                    }`}
+                />
+
+                <GenericButton
+                    label={isEmailLinked ? "Email Linked" : "Link Email"}
+                    icon="pi pi-envelope"
+                    onClick={handleEmailLink}
+                    disabled={isEmailLinked}
+                    className={`w-full border-none ${
+                        isEmailLinked 
+                            ? "bg-gray-600 opacity-70 cursor-not-allowed" 
+                            : "bg-[#4A5568] hover:bg-[#4A5568]/80"
+                    }`}
+                />
+            </div>
+        </div>
+    );
+
+    return windowWidth <= 1440 ? <MobileCard /> : <DesktopCard />;
+};
+
+export default LinkAccountsCard;
diff --git a/src/components/profile/UserProfile.js b/src/components/profile/UserProfile.js
index c35fc41..ed0aa4f 100644
--- a/src/components/profile/UserProfile.js
+++ b/src/components/profile/UserProfile.js
@@ -7,6 +7,7 @@ import ActivityContributionChart from "@/components/charts/ActivityContributionC
 import useCheckCourseProgress from "@/hooks/tracking/useCheckCourseProgress";
 import useWindowWidth from "@/hooks/useWindowWidth";
 import UserProgress from "@/components/profile/progress/UserProgress";
+import UserAccountLinking from "@/components/profile/UserAccountLinking";
 import UserProgressTable from '@/components/profile/DataTables/UserProgressTable';
 import UserPurchaseTable from '@/components/profile/DataTables/UserPurchaseTable';
 
@@ -40,6 +41,7 @@ const UserProfile = () => {
                 <div className="w-full flex flex-row max-lap:flex-col">
                     <div className="w-[22%] h-full max-lap:w-full">
                         {user && <UserProfileCard user={user} />}
+                        {user && <UserAccountLinking session={session} />}
                     </div>
 
                     <div className="w-[78%] flex flex-col justify-center mx-auto max-lap:w-full">
diff --git a/src/pages/api/auth/[...nextauth].js b/src/pages/api/auth/[...nextauth].js
index f69087d..2f99aff 100644
--- a/src/pages/api/auth/[...nextauth].js
+++ b/src/pages/api/auth/[...nextauth].js
@@ -274,6 +274,7 @@ export const authOptions = {
                     username: fullUser.username,
                     avatar: fullUser.avatar,
                     name: fullUser.name,
+                    email: fullUser.email,
                     userCourses: fullUser.userCourses,
                     userLessons: fullUser.userLessons,
                     purchased: fullUser.purchased,
diff --git a/src/pages/api/user/link-email.js b/src/pages/api/user/link-email.js
new file mode 100644
index 0000000..4928155
--- /dev/null
+++ b/src/pages/api/user/link-email.js
@@ -0,0 +1,84 @@
+import { getServerSession } from "next-auth/next";
+import { authOptions } from "../auth/[...nextauth]";
+import prisma from "@/db/prisma";
+import { createTransport } from "nodemailer";
+
+export default async function handler(req, res) {
+    if (req.method !== 'POST') {
+        return res.status(405).json({ error: 'Method not allowed' });
+    }
+
+    try {
+        const session = await getServerSession(req, res, authOptions);
+        if (!session) {
+            return res.status(401).json({ error: 'Unauthorized' });
+        }
+
+        const { email, userId } = req.body;
+
+        // Check if email is already in use
+        const existingUser = await prisma.user.findUnique({
+            where: { email }
+        });
+
+        if (existingUser) {
+            return res.status(400).json({ error: 'Email already in use' });
+        }
+
+        // Create verification token
+        const token = await prisma.verificationToken.create({
+            data: {
+                identifier: email,
+                token: `${Math.random().toString(36).substring(2, 15)}`,
+                expires: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
+            }
+        });
+
+        // Create email transport
+        const transport = createTransport({
+            host: process.env.EMAIL_SERVER_HOST,
+            port: process.env.EMAIL_SERVER_PORT,
+            auth: {
+                user: process.env.EMAIL_SERVER_USER,
+                pass: process.env.EMAIL_SERVER_PASSWORD
+            }
+        });
+
+        // Generate verification URL
+        const baseUrl = process.env.BACKEND_URL;
+        const verificationUrl = `${baseUrl}/api/user/verify-email?token=${token.token}&email=${email}&userId=${userId}`;
+
+        // Send verification email
+        await transport.sendMail({
+            to: email,
+            from: process.env.EMAIL_FROM,
+            subject: `Verify your email for PlebDevs`,
+            text: `Click this link to verify your email: ${verificationUrl}`,
+            html: `
+                <body>
+                    <div style="background: #f9f9f9; padding: 20px;">
+                        <div style="max-width: 600px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px;">
+                            <h2>Verify your email for PlebDevs</h2>
+                            <p>Click the button below to verify your email address:</p>
+                            <div style="text-align: center; margin: 30px 0;">
+                                <a href="${verificationUrl}"
+                                   style="background: #4A5568; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block;">
+                                    Verify Email
+                                </a>
+                            </div>
+                            <p style="color: #666; font-size: 14px;">
+                                If you didn't request this email, you can safely ignore it.
+                            </p>
+                        </div>
+                    </div>
+                </body>
+            `
+        });
+
+        // Don't update the user yet - wait for verification
+        res.status(200).json({ message: 'Verification email sent' });
+    } catch (error) {
+        console.error('Error linking email:', error);
+        res.status(500).json({ error: 'Failed to link email' });
+    }
+} 
\ No newline at end of file
diff --git a/src/pages/api/user/link-nostr.js b/src/pages/api/user/link-nostr.js
new file mode 100644
index 0000000..85ed26e
--- /dev/null
+++ b/src/pages/api/user/link-nostr.js
@@ -0,0 +1,32 @@
+import { getServerSession } from "next-auth/next";
+import { authOptions } from "../auth/[...nextauth]";
+import prisma from "@/db/prisma";
+
+export default async function handler(req, res) {
+    if (req.method !== 'POST') {
+        return res.status(405).json({ error: 'Method not allowed' });
+    }
+
+    try {
+        const session = await getServerSession(req, res, authOptions);
+        if (!session) {
+            return res.status(401).json({ error: 'Unauthorized' });
+        }
+
+        const { nostrPubkey, userId } = req.body;
+
+        // Update user with new Nostr pubkey
+        const updatedUser = await prisma.user.update({
+            where: { id: userId },
+            data: {
+                pubkey: nostrPubkey,
+                privkey: null // Remove privkey when linking to external Nostr account
+            }
+        });
+
+        res.status(200).json(updatedUser);
+    } catch (error) {
+        console.error('Error linking Nostr:', error);
+        res.status(500).json({ error: 'Failed to link Nostr account' });
+    }
+} 
\ No newline at end of file
diff --git a/src/pages/api/user/verify-email.js b/src/pages/api/user/verify-email.js
new file mode 100644
index 0000000..a1b3337
--- /dev/null
+++ b/src/pages/api/user/verify-email.js
@@ -0,0 +1,46 @@
+import prisma from "@/db/prisma";
+
+export default async function handler(req, res) {
+    if (req.method !== 'GET') {
+        return res.status(405).json({ error: 'Method not allowed' });
+    }
+
+    try {
+        const { token, email, userId } = req.query;
+
+        // Verify token
+        const verificationToken = await prisma.verificationToken.findFirst({
+            where: {
+                token,
+                identifier: email,
+                expires: { gt: new Date() }
+            }
+        });
+
+        if (!verificationToken) {
+            return res.status(400).json({ error: 'Invalid or expired token' });
+        }
+
+        // Update user with verified email
+        await prisma.user.update({
+            where: { id: userId },
+            data: { 
+                email,
+                emailVerified: new Date()
+            }
+        });
+
+        // Delete the used token using the token value
+        await prisma.verificationToken.delete({
+            where: { 
+                token: token // Changed from id to token
+            }
+        });
+
+        // Redirect to success page
+        res.redirect('/profile?emailVerified=true');
+    } catch (error) {
+        console.error('Error verifying email:', error);
+        res.redirect('/profile?error=VerificationFailed');
+    }
+} 
\ No newline at end of file