diff --git a/apps/web/src/features/profile/components/ProfileSocialLinksSection.stories.tsx b/apps/web/src/features/profile/components/ProfileSocialLinksSection.stories.tsx
new file mode 100644
index 000000000..3736508f5
--- /dev/null
+++ b/apps/web/src/features/profile/components/ProfileSocialLinksSection.stories.tsx
@@ -0,0 +1,37 @@
+import type { Meta, StoryObj } from '@storybook/react';
+import { ProfileSocialLinksSection } from './ProfileSocialLinksSection';
+
+const meta: Meta = {
+ component: ProfileSocialLinksSection,
+ tags: ['autodocs'],
+ parameters: {
+ layout: 'centered',
+ },
+};
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ socialLinks: {
+ twitter: 'https://twitter.com/veza_user',
+ youtube: 'https://youtube.com/@veza_channel',
+ instagram: 'https://instagram.com/veza_profile',
+ },
+ },
+};
+
+export const Empty: Story = {
+ args: {
+ socialLinks: null,
+ },
+};
+
+export const SingleLink: Story = {
+ args: {
+ socialLinks: {
+ website: 'https://veza.example.com',
+ },
+ },
+};
diff --git a/apps/web/src/features/profile/components/ProfileSocialLinksSection.tsx b/apps/web/src/features/profile/components/ProfileSocialLinksSection.tsx
new file mode 100644
index 000000000..dd55a51ac
--- /dev/null
+++ b/apps/web/src/features/profile/components/ProfileSocialLinksSection.tsx
@@ -0,0 +1,65 @@
+/**
+ * B2: Section Liens sociaux sur le profil public.
+ * Affiche Twitter, YouTube, Instagram, etc. avec icĂ´nes et URLs cliquables.
+ */
+import {
+ Twitter,
+ Instagram,
+ Facebook,
+ Youtube,
+ Link as LinkIcon,
+} from 'lucide-react';
+
+const SOCIAL_KEYS = [
+ { key: 'twitter', label: 'Twitter', Icon: Twitter },
+ { key: 'instagram', label: 'Instagram', Icon: Instagram },
+ { key: 'facebook', label: 'Facebook', Icon: Facebook },
+ { key: 'youtube', label: 'YouTube', Icon: Youtube },
+ { key: 'website', label: 'Website', Icon: LinkIcon },
+] as const;
+
+interface ProfileSocialLinksSectionProps {
+ socialLinks?: Record | null;
+}
+
+function isValidUrl(value: unknown): value is string {
+ if (typeof value !== 'string') return false;
+ if (!value.trim()) return false;
+ return value.startsWith('http://') || value.startsWith('https://');
+}
+
+export function ProfileSocialLinksSection({ socialLinks }: ProfileSocialLinksSectionProps) {
+ const entries = SOCIAL_KEYS.filter(
+ ({ key }) => socialLinks?.[key] != null && isValidUrl(socialLinks[key]),
+ ).map(({ key, label, Icon }) => ({
+ key,
+ label,
+ Icon,
+ href: String(socialLinks![key]),
+ }));
+
+ if (entries.length === 0) return null;
+
+ return (
+
+
+ Links
+
+
+ {entries.map(({ key, label, Icon, href }) => (
+
+
+ {label}
+
+ ))}
+
+
+ );
+}
diff --git a/apps/web/src/features/profile/pages/user-profile-page/UserProfilePageHeader.tsx b/apps/web/src/features/profile/pages/user-profile-page/UserProfilePageHeader.tsx
index 9ade4495e..d9eaef946 100644
--- a/apps/web/src/features/profile/pages/user-profile-page/UserProfilePageHeader.tsx
+++ b/apps/web/src/features/profile/pages/user-profile-page/UserProfilePageHeader.tsx
@@ -1,4 +1,5 @@
import { MapPin, Calendar, User, Music, Library, Users } from 'lucide-react';
+import { ProfileSocialLinksSection } from '../../components/ProfileSocialLinksSection';
import { Avatar } from '@/components/ui/avatar';
import { Card, CardContent } from '@/components/ui/card';
import { FollowButton } from '../../components/FollowButton';
@@ -108,6 +109,7 @@ export function UserProfilePageHeader({
)}
+
{/* Stats pills */}
diff --git a/apps/web/src/mocks/handlers-misc.ts b/apps/web/src/mocks/handlers-misc.ts
index 578563405..9488a5c58 100644
--- a/apps/web/src/mocks/handlers-misc.ts
+++ b/apps/web/src/mocks/handlers-misc.ts
@@ -224,6 +224,7 @@ export const handlersMisc = [
first_name: 'Story',
last_name: 'User',
avatar_url: `https://i.pravatar.cc/150?u=${params.username}`,
+ banner_url: params.username === 'demo' ? 'https://picsum.photos/1200/400?random=1' : null,
bio: 'Music enthusiast',
location: 'Paris, France',
birthdate: null,
@@ -231,6 +232,14 @@ export const handlersMisc = [
created_at: '2024-01-01T00:00:00Z',
followers_count: 42,
following_count: 10,
+ social_links:
+ params.username === 'demo'
+ ? {
+ twitter: 'https://twitter.com/veza_demo',
+ youtube: 'https://youtube.com/@veza_channel',
+ instagram: 'https://instagram.com/veza_profile',
+ }
+ : undefined,
},
});
}),