1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-10-11 17:06:21 +02:00

Compare commits

..

2 Commits

Author SHA1 Message Date
9c20844d89 fix: update Curriculum Vitae 2025-09-23 10:15:03 +02:00
eceeca8b69 fix: update Curriculum Vitae 2025-09-22 19:29:02 +02:00
8 changed files with 167 additions and 54 deletions

View File

@@ -74,6 +74,10 @@
@apply font-semibold italic; @apply font-semibold italic;
cursor: help; cursor: help;
} }
small {
font-size: 87%;
}
} }
body { body {
@@ -250,8 +254,8 @@ code .line::before {
padding: 10px 0; padding: 10px 0;
} }
.profile-pic img { .profile-pic img {
width: 80px; width: 100px;
height: 80px; height: 100px;
border-radius: 50%; border-radius: 50%;
vertical-align: middle; vertical-align: middle;
border: 0; border: 0;

View File

@@ -7,6 +7,7 @@
"en-US": "English", "en-US": "English",
"fr-FR": "French" "fr-FR": "French"
}, },
"fr-FR-main": "French (primary language)",
"loading": "Loading...", "loading": "Loading...",
"errors": { "errors": {
"error": "Error", "error": "Error",
@@ -24,7 +25,7 @@
"description": "I constantly wonder how to improve our present, to make our future better, particularly thanks to the advancements in computer science. <br></br> My priority is to craft intuitive user experiences (UX), that meet the needs of the users in the most efficient way possible.", "description": "I constantly wonder how to improve our present, to make our future better, particularly thanks to the advancements in computer science. <br></br> My priority is to craft intuitive user experiences (UX), that meet the needs of the users in the most efficient way possible.",
"title": "About" "title": "About"
}, },
"description": "Developer Full Stack • Student", "description": "Developer Full Stack • French Student",
"education": { "education": {
"cnam": { "cnam": {
"institution": "Conservatoire National des Arts et Métiers (CNAM), in Eckbolsheim - UIMM Alsace - ITII Alsace", "institution": "Conservatoire National des Arts et Métiers (CNAM), in Eckbolsheim - UIMM Alsace - ITII Alsace",
@@ -45,7 +46,7 @@
"2021-2022": { "2021-2022": {
"courses": { "courses": {
"java": "Object Oriented Development in Java", "java": "Object Oriented Development in Java",
"sql": "Relational database and SQL language", "sql": "<strong>Relational database and SQL language</strong>",
"systems-c": "Systems programming in C (Memory allocation, Pointers, Structures)", "systems-c": "Systems programming in C (Memory allocation, Pointers, Structures)",
"windows-forms": "Windows Forms (.NET Framework) Application Development in C#" "windows-forms": "Windows Forms (.NET Framework) Application Development in C#"
}, },
@@ -54,10 +55,10 @@
}, },
"2022-2023": { "2022-2023": {
"courses": { "courses": {
"clean-code": "Design Patterns and Principles (Maintainable and Reusable Code) in UML", "clean-code": "Design Patterns and Principles (<strong>Maintainable and Reusable Code</strong>) in UML",
"sql-security": "Securing database access and PL/SQL", "sql-security": "Securing database access and PL/SQL",
"systems-c": "Systems programming in C (Multi-Thread, Server/Client UDP/TCP)", "systems-c": "Systems programming in <strong>C (Multi-Thread, Server/Client UDP/TCP)</strong>",
"tests": "Development Quality and Automated Testing", "tests": "<strong>Development Quality and Automated Testing</strong>",
"web": "Web development with the Laravel framework in PHP" "web": "Web development with the Laravel framework in PHP"
}, },
"description": "2nd year", "description": "2nd year",
@@ -68,7 +69,7 @@
"ci-cd": "Continuous Integration/Deployment (CI/CD) and Docker", "ci-cd": "Continuous Integration/Deployment (CI/CD) and Docker",
"complexity-algorithms": "Theoretical and Practical Algorithmic Complexity in C++", "complexity-algorithms": "Theoretical and Practical Algorithmic Complexity in C++",
"no-sql": "NoSQL database (Redis, MongoDB, Cassandra)", "no-sql": "NoSQL database (Redis, MongoDB, Cassandra)",
"web": "Web development in Node.js and React.js" "web": "<strong>Web development in Node.js and React.js</strong>"
}, },
"description": "3rd year", "description": "3rd year",
"title": "2023 - 2024" "title": "2023 - 2024"
@@ -90,7 +91,7 @@
"interests": { "interests": {
"title": "Interests & hobbies", "title": "Interests & hobbies",
"fusey": "<link>Fusey (fusey.gg)</link>: website I'm developing for the game ARK that tracks the number of players connected to the servers in real time and has <strong>over ~5,000 visitors each month, ~100,000 members on Discord, and ~120,000 followers on X/Twitter</strong>.", "fusey": "<link>Fusey (fusey.gg)</link>: website I'm developing for the game ARK that tracks the number of players connected to the servers in real time and has <strong>over ~5,000 visitors each month, ~100,000 members on Discord, and ~120,000 followers on X/Twitter</strong>.",
"open-source": "Open-Source Enthusiast" "open-source": "<strong>Open-Source Contributor</strong>: publishing and <strong>contributing to npm packages</strong> and <link-github>GitHub</link-github> repositories, notably with <link-markdownlint>markdownlint-rule-relative-links</link-markdownlint> (around 20,000 downloads per week), contributions to <link-leon>Leon</link-leon>, an open-source personal assistant, among other projects."
}, },
"work": { "work": {
"ircad": { "ircad": {
@@ -98,12 +99,12 @@
"position": "Full Stack Web Developer Apprentice", "position": "Full Stack Web Developer Apprentice",
"tasks": { "tasks": {
"WebSurg": "Development of WebSurg, a virtual university dedicated to medical-surgical training, built with React.js/Next.js and API Platform with Symfony.", "WebSurg": "Development of WebSurg, a virtual university dedicated to medical-surgical training, built with React.js/Next.js and API Platform with Symfony.",
"Figma": "Integration of Figma mockups for WebSurg, website dedicated to medical-surgical training.", "Figma": "<strong>Integration of Figma mockups</strong> for WebSurg, website dedicated to medical-surgical training.",
"IRCAD-Core": "IRCAD Core, an internal tool for managing medical training sessions and their requirements (anatomical models, medications, staff training, etc.).", "IRCAD-Core": "IRCAD Core, an internal tool for managing medical training sessions and their requirements (anatomical models, medications, staff training, etc.).",
"feature-logs": "History and traceability of data modifications (what? who? when?) in IRCAD Core.", "feature-logs": "History and traceability of data modifications (what? who? when?) in IRCAD Core.",
"feature-permissions": "Advanced permissions system and OAuth2 authentication, with read, write, and delete access restricted for specific users of the IRCAD Core application.", "feature-permissions": "<strong>Advanced permissions system and OAuth2 authentication</strong>, with read, write, and delete access restricted for specific users of the IRCAD Core application.",
"feature-search": "Search engine with filters, sorting, and customizable display for each user of IRCAD Core.", "feature-search": "<strong>Search engine with filters, sorting, and customizable display</strong> for each user of IRCAD Core.",
"feature-architecture": "IRCAD Core project architecture in TypeScript Monorepo with Turborepo, automatic deployment (CI/CD) and self-hosted internally with Docker Compose." "feature-architecture": "IRCAD Core project architecture in <strong>TypeScript Monorepo</strong> with Turborepo, <strong>automatic deployment (CI/CD)</strong> and <strong>self-hosted internally with Docker Compose</strong>."
} }
}, },
"numerize": { "numerize": {
@@ -175,7 +176,10 @@
"others": "Others", "others": "Others",
"programming-languages": "Programming languages", "programming-languages": "Programming languages",
"software-tools": "Software and tools", "software-tools": "Software and tools",
"title": "Skills" "title": "Skills",
"rust-advent-of-code": " (as hobby and <link-aoc>Advent Of Code</link-aoc>)",
"go-basics": " (basics and fundamentals)"
} }
} }
} }

View File

@@ -7,6 +7,7 @@
"en-US": "Anglais", "en-US": "Anglais",
"fr-FR": "Français" "fr-FR": "Français"
}, },
"fr-FR-main": "Français (langue principale)",
"loading": "Chargement...", "loading": "Chargement...",
"errors": { "errors": {
"error": "Erreur", "error": "Erreur",
@@ -45,7 +46,7 @@
"2021-2022": { "2021-2022": {
"courses": { "courses": {
"java": "Développement Orientée Objet en Java", "java": "Développement Orientée Objet en Java",
"sql": "Base de données relationnelles et langage SQL", "sql": "<strong>Base de données relationnelles et langage SQL</strong>",
"systems-c": "Programmation systèmes en C (Allocation mémoire, Pointeurs, Structures)", "systems-c": "Programmation systèmes en C (Allocation mémoire, Pointeurs, Structures)",
"windows-forms": "Développement d'application Windows Forms (.NET Framework) en C#" "windows-forms": "Développement d'application Windows Forms (.NET Framework) en C#"
}, },
@@ -54,10 +55,10 @@
}, },
"2022-2023": { "2022-2023": {
"courses": { "courses": {
"clean-code": "Patrons et Principes de conceptions (Code maintenable et réutilisable) en UML", "clean-code": "Patrons et Principes de conceptions (<strong>Code maintenable et réutilisable</strong>) en UML",
"sql-security": "Sécurisation des accès à la base de données et PL/SQL", "sql-security": "Sécurisation des accès à la base de données et PL/SQL",
"systems-c": "Programmation systèmes en C (Multi-Thread, Serveur/Client UDP/TCP)", "systems-c": "Programmation systèmes en <strong>C (Multi-Thread, Serveur/Client UDP/TCP)</strong>",
"tests": "Qualité de développement et Tests automatisés", "tests": "<strong>Qualité de développement et Tests automatisés</strong>",
"web": "Développement Web avec le framework Laravel en PHP" "web": "Développement Web avec le framework Laravel en PHP"
}, },
"description": "2ème année", "description": "2ème année",
@@ -68,7 +69,7 @@
"ci-cd": "Intégration/Déploiement Continue et Docker", "ci-cd": "Intégration/Déploiement Continue et Docker",
"complexity-algorithms": "Complexité Algorithmique Théorique et Pratique en C++", "complexity-algorithms": "Complexité Algorithmique Théorique et Pratique en C++",
"no-sql": "Base de données NoSQL (Redis, MongoDB, Cassandra)", "no-sql": "Base de données NoSQL (Redis, MongoDB, Cassandra)",
"web": "Développement Web en Node.js et React.js" "web": "<strong>Développement Web en Node.js et React.js</strong>"
}, },
"description": "3ème année", "description": "3ème année",
"title": "2023 - 2024" "title": "2023 - 2024"
@@ -90,7 +91,7 @@
"interests": { "interests": {
"title": "Intérêts & loisirs", "title": "Intérêts & loisirs",
"fusey": "<link>Fusey (fusey.gg)</link> : site web que je développe pour le jeu ARK qui permet de suivre en temps réel le nombre de joueurs connectés sur les serveurs et a plus de <strong>~5 000 visiteurs chaque mois, ~100 000 membres sur Discord et ~120 000 followers sur X/Twitter</strong>.", "fusey": "<link>Fusey (fusey.gg)</link> : site web que je développe pour le jeu ARK qui permet de suivre en temps réel le nombre de joueurs connectés sur les serveurs et a plus de <strong>~5 000 visiteurs chaque mois, ~100 000 membres sur Discord et ~120 000 followers sur X/Twitter</strong>.",
"open-source": "Enthousiaste de l'Open-Source" "open-source": "<strong>Contributeur de l'Open-Source</strong> : publications et <strong>contributions sur npm</strong> et <link-github>GitHub</link-github> avec notamment <link-markdownlint>markdownlint-rule-relative-links</link-markdownlint> avec ~20 000 téléchargements par semaine, contributions à <link-leon>Leon</link-leon>, un assistant personnel open source, parmis d'autres projets."
}, },
"work": { "work": {
"ircad": { "ircad": {
@@ -98,12 +99,12 @@
"position": "Apprenti Développeur Web Full Stack", "position": "Apprenti Développeur Web Full Stack",
"tasks": { "tasks": {
"WebSurg": "Développement de WebSurg, une université virtuelle consacrée à la formation médico-chirurgicale, en React.js/Next.js et API Platform avec Symfony.", "WebSurg": "Développement de WebSurg, une université virtuelle consacrée à la formation médico-chirurgicale, en React.js/Next.js et API Platform avec Symfony.",
"Figma": "Intégration des maquettes Figma pour WebSurg, site web consacrée à la formation médico-chirurgicale.", "Figma": "<strong>Intégration des maquettes Figma</strong> pour WebSurg, site web consacrée à la formation médico-chirurgicale.",
"IRCAD-Core": "IRCAD Core, outil interne de gestion des formations médicales et leurs besoins (modèles anatomiques, médicaments, formations du personnel, etc.).", "IRCAD-Core": "IRCAD Core, outil interne de gestion des formations médicales et leurs besoins (modèles anatomiques, médicaments, formations du personnel, etc.).",
"feature-logs": "Historique et traçabilité des modifications des données (quoi? qui? quand?) dans IRCAD Core.", "feature-logs": "Historique et traçabilité des modifications des données (quoi? qui? quand?) dans IRCAD Core.",
"feature-permissions": "Système de permissions avancé et authentification OAuth2, avec accès en lecture, écriture et suppression restreint pour des utilisateurs spécifiques de l'application IRCAD Core.", "feature-permissions": "<strong>Système de permissions avancé</strong> et authentification OAuth2, avec accès en lecture, écriture et suppression restreint pour des utilisateurs spécifiques de l'application IRCAD Core.",
"feature-search": "Moteur de recherche avec filtres, tris et ordre d'affichage personnalisable pour IRCAD Core.", "feature-search": "<strong>Moteur de recherche avec filtres, tris et ordre d'affichage personnalisable</strong> pour IRCAD Core.",
"feature-architecture": "Architecture du projet IRCAD Core en Monorepo TypeScript avec Turborepo, déploiement automatique (CI/CD) et hébergé en interne avec Docker Compose." "feature-architecture": "Architecture du projet IRCAD Core en <strong>Monorepo TypeScript</strong> avec Turborepo, <strong>déploiement automatique (CI/CD)</strong> et <strong>hébergé en interne avec Docker Compose</strong>."
} }
}, },
"numerize": { "numerize": {
@@ -175,7 +176,10 @@
"others": "Autres", "others": "Autres",
"programming-languages": "Langages de programmation", "programming-languages": "Langages de programmation",
"software-tools": "Logiciels et outils", "software-tools": "Logiciels et outils",
"title": "Compétences" "title": "Compétences",
"rust-advent-of-code": " (pendant temps libre et <link-aoc>Advent Of Code</link-aoc>)",
"go-basics": " (bases et fondamentaux)"
} }
} }
} }

View File

@@ -33,7 +33,14 @@ export const CurriculumVitaeEducation: React.FC<
// t( // t(
// "curriculum-vitae.education.iut.years.2021-2022.courses.windows-forms", // "curriculum-vitae.education.iut.years.2021-2022.courses.windows-forms",
// ), // ),
t("curriculum-vitae.education.iut.years.2021-2022.courses.sql"), t.rich(
"curriculum-vitae.education.iut.years.2021-2022.courses.sql",
{
strong: (children) => {
return <strong>{children}</strong>
},
},
),
], ],
}, },
{ {
@@ -41,13 +48,30 @@ export const CurriculumVitaeEducation: React.FC<
title: t("curriculum-vitae.education.iut.years.2022-2023.title"), title: t("curriculum-vitae.education.iut.years.2022-2023.title"),
courses: [ courses: [
t("curriculum-vitae.education.iut.years.2022-2023.courses.web"), t("curriculum-vitae.education.iut.years.2022-2023.courses.web"),
t("curriculum-vitae.education.iut.years.2022-2023.courses.tests"), t.rich(
t( "curriculum-vitae.education.iut.years.2022-2023.courses.tests",
{
strong: (children) => {
return <strong>{children}</strong>
},
},
),
t.rich(
"curriculum-vitae.education.iut.years.2022-2023.courses.clean-code", "curriculum-vitae.education.iut.years.2022-2023.courses.clean-code",
{
strong: (children) => {
return <strong>{children}</strong>
},
},
), ),
// t("curriculum-vitae.education.iut.years.2022-2023.courses.sql-security"), // t("curriculum-vitae.education.iut.years.2022-2023.courses.sql-security"),
t( t.rich(
"curriculum-vitae.education.iut.years.2022-2023.courses.systems-c", "curriculum-vitae.education.iut.years.2022-2023.courses.systems-c",
{
strong: (children) => {
return <strong>{children}</strong>
},
},
), ),
], ],
}, },
@@ -55,7 +79,14 @@ export const CurriculumVitaeEducation: React.FC<
year: t("curriculum-vitae.education.iut.years.2023-2024.description"), year: t("curriculum-vitae.education.iut.years.2023-2024.description"),
title: t("curriculum-vitae.education.iut.years.2023-2024.title"), title: t("curriculum-vitae.education.iut.years.2023-2024.title"),
courses: [ courses: [
t("curriculum-vitae.education.iut.years.2023-2024.courses.web"), t.rich(
"curriculum-vitae.education.iut.years.2023-2024.courses.web",
{
strong: (children) => {
return <strong>{children}</strong>
},
},
),
t("curriculum-vitae.education.iut.years.2023-2024.courses.ci-cd"), t("curriculum-vitae.education.iut.years.2023-2024.courses.ci-cd"),
t( t(
"curriculum-vitae.education.iut.years.2023-2024.courses.complexity-algorithms", "curriculum-vitae.education.iut.years.2023-2024.courses.complexity-algorithms",
@@ -114,8 +145,8 @@ export const CurriculumVitaeEducation: React.FC<
paddingInlineStart: 20, paddingInlineStart: 20,
}} }}
> >
{courses.map((course) => { {courses.map((course, index) => {
return <li key={course}>{course}</li> return <li key={index}>{course}</li>
})} })}
</ul> </ul>
</li> </li>

