Compare commits

..

No commits in common. "3e4a632adc13b331b86e4f4f97f63022febbf110" and "bf26caded305033b9eb59a9b28f26807a37b3809" have entirely different histories.

27 changed files with 147 additions and 304 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View file

@ -10,7 +10,7 @@ const avatarImages = import.meta.glob<{ default: ImageMetadata }>(
interface Props { interface Props {
author: string; author: string;
authorRole: string; authorRole: string;
company?: string; company: string;
text: string; text: string;
avatar?: string; avatar?: string;
url?: string; url?: string;

View file

@ -0,0 +1,23 @@
---
interface Props {
title: string;
description: string;
href: string;
icon: string;
}
const { title, description, href, icon } = Astro.props;
---
<a
href={href}
class="facet-card group block rounded-2xl bg-white/[0.06] border border-white/[0.1] p-6 hover:bg-white/[0.12] hover:border-white/[0.2] hover:scale-[1.02] transition-all duration-300 no-underline"
>
<div class="text-3xl mb-3 opacity-80 group-hover:opacity-100 group-hover:scale-110 transition-all duration-300 inline-block">{icon}</div>
<h3 class="text-lg font-bold text-white mb-2 group-hover:text-purple-200 transition-colors">
{title}
</h3>
<p class="text-sm text-white/55 leading-relaxed group-hover:text-white/70 transition-colors">
{description}
</p>
</a>

View file

@ -10,7 +10,7 @@ const avatarImages = import.meta.glob<{ default: ImageMetadata }>(
interface Props { interface Props {
author: string; author: string;
authorRole: string; authorRole: string;
company?: string; company: string;
text: string; text: string;
date: Date; date: Date;
avatar?: string; avatar?: string;

View file

@ -75,7 +75,7 @@ const recommendationsCollection = defineCollection({
schema: z.object({ schema: z.object({
author: z.string(), author: z.string(),
authorRole: z.string(), authorRole: z.string(),
company: z.string().optional(), company: z.string(),
avatar: z.string().optional(), avatar: z.string().optional(),
url: z.string().url().optional(), url: z.string().url().optional(),
date: z.date(), date: z.date(),

View file

@ -2,7 +2,6 @@
author: "Antoine Wolff" author: "Antoine Wolff"
authorRole: "Développeur, graphiste et chef de projet" authorRole: "Développeur, graphiste et chef de projet"
company: "LeCollectif" company: "LeCollectif"
avatar: antoine-wolff.png
url: https://www.linkedin.com/in/wolffantoine url: https://www.linkedin.com/in/wolffantoine
date: 2020-12-07 date: 2020-12-07
lang: "fr" lang: "fr"

View file

@ -1,6 +1,6 @@
--- ---
author: "Benoit Sarda" author: "Benoit Sarda"
authorRole: "Sr Solution Architect" authorRole: "Sr Solution Architect, Manuf"
company: "Amazon Web Services (AWS)" company: "Amazon Web Services (AWS)"
avatar: benoit-sarda.jpg avatar: benoit-sarda.jpg
url: https://www.linkedin.com/in/benoitsarda url: https://www.linkedin.com/in/benoitsarda

View file

@ -2,7 +2,6 @@
author: "Bouchra Ghaoui" author: "Bouchra Ghaoui"
authorRole: "Senior Engagement Manager" authorRole: "Senior Engagement Manager"
company: "Capgemini" company: "Capgemini"
avatar: bouchra-ghaoui.jpg
url: https://www.linkedin.com/in/bouchra-ghaoui-46509a10 url: https://www.linkedin.com/in/bouchra-ghaoui-46509a10
date: 2011-12-09 date: 2011-12-09
lang: "fr" lang: "fr"

View file

@ -1,10 +0,0 @@
---
author: "John Samson"
authorRole: "Président"
company: "DisMoi SAS"
avatar: john-samson.png
url: https://www.malt.fr/profile/jalilarfaoui
date: 2022-06-17
lang: "fr"
---
Jalil a su trouver la bonne architecture à notre projet à 5 pattes, il est réactif en cas d'urgence, et s'engage au-delà de son rôle de développeur, très apprécié par les autres membres de l'équipe.

View file

@ -1,9 +0,0 @@
---
author: "Thomas Kientz"
authorRole: "Expert Vue.js | Nuxt"
avatar: thomas-kientz.jpg
url: https://www.malt.fr/profile/jalilarfaoui
date: 2022-06-17
lang: "fr"
---
Jalil est un développeur et mentor hors pair. Le développement logiciel est pour lui un art dont il adore partager sa passion. Je consulte Jalil régulièrement pour avoir son regard expérimenté tant le choix d'une nouvelle techno que pour des reviews de code. C'est un véritable atout à avoir dans son équipe, je le recommande fortement.

View file

@ -1,9 +0,0 @@
---
author: "Thomas Morellato"
authorRole: "UI / UX designer"
avatar: thomas-morellato.webp
url: https://www.malt.fr/profile/jalilarfaoui
date: 2022-06-17
lang: "fr"
---
Jalil est un professionnel engagé et très compétent. Son relationnel et sa vision du projet en font un élément indispensable au sein d'une équipe. Je recommande vivement son profil.

View file

@ -1,11 +0,0 @@
---
author: "Vadim Toropoff"
authorRole: "Dirigeant"
company: "Event Finder"
url: https://www.malt.fr/profile/jalilarfaoui
date: 2015-10-08
lang: "fr"
---
Jalil nous a apporté conseil et expertise pour le lancement de tous nos projets technos pour notre agence événementielle. Il a réussi à comprendre et à mettre en place des systèmes complexes et surtout sur mesure.
Patient, à l'écoute, je conseille les yeux fermés de travailler avec lui.

View file

@ -2,7 +2,6 @@
author: "Vanessa Boissard" author: "Vanessa Boissard"
authorRole: "Psychologue sociale" authorRole: "Psychologue sociale"
company: "AlterAlliance" company: "AlterAlliance"
avatar: vanessa-boissard.jpg
url: https://www.linkedin.com/in/vanessaboissard url: https://www.linkedin.com/in/vanessaboissard
date: 2011-12-05 date: 2011-12-05
lang: "fr" lang: "fr"

View file

@ -3,11 +3,9 @@ import { getCollection } from "astro:content";
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import Layout from "../../../layouts/main.astro"; import Layout from "../../../layouts/main.astro";
import Link from "../../../components/Link.astro"; import Link from "../../../components/Link.astro";
import NavigationCard from "../../../components/code/NavigationCard.astro";
import FeaturedRecommendation from "../../../components/code/FeaturedRecommendation.astro"; import FeaturedRecommendation from "../../../components/code/FeaturedRecommendation.astro";
import ProjectCard from "../../../components/code/ProjectCard.astro";
import SkillBadge from "../../../components/code/SkillBadge.astro";
import logoTiqa from "../../../assets/images/logo-tiqa-blanc.png"; import logoTiqa from "../../../assets/images/logo-tiqa-blanc.png";
import skillsData from "../../../data/skills.json";
const locale = "ar"; const locale = "ar";
@ -15,15 +13,7 @@ const experiences = (await getCollection("experiences"))
.filter((e) => e.data.lang === locale && !e.data.draft) .filter((e) => e.data.lang === locale && !e.data.draft)
.sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1)); .sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1));
const recentExperiences = experiences.slice(0, 4); const currentPosition = experiences.find((e) => !e.data.endDate);
const projects = (await getCollection("projects"))
.filter((p) => p.data.lang === locale && !p.data.draft && p.data.category === "dev")
.sort((a, b) => {
if (a.data.featured !== b.data.featured) return a.data.featured ? -1 : 1;
return b.data.date.getTime() - a.data.date.getTime();
})
.slice(0, 3);
const recommendations = (await getCollection("recommendations")) const recommendations = (await getCollection("recommendations"))
.sort((a, b) => b.data.date.getTime() - a.data.date.getTime()) .sort((a, b) => b.data.date.getTime() - a.data.date.getTime())
@ -33,14 +23,6 @@ const recommendationTexts = recommendations.map((rec) => ({
...rec, ...rec,
text: rec.body || '', text: rec.body || '',
})); }));
const topSkills = skillsData.categories.slice(0, 3);
function formatMonth(dateStr: string) {
const [year, month] = dateStr.split('-');
return new Date(parseInt(year), parseInt(month) - 1)
.toLocaleDateString('ar-SA', { year: 'numeric', month: 'short' });
}
--- ---
<Layout <Layout
@ -62,56 +44,47 @@ function formatMonth(dateStr: string) {
</p> </p>
</div> </div>
<div class="mb-12"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-12">
<div class="flex items-center justify-between mb-5"> <NavigationCard
<h2 class="text-2xl font-bold text-white">المسار</h2> title="المسار"
<a href="/ar/برمجة/مسار" class="text-sm text-purple-200 hover:text-white transition-colors">&larr; عرض الكل</a> description="الجدول الزمني لخبراتي المهنية منذ 2002."
</div> href="/ar/برمجة/مسار"
<div class="space-y-3"> icon="📋"
{recentExperiences.map((exp) => { />
const isOngoing = !exp.data.endDate; <NavigationCard
const start = formatMonth(exp.data.startDate); title="المشاريع"
const end = exp.data.endDate ? formatMonth(exp.data.endDate) : 'الحالي'; description="برمجيات مفتوحة المصدر ومشاريع شخصية."
return ( href="/ar/برمجة/مشاريع"
<div class="facet-card rounded-xl bg-white/[0.06] border border-white/[0.1] p-4 hover:bg-white/[0.1] transition-colors"> icon="💻"
<div class="flex items-start justify-between gap-4"> />
<div class="min-w-0"> <NavigationCard
<p class="font-semibold text-white text-sm truncate">{exp.data.role}</p> title="المهارات"
<p class="text-xs text-white/50 mt-0.5"> description="لغات، أطر عمل، ممارسات وأدوات."
{exp.data.companyUrl ? ( href="/ar/برمجة/مهارات"
<a href={exp.data.companyUrl} target="_blank" rel="noopener noreferrer" class="text-purple-200 hover:text-white transition-colors">{exp.data.company}</a> icon="🛠"
) : exp.data.company} />
{exp.data.location && ` · ${exp.data.location}`} <NavigationCard
</p> title="التوصيات"
</div> description="ما يقوله الأشخاص الذين عملت معهم."
<span class:list={["text-xs whitespace-nowrap flex-shrink-0", isOngoing ? "text-purple-200 font-semibold" : "text-white/40"]}> href="/ar/برمجة/توصيات"
{start} — {end} icon="💬"
</span> />
</div>
</div>
);
})}
</div>
</div> </div>
<div class="mb-12"> {currentPosition && (
<div class="flex items-center justify-between mb-5"> <div class="facet-card rounded-2xl bg-gradient-to-r from-purple-500/20 to-indigo-500/20 border border-purple-300/15 p-6 mb-10">
<h2 class="text-2xl font-bold text-white">المشاريع</h2> <p class="text-xs font-semibold text-purple-200 uppercase tracking-wider mb-2">المنصب الحالي</p>
<a href="/ar/برمجة/مشاريع" class="text-sm text-purple-200 hover:text-white transition-colors">&larr; عرض الكل</a> <p class="text-xl font-bold text-white">{currentPosition.data.role}</p>
</div> <p class="text-sm text-white/60 mt-1">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> {currentPosition.data.companyUrl ? (
{projects.map((project) => ( <a href={currentPosition.data.companyUrl} target="_blank" rel="noopener noreferrer" class="text-purple-200 hover:text-white transition-colors">{currentPosition.data.company}</a>
<ProjectCard ) : (
title={project.data.title} currentPosition.data.company
description={project.data.description} )}
technologies={project.data.technologies} {currentPosition.data.location && ` · ${currentPosition.data.location}`}
url={project.data.url} </p>
github={project.data.github}
featured={project.data.featured}
/>
))}
</div>
</div> </div>
)}
{recommendationTexts.length > 0 && ( {recommendationTexts.length > 0 && (
<div class="mb-12"> <div class="mb-12">
@ -134,25 +107,6 @@ function formatMonth(dateStr: string) {
</div> </div>
)} )}
<div class="mb-12">
<div class="flex items-center justify-between mb-5">
<h2 class="text-2xl font-bold text-white">المهارات</h2>
<a href="/ar/برمجة/مهارات" class="text-sm text-purple-200 hover:text-white transition-colors">&larr; عرض الكل</a>
</div>
<div class="space-y-4">
{topSkills.map((category) => (
<div>
<p class="text-xs font-semibold text-white/40 uppercase tracking-wider mb-2">{category.name[locale as keyof typeof category.name]}</p>
<div class="flex flex-wrap gap-1.5">
{category.skills.map((skill) => (
<SkillBadge name={skill} />
))}
</div>
</div>
))}
</div>
</div>
<h2 class="text-2xl font-bold text-white mb-5">القيم والمنهج</h2> <h2 class="text-2xl font-bold text-white mb-5">القيم والمنهج</h2>
<div class="facet-card rounded-2xl bg-white/[0.04] border border-white/[0.08] p-6 mb-10"> <div class="facet-card rounded-2xl bg-white/[0.04] border border-white/[0.08] p-6 mb-10">
<ul class="space-y-3 text-white/70"> <ul class="space-y-3 text-white/70">

View file

@ -3,11 +3,9 @@ import { getCollection } from "astro:content";
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import Layout from "../../layouts/main.astro"; import Layout from "../../layouts/main.astro";
import Link from "../../components/Link.astro"; import Link from "../../components/Link.astro";
import NavigationCard from "../../components/code/NavigationCard.astro";
import FeaturedRecommendation from "../../components/code/FeaturedRecommendation.astro"; import FeaturedRecommendation from "../../components/code/FeaturedRecommendation.astro";
import ProjectCard from "../../components/code/ProjectCard.astro";
import SkillBadge from "../../components/code/SkillBadge.astro";
import logoTiqa from "../../assets/images/logo-tiqa-blanc.png"; import logoTiqa from "../../assets/images/logo-tiqa-blanc.png";
import skillsData from "../../data/skills.json";
const locale = "fr"; const locale = "fr";
@ -15,15 +13,7 @@ const experiences = (await getCollection("experiences"))
.filter((e) => e.data.lang === locale && !e.data.draft) .filter((e) => e.data.lang === locale && !e.data.draft)
.sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1)); .sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1));
const recentExperiences = experiences.slice(0, 4); const currentPosition = experiences.find((e) => !e.data.endDate);
const projects = (await getCollection("projects"))
.filter((p) => p.data.lang === locale && !p.data.draft && p.data.category === "dev")
.sort((a, b) => {
if (a.data.featured !== b.data.featured) return a.data.featured ? -1 : 1;
return b.data.date.getTime() - a.data.date.getTime();
})
.slice(0, 3);
const recommendations = (await getCollection("recommendations")) const recommendations = (await getCollection("recommendations"))
.sort((a, b) => b.data.date.getTime() - a.data.date.getTime()) .sort((a, b) => b.data.date.getTime() - a.data.date.getTime())
@ -33,14 +23,6 @@ const recommendationTexts = recommendations.map((rec) => ({
...rec, ...rec,
text: rec.body || '', text: rec.body || '',
})); }));
const topSkills = skillsData.categories.slice(0, 3);
function formatMonth(dateStr: string) {
const [year, month] = dateStr.split('-');
return new Date(parseInt(year), parseInt(month) - 1)
.toLocaleDateString('fr-FR', { year: 'numeric', month: 'short' });
}
--- ---
<Layout <Layout
@ -62,56 +44,47 @@ function formatMonth(dateStr: string) {
</p> </p>
</div> </div>
<div class="mb-12"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-12">
<div class="flex items-center justify-between mb-5"> <NavigationCard
<h2 class="text-2xl font-bold text-white">Parcours</h2> title="Parcours"
<a href="/code/parcours" class="text-sm text-purple-200 hover:text-white transition-colors">Voir tout &rarr;</a> description="Timeline de mes expériences professionnelles depuis 2002."
</div> href="/code/parcours"
<div class="space-y-3"> icon="📋"
{recentExperiences.map((exp) => { />
const isOngoing = !exp.data.endDate; <NavigationCard
const start = formatMonth(exp.data.startDate); title="Projets"
const end = exp.data.endDate ? formatMonth(exp.data.endDate) : 'Présent'; description="Logiciels open source et projets personnels."
return ( href="/code/projets"
<div class="facet-card rounded-xl bg-white/[0.06] border border-white/[0.1] p-4 hover:bg-white/[0.1] transition-colors"> icon="💻"
<div class="flex items-start justify-between gap-4"> />
<div class="min-w-0"> <NavigationCard
<p class="font-semibold text-white text-sm truncate">{exp.data.role}</p> title="Compétences"
<p class="text-xs text-white/50 mt-0.5"> description="Langages, frameworks, pratiques et outils."
{exp.data.companyUrl ? ( href="/code/competences"
<a href={exp.data.companyUrl} target="_blank" rel="noopener noreferrer" class="text-purple-200 hover:text-white transition-colors">{exp.data.company}</a> icon="🛠"
) : exp.data.company} />
{exp.data.location && ` · ${exp.data.location}`} <NavigationCard
</p> title="Recommandations"
</div> description="Ce que disent les gens avec qui j'ai travaillé."
<span class:list={["text-xs whitespace-nowrap flex-shrink-0", isOngoing ? "text-purple-200 font-semibold" : "text-white/40"]}> href="/code/recommandations"
{start} — {end} icon="💬"
</span> />
</div>
</div>
);
})}
</div>
</div> </div>
<div class="mb-12"> {currentPosition && (
<div class="flex items-center justify-between mb-5"> <div class="facet-card rounded-2xl bg-gradient-to-r from-purple-500/20 to-indigo-500/20 border border-purple-300/15 p-6 mb-10">
<h2 class="text-2xl font-bold text-white">Projets</h2> <p class="text-xs font-semibold text-purple-200 uppercase tracking-wider mb-2">Poste actuel</p>
<a href="/code/projets" class="text-sm text-purple-200 hover:text-white transition-colors">Voir tous &rarr;</a> <p class="text-xl font-bold text-white">{currentPosition.data.role}</p>
</div> <p class="text-sm text-white/60 mt-1">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> {currentPosition.data.companyUrl ? (
{projects.map((project) => ( <a href={currentPosition.data.companyUrl} target="_blank" rel="noopener noreferrer" class="text-purple-200 hover:text-white transition-colors">{currentPosition.data.company}</a>
<ProjectCard ) : (
title={project.data.title} currentPosition.data.company
description={project.data.description} )}
technologies={project.data.technologies} {currentPosition.data.location && ` · ${currentPosition.data.location}`}
url={project.data.url} </p>
github={project.data.github}
featured={project.data.featured}
/>
))}
</div>
</div> </div>
)}
{recommendationTexts.length > 0 && ( {recommendationTexts.length > 0 && (
<div class="mb-12"> <div class="mb-12">
@ -134,25 +107,6 @@ function formatMonth(dateStr: string) {
</div> </div>
)} )}
<div class="mb-12">
<div class="flex items-center justify-between mb-5">
<h2 class="text-2xl font-bold text-white">Compétences</h2>
<a href="/code/competences" class="text-sm text-purple-200 hover:text-white transition-colors">Voir toutes &rarr;</a>
</div>
<div class="space-y-4">
{topSkills.map((category) => (
<div>
<p class="text-xs font-semibold text-white/40 uppercase tracking-wider mb-2">{category.name[locale as keyof typeof category.name]}</p>
<div class="flex flex-wrap gap-1.5">
{category.skills.map((skill) => (
<SkillBadge name={skill} />
))}
</div>
</div>
))}
</div>
</div>
<h2 class="text-2xl font-bold text-white mb-5">Valeurs & Approche</h2> <h2 class="text-2xl font-bold text-white mb-5">Valeurs & Approche</h2>
<div class="facet-card rounded-2xl bg-white/[0.04] border border-white/[0.08] p-6 mb-10"> <div class="facet-card rounded-2xl bg-white/[0.04] border border-white/[0.08] p-6 mb-10">
<ul class="space-y-3 text-white/70"> <ul class="space-y-3 text-white/70">

View file

@ -3,11 +3,9 @@ import { getCollection } from "astro:content";
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import Layout from "../../../layouts/main.astro"; import Layout from "../../../layouts/main.astro";
import Link from "../../../components/Link.astro"; import Link from "../../../components/Link.astro";
import NavigationCard from "../../../components/code/NavigationCard.astro";
import FeaturedRecommendation from "../../../components/code/FeaturedRecommendation.astro"; import FeaturedRecommendation from "../../../components/code/FeaturedRecommendation.astro";
import ProjectCard from "../../../components/code/ProjectCard.astro";
import SkillBadge from "../../../components/code/SkillBadge.astro";
import logoTiqa from "../../../assets/images/logo-tiqa-blanc.png"; import logoTiqa from "../../../assets/images/logo-tiqa-blanc.png";
import skillsData from "../../../data/skills.json";
const locale = "en"; const locale = "en";
@ -15,15 +13,7 @@ const experiences = (await getCollection("experiences"))
.filter((e) => e.data.lang === locale && !e.data.draft) .filter((e) => e.data.lang === locale && !e.data.draft)
.sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1)); .sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1));
const recentExperiences = experiences.slice(0, 4); const currentPosition = experiences.find((e) => !e.data.endDate);
const projects = (await getCollection("projects"))
.filter((p) => p.data.lang === locale && !p.data.draft && p.data.category === "dev")
.sort((a, b) => {
if (a.data.featured !== b.data.featured) return a.data.featured ? -1 : 1;
return b.data.date.getTime() - a.data.date.getTime();
})
.slice(0, 3);
const recommendations = (await getCollection("recommendations")) const recommendations = (await getCollection("recommendations"))
.sort((a, b) => b.data.date.getTime() - a.data.date.getTime()) .sort((a, b) => b.data.date.getTime() - a.data.date.getTime())
@ -33,14 +23,6 @@ const recommendationTexts = recommendations.map((rec) => ({
...rec, ...rec,
text: rec.body || '', text: rec.body || '',
})); }));
const topSkills = skillsData.categories.slice(0, 3);
function formatMonth(dateStr: string) {
const [year, month] = dateStr.split('-');
return new Date(parseInt(year), parseInt(month) - 1)
.toLocaleDateString('en-US', { year: 'numeric', month: 'short' });
}
--- ---
<Layout <Layout
@ -62,56 +44,47 @@ function formatMonth(dateStr: string) {
</p> </p>
</div> </div>
<div class="mb-12"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-12">
<div class="flex items-center justify-between mb-5"> <NavigationCard
<h2 class="text-2xl font-bold text-white">Career</h2> title="Career"
<a href="/en/code/career" class="text-sm text-purple-200 hover:text-white transition-colors">See all &rarr;</a> description="Timeline of my professional experiences since 2002."
</div> href="/en/code/career"
<div class="space-y-3"> icon="📋"
{recentExperiences.map((exp) => { />
const isOngoing = !exp.data.endDate; <NavigationCard
const start = formatMonth(exp.data.startDate); title="Projects"
const end = exp.data.endDate ? formatMonth(exp.data.endDate) : 'Present'; description="Open source software and personal projects."
return ( href="/en/code/projects"
<div class="facet-card rounded-xl bg-white/[0.06] border border-white/[0.1] p-4 hover:bg-white/[0.1] transition-colors"> icon="💻"
<div class="flex items-start justify-between gap-4"> />
<div class="min-w-0"> <NavigationCard
<p class="font-semibold text-white text-sm truncate">{exp.data.role}</p> title="Skills"
<p class="text-xs text-white/50 mt-0.5"> description="Languages, frameworks, practices and tools."
{exp.data.companyUrl ? ( href="/en/code/skills"
<a href={exp.data.companyUrl} target="_blank" rel="noopener noreferrer" class="text-purple-200 hover:text-white transition-colors">{exp.data.company}</a> icon="🛠"
) : exp.data.company} />
{exp.data.location && ` · ${exp.data.location}`} <NavigationCard
</p> title="Recommendations"
</div> description="What people I've worked with say about me."
<span class:list={["text-xs whitespace-nowrap flex-shrink-0", isOngoing ? "text-purple-200 font-semibold" : "text-white/40"]}> href="/en/code/recommendations"
{start} — {end} icon="💬"
</span> />
</div>
</div>
);
})}
</div>
</div> </div>
<div class="mb-12"> {currentPosition && (
<div class="flex items-center justify-between mb-5"> <div class="facet-card rounded-2xl bg-gradient-to-r from-purple-500/20 to-indigo-500/20 border border-purple-300/15 p-6 mb-10">
<h2 class="text-2xl font-bold text-white">Projects</h2> <p class="text-xs font-semibold text-purple-200 uppercase tracking-wider mb-2">Current position</p>
<a href="/en/code/projects" class="text-sm text-purple-200 hover:text-white transition-colors">See all &rarr;</a> <p class="text-xl font-bold text-white">{currentPosition.data.role}</p>
</div> <p class="text-sm text-white/60 mt-1">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4"> {currentPosition.data.companyUrl ? (
{projects.map((project) => ( <a href={currentPosition.data.companyUrl} target="_blank" rel="noopener noreferrer" class="text-purple-200 hover:text-white transition-colors">{currentPosition.data.company}</a>
<ProjectCard ) : (
title={project.data.title} currentPosition.data.company
description={project.data.description} )}
technologies={project.data.technologies} {currentPosition.data.location && ` · ${currentPosition.data.location}`}
url={project.data.url} </p>
github={project.data.github}
featured={project.data.featured}
/>
))}
</div>
</div> </div>
)}
{recommendationTexts.length > 0 && ( {recommendationTexts.length > 0 && (
<div class="mb-12"> <div class="mb-12">
@ -134,25 +107,6 @@ function formatMonth(dateStr: string) {
</div> </div>
)} )}
<div class="mb-12">
<div class="flex items-center justify-between mb-5">
<h2 class="text-2xl font-bold text-white">Skills</h2>
<a href="/en/code/skills" class="text-sm text-purple-200 hover:text-white transition-colors">See all &rarr;</a>
</div>
<div class="space-y-4">
{topSkills.map((category) => (
<div>
<p class="text-xs font-semibold text-white/40 uppercase tracking-wider mb-2">{category.name[locale as keyof typeof category.name]}</p>
<div class="flex flex-wrap gap-1.5">
{category.skills.map((skill) => (
<SkillBadge name={skill} />
))}
</div>
</div>
))}
</div>
</div>
<h2 class="text-2xl font-bold text-white mb-5">Values & Approach</h2> <h2 class="text-2xl font-bold text-white mb-5">Values & Approach</h2>
<div class="facet-card rounded-2xl bg-white/[0.04] border border-white/[0.08] p-6 mb-10"> <div class="facet-card rounded-2xl bg-white/[0.04] border border-white/[0.08] p-6 mb-10">
<ul class="space-y-3 text-white/70"> <ul class="space-y-3 text-white/70">