Compare commits
No commits in common. "ebd074b8663920d281178152734eb7c80a66733a" and "a79e075fbbaa1efdf0c3a2abde7ee461c343da5f" have entirely different histories.
ebd074b866
...
a79e075fbb
120 changed files with 567 additions and 369 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
|
|
@ -1,8 +1,7 @@
|
|||
---
|
||||
import { render } from "astro:content";
|
||||
import { getCollection, render } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import { t, getDateLocale, type Locale } from "../../utils/i18n";
|
||||
import { getLocalizedCollection } from "../../utils/content-i18n";
|
||||
import "../../styles/exp-card.css";
|
||||
|
||||
interface Props {
|
||||
|
|
@ -54,14 +53,9 @@ function computeDuration(startStr: string, endStr?: string) {
|
|||
return formatDuration(years, months);
|
||||
}
|
||||
|
||||
const experiences = (await getLocalizedCollection("experiences", locale))
|
||||
.filter((e) => !e.data.draft)
|
||||
.sort((a, b) => {
|
||||
const endA = a.data.endDate ?? '9999-12';
|
||||
const endB = b.data.endDate ?? '9999-12';
|
||||
if (endA !== endB) return endB > endA ? 1 : -1;
|
||||
return b.data.startDate! > a.data.startDate! ? 1 : -1;
|
||||
});
|
||||
const experiences = (await getCollection("experiences"))
|
||||
.filter((e) => e.data.lang === locale && !e.data.draft)
|
||||
.sort((a, b) => (b.data.startDate > a.data.startDate ? 1 : -1));
|
||||
|
||||
const presentLabel = t('career', 'present', locale);
|
||||
const logoAltPrefix = t('career', 'logoAlt', locale);
|
||||
|
|
@ -113,11 +107,11 @@ const logoAltPrefix = t('career', 'logoAlt', locale);
|
|||
<span class:list={["inline-block px-2 py-0.5 text-[11px] font-medium rounded-full border", colors.badge]}>
|
||||
{label}
|
||||
</span>
|
||||
<span class="exp-meta text-sm">
|
||||
<span class="exp-meta text-xs">
|
||||
{start} — {end}
|
||||
</span>
|
||||
<span class="exp-meta text-sm">· {duration}</span>
|
||||
{exp.data.location && <span class="exp-meta text-sm">· {exp.data.location}</span>}
|
||||
<span class="exp-meta text-xs">· {duration}</span>
|
||||
{exp.data.location && <span class="exp-meta text-xs">· {exp.data.location}</span>}
|
||||
</div>
|
||||
|
||||
<h3 class="text-xl font-bold pe-20">{exp.data.role}</h3>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import CategoryNav from './CategoryNav.astro';
|
|||
import HeroViewport from './HeroViewport.astro';
|
||||
import Lightbox from './Lightbox.astro';
|
||||
import { Picture } from 'astro:assets';
|
||||
import { getLocalizedEntry } from '../../utils/content-i18n';
|
||||
import { getEntry } from 'astro:content';
|
||||
import { getCategoryEntryId, type Locale } from '../../utils/i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -13,9 +13,10 @@ interface Props {
|
|||
|
||||
const { category, lang = 'fr' } = Astro.props;
|
||||
|
||||
// Récupérer les métadonnées de la catégorie (localisées avec fusion FR)
|
||||
// Récupérer les métadonnées de la catégorie (localisées avec fallback FR)
|
||||
const entryId = getCategoryEntryId(category, lang);
|
||||
const categoryData = await getLocalizedEntry('photoCategories', entryId, lang);
|
||||
const categoryData = await getEntry('photoCategories', entryId)
|
||||
?? await getEntry('photoCategories', category);
|
||||
|
||||
// Auto-détection des images du dossier de la catégorie
|
||||
const allImages = import.meta.glob<{ default: ImageMetadata }>('/src/assets/images/photos/categories/**/*.{jpg,jpeg,png,webp}');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { getLocalizedCollection } from '../../utils/content-i18n';
|
||||
import { getCollection } from 'astro:content';
|
||||
import HomeIcon from '../icons/HomeIcon.astro';
|
||||
import { t, getPhotoBasePath, getPhotoBlogPath, getPhotoAlbumsPath, getHomePath, type Locale } from '../../utils/i18n';
|
||||
|
||||
|
|
@ -15,8 +15,10 @@ const photoBasePath = getPhotoBasePath(lang);
|
|||
const homePath = getHomePath(lang);
|
||||
|
||||
// Récupérer les catégories depuis la collection, filtrées par langue
|
||||
const localizedCategories = await getLocalizedCollection('photoCategories', lang);
|
||||
const sortedCategories = localizedCategories.sort((a, b) => (a.data.order || 99) - (b.data.order || 99));
|
||||
const allCategories = await getCollection('photoCategories');
|
||||
const langCategories = allCategories.filter(c => (c.data.lang ?? 'fr') === lang);
|
||||
const effectiveCategories = langCategories.length > 0 ? langCategories : allCategories.filter(c => (c.data.lang ?? 'fr') === 'fr');
|
||||
const sortedCategories = effectiveCategories.sort((a, b) => (a.data.order || 99) - (b.data.order || 99));
|
||||
|
||||
// Extraire l'id de base (sans suffixe de langue)
|
||||
const categories = sortedCategories.map(cat => ({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { getLocalizedCollection } from '../../utils/content-i18n';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { t, getPhotoBlogPath, getPhotoAlbumsPath, type Locale } from '../../utils/i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -9,8 +9,10 @@ interface Props {
|
|||
const { lang = 'fr' } = Astro.props;
|
||||
|
||||
// Récupérer les catégories filtrées par langue
|
||||
const sortedCategories = (await getLocalizedCollection('photoCategories', lang))
|
||||
.sort((a, b) => (a.data.order || 99) - (b.data.order || 99));
|
||||
const allCategories = await getCollection('photoCategories');
|
||||
const langCategories = allCategories.filter(c => (c.data.lang ?? 'fr') === lang);
|
||||
const effectiveCategories = langCategories.length > 0 ? langCategories : allCategories.filter(c => (c.data.lang ?? 'fr') === 'fr');
|
||||
const sortedCategories = effectiveCategories.sort((a, b) => (a.data.order || 99) - (b.data.order || 99));
|
||||
---
|
||||
|
||||
<section id="explore-section" class="explore-section">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { getLocalizedCollection } from '../../utils/content-i18n';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { t, type Locale } from '../../utils/i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -15,10 +15,12 @@ const { images, albumTitle = '', showCategory = false, category = '', lang = 'fr
|
|||
const imagesForJS = JSON.stringify(images);
|
||||
|
||||
// Construire les labels depuis la collection filtrée par langue
|
||||
const localizedCategories = await getLocalizedCollection('photoCategories', lang);
|
||||
const allCategories = await getCollection('photoCategories');
|
||||
const langCategories = allCategories.filter(c => (c.data.lang ?? 'fr') === lang);
|
||||
const effectiveCategories = langCategories.length > 0 ? langCategories : allCategories.filter(c => (c.data.lang ?? 'fr') === 'fr');
|
||||
const categoryLabels: Record<string, string> = {
|
||||
'blog': t('photo', 'photoFeed', lang),
|
||||
...Object.fromEntries(localizedCategories.map(cat => [cat.id.replace(/\.(en|ar)$/, ''), cat.data.title]))
|
||||
...Object.fromEntries(effectiveCategories.map(cat => [cat.id.replace(/\.(en|ar)$/, ''), cat.data.title]))
|
||||
};
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import PhotoLayout from '../../../layouts/PhotoLayout.astro';
|
||||
import CategoryGrid from '../CategoryGrid.astro';
|
||||
import { getCategoryEntryId, type Locale } from '../../../utils/i18n';
|
||||
import { getLocalizedEntry } from '../../../utils/content-i18n';
|
||||
import { getEntry } from 'astro:content';
|
||||
|
||||
interface Props {
|
||||
category: string;
|
||||
|
|
@ -13,7 +13,8 @@ const { category, lang = 'fr' } = Astro.props;
|
|||
|
||||
// Récupérer le titre localisé pour le title de la page
|
||||
const entryId = getCategoryEntryId(category, lang);
|
||||
const categoryData = await getLocalizedEntry('photoCategories', entryId, lang);
|
||||
const categoryData = await getEntry('photoCategories', entryId)
|
||||
?? await getEntry('photoCategories', category);
|
||||
const categoryLabel = categoryData?.data.title || category;
|
||||
const categorySubtitle = categoryData?.data.subtitle || "";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import PhotoLayout from '../../../layouts/PhotoLayout.astro';
|
||||
import CategoryNav from '../CategoryNav.astro';
|
||||
import { getLocalizedCollection } from '../../../utils/content-i18n';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { Picture } from 'astro:assets';
|
||||
import { t, getPhotoBlogPath, getDateLocale, getPostBaseSlug, type Locale } from '../../../utils/i18n';
|
||||
|
||||
|
|
@ -20,7 +20,8 @@ const allImages = import.meta.glob<{ default: ImageMetadata }>(
|
|||
);
|
||||
|
||||
// Récupération des posts photo filtrés par langue
|
||||
const allPhotoBlogPosts = await getLocalizedCollection('photoBlogPosts', lang);
|
||||
const allPhotoBlogPosts = (await getCollection('photoBlogPosts'))
|
||||
.filter(post => (post.data.lang ?? 'fr') === lang);
|
||||
|
||||
// Tri par date (plus récent en premier)
|
||||
const sortedPosts = allPhotoBlogPosts.sort((a, b) =>
|
||||
|
|
|
|||
|
|
@ -37,19 +37,19 @@ const projectsCollection = defineCollection({
|
|||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.date().optional(),
|
||||
category: z.enum(['dev', 'comedy', 'photo']).optional(),
|
||||
date: z.date(),
|
||||
category: z.enum(['dev', 'comedy', 'photo']),
|
||||
technologies: z.array(z.string()).optional(),
|
||||
url: z.string().url().optional(),
|
||||
github: z.string().url().optional(),
|
||||
image: z.string().optional(),
|
||||
imageAlt: z.string().optional(),
|
||||
featured: z.boolean().optional(),
|
||||
draft: z.boolean().optional(),
|
||||
featured: z.boolean().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
lang: z.enum(['fr', 'en', 'ar']).default('fr'),
|
||||
}).transform((data) => ({
|
||||
...data,
|
||||
dateFormatted: data.date ? formatDate(data.date, data.lang) : undefined,
|
||||
dateFormatted: formatDate(data.date, data.lang),
|
||||
})),
|
||||
});
|
||||
|
||||
|
|
@ -57,16 +57,16 @@ const experiencesCollection = defineCollection({
|
|||
loader: glob({ pattern: "**/*.md", base: "./src/content/experiences", ...stripExtension('md') }),
|
||||
schema: z.object({
|
||||
role: z.string(),
|
||||
company: z.string().optional(),
|
||||
company: z.string(),
|
||||
companyUrl: z.string().url().optional(),
|
||||
logo: z.string().optional(),
|
||||
location: z.string().optional(),
|
||||
startDate: z.string().optional(),
|
||||
startDate: z.string(),
|
||||
endDate: z.string().optional(),
|
||||
technologies: z.array(z.string()).optional(),
|
||||
type: z.enum(['employment', 'freelance', 'teaching', 'community', 'entrepreneurship']).optional(),
|
||||
featured: z.boolean().optional(),
|
||||
draft: z.boolean().optional(),
|
||||
type: z.enum(['employment', 'freelance', 'teaching', 'community', 'entrepreneurship']),
|
||||
featured: z.boolean().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
lang: z.enum(['fr', 'en', 'ar']).default('fr'),
|
||||
}),
|
||||
});
|
||||
|
|
@ -110,11 +110,11 @@ const photoBlogPostsCollection = defineCollection({
|
|||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.date().optional(),
|
||||
coverImage: z.string().optional(),
|
||||
date: z.date(),
|
||||
coverImage: z.string(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
featured: z.boolean().optional(),
|
||||
draft: z.boolean().optional(),
|
||||
featured: z.boolean().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
lang: z.enum(['fr', 'en', 'ar']).default('fr'),
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
role: "مهندس معماري للواجهات"
|
||||
location: "عن بُعد / غرونوبل"
|
||||
company: "ARaymond"
|
||||
companyUrl: "https://www.araymond.com/"
|
||||
logo: "araymond.png"
|
||||
location: "غرونوبل"
|
||||
startDate: "2022-01"
|
||||
endDate: "2023-01"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Nx", "Vite"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
role: "Frontend Architect"
|
||||
location: "Remote / Grenoble"
|
||||
company: "ARaymond"
|
||||
companyUrl: "https://www.araymond.com/"
|
||||
logo: "araymond.png"
|
||||
location: "Grenoble"
|
||||
startDate: "2022-01"
|
||||
endDate: "2023-01"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Nx", "Vite"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Architecte frontend"
|
|||
company: "ARaymond"
|
||||
companyUrl: "https://www.araymond.com/"
|
||||
logo: "araymond.png"
|
||||
location: "Télétravail / Grenoble"
|
||||
startDate: "2022-07"
|
||||
endDate: "2023-07"
|
||||
location: "Grenoble"
|
||||
startDate: "2022-01"
|
||||
endDate: "2023-01"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Nx", "Vite"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "أستاذ هندسة البرمجيات"
|
||||
company: "جامعة شامبوليون"
|
||||
companyUrl: "https://www.univ-jfc.fr/"
|
||||
logo: "champollion.png"
|
||||
location: "ألبي"
|
||||
startDate: "2019-09"
|
||||
technologies: ["TypeScript", "JavaScript", "Node.js", "TDD", "Clean Code"]
|
||||
type: "teaching"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
---
|
||||
role: "Software Engineering Professor"
|
||||
company: "Université Champollion"
|
||||
companyUrl: "https://www.univ-jfc.fr/"
|
||||
logo: "champollion.png"
|
||||
location: "Albi"
|
||||
startDate: "2019-09"
|
||||
technologies: ["TypeScript", "JavaScript", "Node.js", "TDD", "Clean Code"]
|
||||
type: "teaching"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "حرفي برمجيات / مؤسس مشارك"
|
||||
location: "عن بُعد / بوردو"
|
||||
company: "DisMoi"
|
||||
companyUrl: "https://github.com/dis-moi"
|
||||
logo: "dismoi.png"
|
||||
location: "عن بُعد"
|
||||
startDate: "2019-01"
|
||||
endDate: "2021-06"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
type: "entrepreneurship"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "Software Craftsman / Cofounder"
|
||||
location: "Remote / Bordeaux"
|
||||
company: "DisMoi"
|
||||
companyUrl: "https://github.com/dis-moi"
|
||||
logo: "dismoi.png"
|
||||
location: "Remote"
|
||||
startDate: "2019-01"
|
||||
endDate: "2021-06"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
type: "entrepreneurship"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Software Craftsman / Cofondateur"
|
|||
company: "DisMoi"
|
||||
companyUrl: "https://github.com/dis-moi"
|
||||
logo: "dismoi.png"
|
||||
location: "Télétravail / Bordeaux"
|
||||
startDate: "2019-02"
|
||||
endDate: "2021-04"
|
||||
location: "Remote"
|
||||
startDate: "2019-01"
|
||||
endDate: "2021-06"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
type: "entrepreneurship"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
role: "مدرّس تطوير"
|
||||
company: "ESN 81"
|
||||
companyUrl: "https://www.esn81.fr/"
|
||||
location: "كاستر"
|
||||
startDate: "2020-09"
|
||||
endDate: "2021-06"
|
||||
technologies: ["JavaScript", "Node.js"]
|
||||
type: "teaching"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
---
|
||||
role: "Development Teacher"
|
||||
company: "ESN 81"
|
||||
companyUrl: "https://www.esn81.fr/"
|
||||
location: "Castres"
|
||||
startDate: "2020-09"
|
||||
endDate: "2021-06"
|
||||
technologies: ["JavaScript", "Node.js"]
|
||||
type: "teaching"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
role: "Enseignant en développement"
|
||||
company: "ESN 81"
|
||||
companyUrl: "https://www.esn81.fr/"
|
||||
logo: "esn81.png"
|
||||
location: "Castres"
|
||||
startDate: "2020-01"
|
||||
endDate: "2021-07"
|
||||
startDate: "2020-09"
|
||||
endDate: "2021-06"
|
||||
technologies: ["JavaScript", "Node.js"]
|
||||
type: "teaching"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "مطوّر ويب"
|
||||
location: "بور مارلي"
|
||||
company: "e-Themis"
|
||||
companyUrl: "https://www.e-themis.com/"
|
||||
logo: "ethemis.png"
|
||||
location: "فرساي"
|
||||
startDate: "2002-06"
|
||||
endDate: "2002-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL"]
|
||||
type: "employment"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
---
|
||||
role: "Web Developer"
|
||||
company: "e-Themis"
|
||||
companyUrl: "https://www.e-themis.com/"
|
||||
logo: "ethemis.png"
|
||||
location: "Versailles"
|
||||
startDate: "2002-06"
|
||||
endDate: "2002-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL"]
|
||||
type: "employment"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Développeur web"
|
|||
company: "e-Themis"
|
||||
companyUrl: "https://www.e-themis.com/"
|
||||
logo: "ethemis.png"
|
||||
location: "Port-Marly"
|
||||
startDate: "2002-02"
|
||||
endDate: "2002-11"
|
||||
location: "Versailles"
|
||||
startDate: "2002-06"
|
||||
endDate: "2002-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL"]
|
||||
type: "employment"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "مهندس برمجيات أول"
|
||||
location: "سان جيرمان أون لاي"
|
||||
company: "e-Themis"
|
||||
companyUrl: "https://www.e-themis.com/"
|
||||
logo: "ethemis.png"
|
||||
location: "فرساي"
|
||||
startDate: "2011-01"
|
||||
endDate: "2015-12"
|
||||
technologies: ["PHP", "Symfony", "JavaScript", "MySQL", "Linux"]
|
||||
type: "employment"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
---
|
||||
role: "Senior Software Engineer"
|
||||
company: "e-Themis"
|
||||
companyUrl: "https://www.e-themis.com/"
|
||||
logo: "ethemis.png"
|
||||
location: "Versailles"
|
||||
startDate: "2011-01"
|
||||
endDate: "2015-12"
|
||||
technologies: ["PHP", "Symfony", "JavaScript", "MySQL", "Linux"]
|
||||
type: "employment"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Ingénieur logiciel senior"
|
|||
company: "e-Themis"
|
||||
companyUrl: "https://www.e-themis.com/"
|
||||
logo: "ethemis.png"
|
||||
location: "Saint-Germain-en-Laye"
|
||||
startDate: "2011-12"
|
||||
endDate: "2015-06"
|
||||
location: "Versailles"
|
||||
startDate: "2011-01"
|
||||
endDate: "2015-12"
|
||||
technologies: ["PHP", "Symfony", "JavaScript", "MySQL", "Linux"]
|
||||
type: "employment"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
role: "مطوّر ويب وبرمجيات"
|
||||
location: "شاتو"
|
||||
company: "مستقل"
|
||||
location: "إيل دو فرانس"
|
||||
startDate: "2003-01"
|
||||
endDate: "2006-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL", "Linux"]
|
||||
type: "freelance"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
---
|
||||
role: "Web & Software Developer"
|
||||
company: "Freelance"
|
||||
location: "Île-de-France"
|
||||
startDate: "2003-01"
|
||||
endDate: "2006-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL", "Linux"]
|
||||
type: "freelance"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
role: "Développeur web & logiciel"
|
||||
company: "Indépendant"
|
||||
location: "Chatou"
|
||||
startDate: "2003-08"
|
||||
location: "Île-de-France"
|
||||
startDate: "2003-01"
|
||||
endDate: "2006-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL", "Linux"]
|
||||
type: "freelance"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
role: "مدير تقني"
|
||||
location: "عن بُعد / ليون"
|
||||
company: "GoBuild (Go-Decision)"
|
||||
companyUrl: "https://www.gobuild.fr"
|
||||
location: "ليون"
|
||||
startDate: "2020-06"
|
||||
endDate: "2022-01"
|
||||
technologies: ["TypeScript", "React.js", "Elixir", "PostgreSQL", "Docker"]
|
||||
type: "employment"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
role: "CTO"
|
||||
location: "Remote / Lyon"
|
||||
company: "GoBuild (Go-Decision)"
|
||||
companyUrl: "https://www.gobuild.fr"
|
||||
location: "Lyon"
|
||||
startDate: "2020-06"
|
||||
endDate: "2022-01"
|
||||
technologies: ["TypeScript", "React.js", "Elixir", "PostgreSQL", "Docker"]
|
||||
type: "employment"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
role: "CTO"
|
||||
company: "GoBuild (Go-Decision)"
|
||||
companyUrl: "https://www.gobuild.fr"
|
||||
logo: "go-decision.png"
|
||||
location: "Télétravail / Lyon"
|
||||
startDate: "2020-02"
|
||||
endDate: "2022-06"
|
||||
location: "Lyon"
|
||||
startDate: "2020-06"
|
||||
endDate: "2022-01"
|
||||
technologies: ["TypeScript", "React.js", "Elixir", "PostgreSQL", "Docker"]
|
||||
type: "freelance"
|
||||
type: "employment"
|
||||
lang: "fr"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "مهندس برمجيات fullstack"
|
||||
location: "عن بُعد / باريس"
|
||||
company: "Libeo"
|
||||
companyUrl: "https://www.libeo.io/"
|
||||
logo: "libeo.png"
|
||||
location: "عن بُعد"
|
||||
startDate: "2021-01"
|
||||
endDate: "2021-06"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "GraphQL"]
|
||||
type: "freelance"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "Fullstack Software Engineer"
|
||||
location: "Remote / Paris"
|
||||
company: "Libeo"
|
||||
companyUrl: "https://www.libeo.io/"
|
||||
logo: "libeo.png"
|
||||
location: "Remote"
|
||||
startDate: "2021-01"
|
||||
endDate: "2021-06"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "GraphQL"]
|
||||
type: "freelance"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Ingénieur logiciel fullstack"
|
|||
company: "Libeo"
|
||||
companyUrl: "https://www.libeo.io/"
|
||||
logo: "libeo.png"
|
||||
location: "Télétravail / Paris"
|
||||
startDate: "2021-02"
|
||||
endDate: "2021-05"
|
||||
location: "Remote"
|
||||
startDate: "2021-01"
|
||||
endDate: "2021-06"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "GraphQL"]
|
||||
type: "freelance"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "مهندس برمجيات أول"
|
||||
company: "Obat"
|
||||
companyUrl: "https://www.obat.fr/"
|
||||
logo: "obat.png"
|
||||
location: "عن بُعد"
|
||||
startDate: "2023-02"
|
||||
endDate: "2024-01"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "NestJS", "PostgreSQL"]
|
||||
type: "freelance"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "Senior Software Engineer"
|
||||
company: "Obat"
|
||||
companyUrl: "https://www.obat.fr/"
|
||||
logo: "obat.png"
|
||||
location: "Remote"
|
||||
startDate: "2023-02"
|
||||
endDate: "2024-01"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "NestJS", "PostgreSQL"]
|
||||
type: "freelance"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Ingénieur logiciel senior"
|
|||
company: "Obat"
|
||||
companyUrl: "https://www.obat.fr/"
|
||||
logo: "obat.png"
|
||||
location: "Télétravail"
|
||||
startDate: "2023-12"
|
||||
endDate: "2024-04"
|
||||
location: "Remote"
|
||||
startDate: "2023-02"
|
||||
endDate: "2024-01"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "NestJS", "PostgreSQL"]
|
||||
type: "freelance"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
role: "مؤسّس ومدير عام"
|
||||
company: "Team Logics"
|
||||
location: "فرساي"
|
||||
startDate: "2007-01"
|
||||
endDate: "2011-12"
|
||||
technologies: ["PHP", "CakePHP", "JavaScript", "MySQL", "Linux"]
|
||||
type: "entrepreneurship"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
---
|
||||
role: "Founder & CEO"
|
||||
company: "Team Logics"
|
||||
location: "Versailles"
|
||||
startDate: "2007-01"
|
||||
endDate: "2011-12"
|
||||
technologies: ["PHP", "CakePHP", "JavaScript", "MySQL", "Linux"]
|
||||
type: "entrepreneurship"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
role: "Fondateur & CEO"
|
||||
company: "Team Logics"
|
||||
logo: "team-logics.png"
|
||||
location: "Versailles"
|
||||
startDate: "2007-01"
|
||||
endDate: "2011-11"
|
||||
endDate: "2011-12"
|
||||
technologies: ["PHP", "CakePHP", "JavaScript", "MySQL", "Linux"]
|
||||
type: "entrepreneurship"
|
||||
featured: true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "مطوّر رئيسي"
|
||||
location: "عن بُعد / مونتروي"
|
||||
company: "Urssaf Caisse nationale"
|
||||
companyUrl: "https://www.urssaf.fr/"
|
||||
logo: "urssaf.png"
|
||||
location: "عن بُعد / باريس"
|
||||
startDate: "2024-02"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js", "GitHub"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
role: "Lead Developer"
|
||||
location: "Remote / Montreuil"
|
||||
company: "Urssaf Caisse nationale"
|
||||
companyUrl: "https://www.urssaf.fr/"
|
||||
logo: "urssaf.png"
|
||||
location: "Remote / Paris"
|
||||
startDate: "2024-02"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js", "GitHub"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ role: "Lead Developer"
|
|||
company: "Urssaf Caisse nationale"
|
||||
companyUrl: "https://www.urssaf.fr/"
|
||||
logo: "urssaf.png"
|
||||
location: "Télétravail / Montreuil"
|
||||
location: "Remote / Paris"
|
||||
startDate: "2024-02"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js", "GitHub"]
|
||||
type: "freelance"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
---
|
||||
role: "مطوّر رئيسي ← قائد تقني"
|
||||
location: "سان دوني"
|
||||
company: "Veepee"
|
||||
companyUrl: "https://www.veepee.com/"
|
||||
logo: "veepee.png"
|
||||
location: "باريس"
|
||||
startDate: "2016-02"
|
||||
endDate: "2019-06"
|
||||
technologies: ["TypeScript", "JavaScript", "React.js", "Redux", "redux-saga", "RxJS", "Node.js", "Webpack"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
---
|
||||
role: "Lead Developer → Tech Lead"
|
||||
company: "Veepee"
|
||||
companyUrl: "https://www.veepee.com/"
|
||||
logo: "veepee.png"
|
||||
location: "Paris"
|
||||
startDate: "2016-02"
|
||||
endDate: "2019-06"
|
||||
technologies: ["TypeScript", "JavaScript", "React.js", "Redux", "redux-saga", "RxJS", "Node.js", "Webpack"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Lead Developer → Tech Lead"
|
|||
company: "Veepee"
|
||||
companyUrl: "https://www.veepee.com/"
|
||||
logo: "veepee.png"
|
||||
location: "Saint-Denis"
|
||||
startDate: "2016-01"
|
||||
endDate: "2019-03"
|
||||
location: "Paris"
|
||||
startDate: "2016-02"
|
||||
endDate: "2019-06"
|
||||
technologies: ["TypeScript", "JavaScript", "React.js", "Redux", "redux-saga", "RxJS", "Node.js", "Webpack"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "تصوير إيرول"
|
||||
description: "أراد إيرول صورًا له لإعداد كتاب أعمال. عملنا طوال اليوم لتنويع الأجواء..."
|
||||
date: 2011-10-02
|
||||
coverImage: "18-Eroll-Shooting-1-19.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Shooting Eroll"
|
||||
description: "Eroll wanted some photos of him in order to have a modeling book. We worked all day in order to have some ambiance variations..."
|
||||
date: 2011-10-02
|
||||
coverImage: "18-Eroll-Shooting-1-19.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Inox Park Paris 2011"
|
||||
description: "بعد نجاحه في 2010، يعود مهرجان Inox Park Paris إلى جزيرة شاتو في نسخته الثانية. ثلاث مسارح، 15 دي جي، 12 ساعة من الحفل في الهواء الطلق: Tiësto، Joachim Garraud، Sven Väth، Steve Aoki..."
|
||||
date: 2011-09-10
|
||||
coverImage: "01-Inox-Park-Paris-Chatou-2011.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Inox Park Paris 2011"
|
||||
description: "After its 2010 success, the Inox Park Paris Electro Festival is back to the island of Chatou for its second edition. Three stages, 15 DJs, 12 hours of outdoor party: Tiësto, Joachim Garraud, Sven Väth, Steve Aoki..."
|
||||
date: 2011-09-10
|
||||
coverImage: "01-Inox-Park-Paris-Chatou-2011.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "عملية المحفظة 2012"
|
||||
description: "توزيع محافظ مدرسية مجانية في مدارس محرومة من طرف جمعية محلية (JCI)، طنجة، المغرب."
|
||||
date: 2012-09-30
|
||||
coverImage: "35-Moroccan-Schoolgirls.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Schoolbag Operation 2012"
|
||||
description: "During a distribution of free schoolbags in poor schools by a local association (JCI), Tangier, Morocco."
|
||||
date: 2012-09-30
|
||||
coverImage: "35-Moroccan-Schoolgirls.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "جولة في طنجة"
|
||||
description: "جولة فوتوغرافية في شوارع طنجة."
|
||||
date: 2012-05-26
|
||||
coverImage: "01-Observer-le-changement.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Tangier Walk"
|
||||
description: "A photographic walk through the streets of Tangier."
|
||||
date: 2012-05-26
|
||||
coverImage: "01-Observer-le-changement.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "هلسنكي"
|
||||
description: "اختفى الثلج من هلسنكي وسرعان ما أفسح المجال للربيع..."
|
||||
date: 2013-05-15
|
||||
coverImage: "01-Library-of-University-of-Helsinki.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Helsinki"
|
||||
description: "The snow has disappeared from Helsinki and quickly gave way to spring..."
|
||||
date: 2013-05-15
|
||||
coverImage: "01-Library-of-University-of-Helsinki.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "نزهة في إفران"
|
||||
description: "نزهة شتوية في جبال الأطلس المتوسط."
|
||||
date: 2013-01-13
|
||||
coverImage: "03-3.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Ifrane Hike"
|
||||
description: "Winter hike in the Middle Atlas mountains."
|
||||
date: 2013-01-13
|
||||
coverImage: "03-3.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "London Calling"
|
||||
description: "عطلة نهاية أسبوع فوتوغرافية في لندن."
|
||||
date: 2014-07-15
|
||||
coverImage: "01-The-sky-inside.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "London Calling"
|
||||
description: "A photographic weekend in London."
|
||||
date: 2014-07-15
|
||||
coverImage: "01-The-sky-inside.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "أحد سيكواني"
|
||||
description: "نزهة يوم أحد على ضفاف نهر السين."
|
||||
date: 2014-05-18
|
||||
coverImage: "04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Sequanian Sunday"
|
||||
description: "A sunday walk near the Seine."
|
||||
date: 2014-05-18
|
||||
coverImage: "04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "تجوال في مدينة طنجة القديمة"
|
||||
description: "أثناء التجوال في أزقة طنجة القديمة، صادفت ساعاتيًا، ونجّارًا، وقمرًا عملاقًا..."
|
||||
date: 2014-08-10
|
||||
coverImage: "01-The-watchmaker.jpg"
|
||||
tags: []
|
||||
featured: true
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Wandering Tangier Medina"
|
||||
description: "Walking in the streets of the old Tangier, met a watchmaker, a carpenter and a super-moon..."
|
||||
date: 2014-08-10
|
||||
coverImage: "01-The-watchmaker.jpg"
|
||||
tags: []
|
||||
featured: true
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ description: |
|
|||
إنيغما كانت مسابقة بحث عن الكنز بين المدارس نظّمها المركز العالي للدراسات CESIM يوم السبت، تحت عنوان «البحث عن كنز ابن بطوطة المنسي». 4 فرق طنجاوية دُعيت لتمثيل مؤسساتها.
|
||||
|
||||
تغطية.
|
||||
date: 2015-04-25
|
||||
coverImage: "01-Enigma-v1.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ description: |
|
|||
Enigma was an inter-school treasure hunt organized this saturday by the CESIM, on the theme "In search of forgotten treasure of Ibn Battuta". 4 Tangier teams were invited to represent their respective institutions.
|
||||
|
||||
Recap.
|
||||
date: 2015-04-25
|
||||
coverImage: "01-Enigma-v1.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Field of Stones"
|
||||
description: "كواليس تصوير غلاف ألبوم ماركو وولتر. أراد أن تُلتقط الصورة في سينماتيك طنجة. لا وقت، لا إضاءة، لكن لا خيار. حاولنا تقديم أفضل ما لدينا..."
|
||||
date: 2015-04-02
|
||||
coverImage: "01-Marco-Wolter-Field-of-Stones-2.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Field of Stones"
|
||||
description: "Making of the album cover for Marco Wolter. He wanted it to be shot in the Cinémathèque of Tangier. We had no time, no light, but no choice. We tried to make the best of it..."
|
||||
date: 2015-04-02
|
||||
coverImage: "01-Marco-Wolter-Field-of-Stones-2.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "لا رياح في لاس كويفاس"
|
||||
description: "كان من المفترض أن يكون يومًا مثاليًا لتطيير طائرتنا الورقية: مشمس وعاصف. مشمس كان، لكن الرياح لم تأتِ أبدًا."
|
||||
date: 2015-01-10
|
||||
coverImage: "13-No-wind-at-Las-Cuevas.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "No Wind at Las Cuevas"
|
||||
description: "It was supposed to be a perfect day for flying our kite: sunny and windy. Sunny it was, but the wind never came."
|
||||
date: 2015-01-10
|
||||
coverImage: "13-No-wind-at-Las-Cuevas.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "زفاف أورور وتوما"
|
||||
description: "كان لي شرف ومتعة أن أكون شاهد توما في زفافه الجميل مع أورور. ليس سهلًا التصوير في نفس الوقت، لكن كل الصور مليئة بالحب."
|
||||
date: 2015-09-26
|
||||
coverImage: "10-Mariage-Aurore-Thomas-10.jpg"
|
||||
tags: []
|
||||
featured: true
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Wedding Aurore & Thomas"
|
||||
description: "I had the honor and pleasure to be Thomas' best man for his beautiful wedding with Aurore. Not easy to shoot pictures though, but all of them are filled with love."
|
||||
date: 2015-09-26
|
||||
coverImage: "10-Mariage-Aurore-Thomas-10.jpg"
|
||||
tags: []
|
||||
featured: true
|
||||
draft: false
|
||||
lang: en
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "ثقافات وتقاليد",
|
||||
"subtitle": "ثراء التقاليد الإنسانية",
|
||||
"order": 4,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Cultures & Traditions",
|
||||
"subtitle": "Richness of human traditions",
|
||||
"order": 4,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "محرّكات",
|
||||
"subtitle": "ميكانيكا وقوة في حركة",
|
||||
"order": 7,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Engines",
|
||||
"subtitle": "Mechanics and power in motion",
|
||||
"order": 7,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "يوميات",
|
||||
"subtitle": "لحظات من الحياة اليومية",
|
||||
"order": 8,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Everyday Life",
|
||||
"subtitle": "Moments of everyday life",
|
||||
"order": 8,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "موسيقى واحتفالات",
|
||||
"subtitle": "نغمات وأغانٍ واهتزازات تحتفي بلحظات حياتنا الكبيرة والصغيرة",
|
||||
"order": 5,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Music & Celebrations",
|
||||
"subtitle": "Notes, songs and vibrations celebrating life's big and small moments",
|
||||
"order": 5,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "طبيعة",
|
||||
"subtitle": "سحر العالم الطبيعي",
|
||||
"order": 3,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Nature",
|
||||
"subtitle": "The magic of the natural world",
|
||||
"order": 3,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "مناظر طبيعية",
|
||||
"subtitle": "جمال المناظر والأماكن",
|
||||
"order": 2,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Landscapes",
|
||||
"subtitle": "Beauty of landscapes and places",
|
||||
"order": 2,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "بورتريهات",
|
||||
"subtitle": "تعابير ومشاعر ملتقطة",
|
||||
"order": 1,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Portraits",
|
||||
"subtitle": "Captured expressions and emotions",
|
||||
"order": 1,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "رياضة",
|
||||
"subtitle": "حركة وجهد وتجاوز للذات",
|
||||
"order": 6,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"title": "Sports",
|
||||
"subtitle": "Movement, effort and pushing limits",
|
||||
"order": 6,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Débats.co"
|
||||
description: "منصّة تعاونية لتلخيص النقاشات المجتمعية. ويكيبيديا المواقف."
|
||||
date: 2015-01-01
|
||||
category: "dev"
|
||||
technologies: ["Next.js", "React", "TypeScript", "Supabase", "PostgreSQL", "Effect TS"]
|
||||
url: "https://debats.co"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
---
|
||||
title: "Débats.co"
|
||||
description: "Collaborative platform for synthesizing public debates. The Wikipedia of public stances."
|
||||
date: 2015-01-01
|
||||
category: "dev"
|
||||
technologies: ["Next.js", "React", "TypeScript", "Supabase", "PostgreSQL", "Effect TS"]
|
||||
url: "https://debats.co"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
title: "DisMoi"
|
||||
description: "إضافة متصفّح في مجال التكنولوجيا المدنية تضيف معلومات سياقية على أي صفحة ويب."
|
||||
date: 2019-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "PHP", "Symfony"]
|
||||
url: "https://www.dismoi.io/"
|
||||
github: "https://github.com/dis-moi"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
title: "DisMoi"
|
||||
description: "Civic tech browser extension that adds contextual information to any web page."
|
||||
date: 2019-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "PHP", "Symfony"]
|
||||
url: "https://www.dismoi.io/"
|
||||
github: "https://github.com/dis-moi"
|
||||
featured: true
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
---
|
||||
title: "ICU"
|
||||
description: "منصة مشاركة صور عبر الإنترنت، مشروع شخصي تاريخي."
|
||||
date: 2005-01-01
|
||||
category: "dev"
|
||||
technologies: ["PHP", "JavaScript", "MySQL"]
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
---
|
||||
title: "ICU"
|
||||
description: "Online photo sharing platform, a historical personal project."
|
||||
date: 2005-01-01
|
||||
category: "dev"
|
||||
technologies: ["PHP", "JavaScript", "MySQL"]
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
title: "mon-entreprise.urssaf.fr"
|
||||
description: "المساعد الرسمي لروّاد الأعمال في فرنسا. أكثر من 20 محاكيًا اجتماعيًا-ضريبيًا، مليون مستخدم شهريًا."
|
||||
date: 2024-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Redux", "Node.js"]
|
||||
url: "https://mon-entreprise.urssaf.fr/"
|
||||
github: "https://github.com/betagouv/mon-entreprise"
|
||||
featured: false
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
---
|
||||
title: "mon-entreprise.urssaf.fr"
|
||||
description: "The official assistant for entrepreneurs in France. Over 20 socio-fiscal simulators, one million users per month."
|
||||
date: 2024-01-01
|
||||
category: "dev"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Redux", "Node.js"]
|
||||
url: "https://mon-entreprise.urssaf.fr/"
|
||||
github: "https://github.com/betagouv/mon-entreprise"
|
||||
featured: false
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
---
|
||||
title: "N.Gine"
|
||||
description: "نظام إدارة محتوى خاص بُني من الصفر، استُخدم للعديد من مشاريع العملاء."
|
||||
date: 2004-01-01
|
||||
category: "dev"
|
||||
technologies: ["PHP", "JavaScript", "MySQL"]
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue