Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"protobufjs": "^7.5.7",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"sonner": "^2.0.7",
"tailwindcss": "^4.2.1"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function RootLayout({
<meta name="theme-color" content="#000000" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, interactive-widget=resizes-content"
/>
</head>
<body className="h-dvh w-screen monospace">
Expand Down
Binary file added src/assets/Pro-Hacked.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/gpg-fingerprint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"fingerprint": "3C79 D440 DC6D 7167 36A8 BD41 70E8 63D2 6824 D0F5"
}
117 changes: 116 additions & 1 deletion src/components/about-me/AboutMe.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,118 @@
'use client';

import {
Avatar,
AvatarFallback,
AvatarImage,
Badge,
Button,
Typography,
} from '@nipsys/lsd';
import {
BriefcaseIcon,
CopyIcon,
LockKeyIcon,
MapPinIcon,
TargetIcon,
} from '@phosphor-icons/react';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { toast } from 'sonner';
import gpgFingerprint from '@/assets/gpg-fingerprint.json';
import profileImage from '@/assets/Pro-Hacked.png';

const GPG_FINGERPRINT = gpgFingerprint.fingerprint;

export default function AboutMe() {
return <div>about me / todo</div>;
const t = useTranslations('AboutMe');
const [copied, setCopied] = useState(false);

const quickInfo = [
{ icon: MapPinIcon, textKey: 'badges.location' },
{ icon: BriefcaseIcon, textKey: 'badges.experience' },
{ icon: LockKeyIcon, textKey: 'badges.focus' },
{ icon: TargetIcon, textKey: 'badges.goal' },
];

const handleCopy = async () => {
await navigator.clipboard.writeText(GPG_FINGERPRINT);
setCopied(true);
toast.success(t('copyToast'));
setTimeout(() => setCopied(false), 200);
};

return (
<div className="flex flex-col gap-(--lsd-spacing-large) py-(--lsd-spacing-small)">
<div className="flex gap-(--lsd-spacing-large) items-center">
<Avatar className="size-32!">
<AvatarImage src={profileImage.src} alt="Xav" />
<AvatarFallback>X</AvatarFallback>
</Avatar>

<div className="flex flex-col gap-(--lsd-spacing-base)">
<div className="flex flex-col gap-(--lsd-spacing-smallest)">
<Typography variant="h2">{t('name')}</Typography>
<Typography variant="body2" color="secondary">
{t('tagline')}
</Typography>
</div>

<div className="flex flex-wrap gap-(--lsd-spacing-smaller)">
{quickInfo.map(({ icon: Icon, textKey }) => (
<Badge
key={textKey}
variant="outlined"
size="sm"
className="leading-1"
icon={<Icon weight="duotone" size={14} />}
>
{t(textKey)}
</Badge>
))}
</div>
</div>
</div>

<div className="flex flex-col gap-(--lsd-spacing-base)">
<Typography variant="body1">{t('bio.intro1')}</Typography>
<Typography variant="body1">{t('bio.intro2')}</Typography>

<Typography variant="body2" color="secondary">
{t('bio.para1')}
</Typography>

<Typography variant="body2" color="secondary">
{t('bio.para2')}
</Typography>

<Typography variant="body2" color="secondary">
{t('bio.para3')}
</Typography>

<Typography variant="body2" color="secondary">
{t('bio.para4')}
</Typography>

<Typography variant="body2" color="secondary">
{t('bio.para5')}
</Typography>

<Typography variant="body2">{t('bio.current')}</Typography>
</div>

<div className="flex flex-col gap-(--lsd-spacing-smallest)">
<div className="flex items-center gap-(--lsd-spacing-smaller)">
<Typography variant="label1" color="secondary">
{t('gpgLabel')}
</Typography>
<Button variant="ghost" size="square-sm" onClick={handleCopy}>
<CopyIcon weight={copied ? 'fill' : 'duotone'} size={14} />
</Button>
</div>
<Typography variant="body3" color="secondary">
{GPG_FINGERPRINT}
</Typography>
</div>
</div>
);
}
31 changes: 30 additions & 1 deletion src/components/layout/MainWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,40 @@
'use client';

import { Toaster } from 'sonner';
import Sidenav from './Sidenav';

export default function MainWrapper({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return <Sidenav>{children}</Sidenav>;
return (
<>
<Sidenav>{children}</Sidenav>
{/* TODO: Fix toaster export in @nipsys/lsd package to avoid doing all of this */}
<Toaster
className="lsd:toaster lsd:group"
richColors
style={
{
'--normal-bg': 'var(--lsd-foreground)',
'--normal-text': 'var(--lsd-text-neutral)',
'--normal-border': 'var(--lsd-border)',
'--success-bg': 'var(--lsd-foreground)',
'--success-border': 'var(--lsd-success)',
'--success-text': 'var(--lsd-text-success)',
'--error-bg': 'var(--lsd-foreground)',
'--error-border': 'var(--lsd-destructive)',
'--error-text': 'var(--lsd-text-destructive)',
'--warning-bg': 'var(--lsd-foreground)',
'--warning-border': 'var(--lsd-warning)',
'--warning-text': 'var(--lsd-text-warning)',
'--info-bg': 'var(--lsd-foreground)',
'--info-border': 'var(--lsd-info)',
'--info-text': 'var(--lsd-text-info)',
} as React.CSSProperties
}
/>
</>
);
}
24 changes: 23 additions & 1 deletion src/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,33 @@
"switchToDarkMode": "Switch to dark mode"
},
"Sidebar": {
"p2pMessaging": "P2P Messaging",
"p2pMessaging": "Logos Delivery",
"aboutSite": "About this site",
"checkOutCode": "Check out its code",
"andItsUI": "and its UI!"
},
"AboutMe": {
"name": "Xav [nipsysdev]",
"tagline": "cypherpunk / builder / digital sovereignty advocate",
"badges": {
"location": "France → Canada → Switzerland",
"experience": "10+ yrs building for the web",
"focus": "Privacy, Decentralization, FLOSS",
"goal": "Aspiring penetration tester"
},
"bio": {
"intro1": "My name is Xavier Saliniere — a cypherpunk at heart, building and breaking things for a freer internet.",
"intro2": "I'm driven by a simple question: what if the internet actually worked for the people using it?",
"para1": "I started coding at 14, hacking together PSP homebrews in my bedroom. What began as teenage curiosity evolved into a decade-long journey through the web development world — from dropping out of school at 21 to join a startup, to building enterprise security platforms at Bell Canada's Operations Center.",
"para2": "But the real story isn't in the job titles. It's in the late nights experimenting and learning about alternative systems and technologies.",
"para3": "Diving into Linux, the FLOSS philosophy, self-hosting various services, and gradually extricating myself from the walled gardens of Big Tech. The more I learned about centralized systems and the organizations behind them, the more I developed a passion for their alternatives.",
"para4": "After 4 years in Canada, I'm now heading to Switzerland — bringing my passion for decentralized, permissionless, and privacy-preserving technologies with me.",
"para5": "Career-wise, following 10 years in web development, I'm working on shifting towards cybersecurity, with a strong interest in penetration testing.",
"current": "Currently focused on: building AnyMaps and its decentralized infrastructure, contributing to the ecosystems powering my work, getting into cybersecurity, and breaking things to see how they work :)"
},
"gpgLabel": "GPG Fingerprint",
"copyToast": "GPG fingerprint copied to clipboard"
},
"Terminal": {
"unknownCmdErr": "command not recognized",
"noMatch": "no match",
Expand Down
24 changes: 23 additions & 1 deletion src/i18n/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,33 @@
"switchToDarkMode": "Passer au mode nuit"
},
"Sidebar": {
"p2pMessaging": "Messagerie P2P",
"p2pMessaging": "Logos Delivery",
"aboutSite": "À propos de ce site",
"checkOutCode": "Voir son code",
"andItsUI": "et sa lib UI !"
},
"AboutMe": {
"name": "Xav [nipsysdev]",
"tagline": "cypherpunk / développeur / défenseur de la souveraineté numérique",
"badges": {
"location": "France → Canada → Suisse",
"experience": "10+ ans à construire pour le web",
"focus": "Confidentialité, Décentralisation, FLOSS",
"goal": "Pentester en devenir"
},
"bio": {
"intro1": "Je m'appelle Xavier Saliniere — cypherpunk dans l'âme, je développe et j'expérimente pour un internet plus libre.",
"intro2": "Une simple question me motive : et si l'internet pouvait réellement être au service de ceux qui l'utilisent ?",
"para1": "J'ai commencé à coder à 14 ans, en bricolant des homebrews PSP dans ma chambre. Ce qui a commencé comme une curiosité d'adolescent s'est transformé en un voyage d'une décennie à travers le monde du développement web — depuis l'abandon de mes études à 21 ans pour rejoindre une startup, jusqu'à développer des plateformes de sécurité d'entreprise au Centre des Opérations de Bell Canada.",
"para2": "Mais la vraie histoire n'est pas dans les postes que j'ai occupé. Elle est dans les nuits blanches à expérimenter et à découvrir des systèmes et technologies alternatifs.",
"para3": "Plonger dans Linux, la philosophie FLOSS, l'auto-hébergement de divers services, et progressivement m'extraire des \"walled gardens\" de la Big Tech. Plus j'apprenais sur les systèmes centralisés et les organisations qui les contrôlent, plus je suis devenu passioné par leurs alternatives.",
"para4": "Après 4 ans au Canada, je m'installe maintenant en Suisse — emportant avec moi ma passion pour les technologies décentralisées, \"permissionless\" et respectueuses de la vie privée.",
"para5": "Côté carrière, après 10 ans en développement web, je me forme pour transitionner vers la cybersécurité, avec un fort intérêt pour le pentesting.",
"current": "Ce que je fais actuellement : Développement d'AnyMaps et de son infrastructure décentralisée, contribution aux écosystèmes qui alimentent mes projets, formation en cybersécurité, et mes expérimentations routinières :)"
},
"gpgLabel": "Empreinte GPG",
"copyToast": "Empreinte GPG copiée dans le presse-papier"
},
"Terminal": {
"unknownCmdErr": "commande non reconnue",
"noMatch": "aucune correspondance",
Expand Down
Loading