View File

@@ -10,9 +10,44 @@ export const CurriculumVitaeInterests: React.FC<
const t = useTranslations() const t = useTranslations()
const interests = [ const interests = [
<strong key="open-source"> t.rich("curriculum-vitae.interests.open-source", {
{t("curriculum-vitae.interests.open-source")} strong: (children) => {
</strong>, return <strong>{children}</strong>
},
"link-github": (children) => {
return (
<a
href="https://github.com/theoludwig"
target="_blank"
className="font-semibold"
>
{children}
</a>
)
},
"link-leon": (children) => {
return (
<a
href="https://github.com/leon-ai/leon"
target="_blank"
className="font-semibold"
>
{children}
</a>
)
},
"link-markdownlint": (children) => {
return (
<a
href="https://www.npmjs.com/package/markdownlint-rule-relative-links"
target="_blank"
className="font-semibold"
>
{children}
</a>
)
},
}),
t.rich("curriculum-vitae.interests.fusey", { t.rich("curriculum-vitae.interests.fusey", {
link: (children) => { link: (children) => {
return ( return (

View File

@@ -21,16 +21,18 @@ export const CurriculumVitaeProfile: React.FC<
<Image <Image
className="mx-auto block" className="mx-auto block"
alt={t("meta.title")} alt={t("meta.title")}
src="/images/logo_background.webp" src="/images/logo.webp"
width={400} width={450}
height={400} height={450}
/> />
</div> </div>
<div className="name-and-profession text-center"> <div className="name-and-profession text-center">
<h1 className="h3 my-1!"> <h1 className="h3 my-1!">
<strong>{t("meta.title")}</strong> <strong>{t("meta.title")}</strong>
</h1> </h1>
<h2 className="text-muted h5">{t("curriculum-vitae.description")}</h2> <h2 className="text-muted h5 font-semibold">
{t("curriculum-vitae.description")}
</h2>
<h2 className="text-muted h5"> <h2 className="text-muted h5">
<BirthDate /> <BirthDate />
</h2> </h2>
@@ -39,17 +41,13 @@ export const CurriculumVitaeProfile: React.FC<
</div> </div>
<div className="flex justify-center"> <div className="flex justify-center">
<div className="relative px-3"> <div className="relative px-3">
<strong className="info"> <strong className="info font-bold">
<a className="" href="mailto:contact@theoludwig.fr"> <a href="mailto:contact@theoludwig.fr">contact@theoludwig.fr</a>
contact@theoludwig.fr
</a>
</strong> </strong>
</div> </div>
<div className="detail"> <div className="detail">
<strong className="info"> <strong className="info font-bold">
<Link className="" href="/"> <Link href="/">https://theoludwig.fr</Link>
https://theoludwig.fr
</Link>
</strong> </strong>
</div> </div>
</div> </div>

View File

@@ -23,7 +23,11 @@ export const CurriculumVitaeSkills: React.FC<
}), }),
{ {
category: "others", category: "others",
skillNames: [t("locales.en-US"), t("home.skills.driving-license")], skillNames: [
t("fr-FR-main"),
t("locales.en-US"),
t("home.skills.driving-license"),
],
}, },
] as const ] as const
@@ -45,6 +49,23 @@ export const CurriculumVitaeSkills: React.FC<
return ( return (
<p key={skillName} className="label label-keyword"> <p key={skillName} className="label label-keyword">
{skillName} {skillName}
{skillName === "Rust"
? t.rich("home.skills.rust-advent-of-code", {
"link-aoc": (children) => {
return (
<a
href="https://github.com/theoludwig/advent_of_code"
target="_blank"
className="no-underline"
>
{children}
</a>
)
},
})
: skillName === "Go"
? t("home.skills.go-basics")
: ""}
</p> </p>
) )
})} })}

View File

@@ -17,12 +17,28 @@ export const CurriculumVitaeWork: React.FC<CurriculumVitaeWorkProps> = () => {
duration: t("curriculum-vitae.work.ircad.duration"), duration: t("curriculum-vitae.work.ircad.duration"),
tasks: [ tasks: [
// t("curriculum-vitae.work.ircad.tasks.WebSurg"), // t("curriculum-vitae.work.ircad.tasks.WebSurg"),
t("curriculum-vitae.work.ircad.tasks.Figma"), t.rich("curriculum-vitae.work.ircad.tasks.Figma", {
strong: (children) => {
return <strong>{children}</strong>
},
}),
t("curriculum-vitae.work.ircad.tasks.IRCAD-Core"), t("curriculum-vitae.work.ircad.tasks.IRCAD-Core"),
t("curriculum-vitae.work.ircad.tasks.feature-logs"), t("curriculum-vitae.work.ircad.tasks.feature-logs"),
t("curriculum-vitae.work.ircad.tasks.feature-permissions"), t.rich("curriculum-vitae.work.ircad.tasks.feature-permissions", {
t("curriculum-vitae.work.ircad.tasks.feature-search"), strong: (children) => {
t("curriculum-vitae.work.ircad.tasks.feature-architecture"), return <strong>{children}</strong>
},
}),
t.rich("curriculum-vitae.work.ircad.tasks.feature-search", {
strong: (children) => {
return <strong>{children}</strong>
},
}),
t.rich("curriculum-vitae.work.ircad.tasks.feature-architecture", {
strong: (children) => {
return <strong>{children}</strong>
},
}),
], ],
}, },
{ {
@@ -74,8 +90,8 @@ export const CurriculumVitaeWork: React.FC<CurriculumVitaeWorkProps> = () => {
}} }}
className="space-y-1" className="space-y-1"
> >
{workExperience.tasks.map((task) => { {workExperience.tasks.map((task, index) => {
return <li key={task}>{task}</li> return <li key={index}>{task}</li>
})} })}
</ul> </ul>
) : ( ) : (