Compare commits
15 commits
a79e075fbb
...
ebd074b866
| Author | SHA1 | Date | |
|---|---|---|---|
| ebd074b866 | |||
| f88a17b0ee | |||
| 3d67c2a320 | |||
| 677142a7c4 | |||
| 663ce9a879 | |||
| 973b2faa04 | |||
| 5dfdbd88ba | |||
| 78a72bfb92 | |||
| 6b3ceef903 | |||
| 0a4ed28fc0 | |||
| c8f444993d | |||
| 52aaa0a5aa | |||
| 88ed94dca3 | |||
| f32cd09940 | |||
| 366d18764b |
120 changed files with 369 additions and 567 deletions
BIN
src/assets/images/companies/esn81.png
Normal file
BIN
src/assets/images/companies/esn81.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
BIN
src/assets/images/companies/go-decision.png
Normal file
BIN
src/assets/images/companies/go-decision.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
BIN
src/assets/images/companies/team-logics.png
Executable file
BIN
src/assets/images/companies/team-logics.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
import { getCollection, render } from "astro:content";
|
||||
import { 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 {
|
||||
|
|
@ -53,9 +54,14 @@ function computeDuration(startStr: string, endStr?: string) {
|
|||
return formatDuration(years, months);
|
||||
}
|
||||
|
||||
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 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 presentLabel = t('career', 'present', locale);
|
||||
const logoAltPrefix = t('career', 'logoAlt', locale);
|
||||
|
|
@ -107,11 +113,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-xs">
|
||||
<span class="exp-meta text-sm">
|
||||
{start} — {end}
|
||||
</span>
|
||||
<span class="exp-meta text-xs">· {duration}</span>
|
||||
{exp.data.location && <span class="exp-meta text-xs">· {exp.data.location}</span>}
|
||||
<span class="exp-meta text-sm">· {duration}</span>
|
||||
{exp.data.location && <span class="exp-meta text-sm">· {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 { getEntry } from 'astro:content';
|
||||
import { getLocalizedEntry } from '../../utils/content-i18n';
|
||||
import { getCategoryEntryId, type Locale } from '../../utils/i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -13,10 +13,9 @@ interface Props {
|
|||
|
||||
const { category, lang = 'fr' } = Astro.props;
|
||||
|
||||
// Récupérer les métadonnées de la catégorie (localisées avec fallback FR)
|
||||
// Récupérer les métadonnées de la catégorie (localisées avec fusion FR)
|
||||
const entryId = getCategoryEntryId(category, lang);
|
||||
const categoryData = await getEntry('photoCategories', entryId)
|
||||
?? await getEntry('photoCategories', category);
|
||||
const categoryData = await getLocalizedEntry('photoCategories', entryId, lang);
|
||||
|
||||
// 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 { getCollection } from 'astro:content';
|
||||
import { getLocalizedCollection } from '../../utils/content-i18n';
|
||||
import HomeIcon from '../icons/HomeIcon.astro';
|
||||
import { t, getPhotoBasePath, getPhotoBlogPath, getPhotoAlbumsPath, getHomePath, type Locale } from '../../utils/i18n';
|
||||
|
||||
|
|
@ -15,10 +15,8 @@ const photoBasePath = getPhotoBasePath(lang);
|
|||
const homePath = getHomePath(lang);
|
||||
|
||||
// Récupérer les catégories depuis la collection, filtrées par langue
|
||||
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));
|
||||
const localizedCategories = await getLocalizedCollection('photoCategories', lang);
|
||||
const sortedCategories = localizedCategories.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 { getCollection } from 'astro:content';
|
||||
import { getLocalizedCollection } from '../../utils/content-i18n';
|
||||
import { t, getPhotoBlogPath, getPhotoAlbumsPath, type Locale } from '../../utils/i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -9,10 +9,8 @@ interface Props {
|
|||
const { lang = 'fr' } = Astro.props;
|
||||
|
||||
// Récupérer les catégories filtrées par langue
|
||||
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));
|
||||
const sortedCategories = (await getLocalizedCollection('photoCategories', lang))
|
||||
.sort((a, b) => (a.data.order || 99) - (b.data.order || 99));
|
||||
---
|
||||
|
||||
<section id="explore-section" class="explore-section">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
import { getLocalizedCollection } from '../../utils/content-i18n';
|
||||
import { t, type Locale } from '../../utils/i18n';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -15,12 +15,10 @@ const { images, albumTitle = '', showCategory = false, category = '', lang = 'fr
|
|||
const imagesForJS = JSON.stringify(images);
|
||||
|
||||
// Construire les labels depuis la collection filtrée par langue
|
||||
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 localizedCategories = await getLocalizedCollection('photoCategories', lang);
|
||||
const categoryLabels: Record<string, string> = {
|
||||
'blog': t('photo', 'photoFeed', lang),
|
||||
...Object.fromEntries(effectiveCategories.map(cat => [cat.id.replace(/\.(en|ar)$/, ''), cat.data.title]))
|
||||
...Object.fromEntries(localizedCategories.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 { getEntry } from 'astro:content';
|
||||
import { getLocalizedEntry } from '../../../utils/content-i18n';
|
||||
|
||||
interface Props {
|
||||
category: string;
|
||||
|
|
@ -13,8 +13,7 @@ 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 getEntry('photoCategories', entryId)
|
||||
?? await getEntry('photoCategories', category);
|
||||
const categoryData = await getLocalizedEntry('photoCategories', entryId, lang);
|
||||
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 { getCollection } from 'astro:content';
|
||||
import { getLocalizedCollection } from '../../../utils/content-i18n';
|
||||
import { Picture } from 'astro:assets';
|
||||
import { t, getPhotoBlogPath, getDateLocale, getPostBaseSlug, type Locale } from '../../../utils/i18n';
|
||||
|
||||
|
|
@ -20,8 +20,7 @@ const allImages = import.meta.glob<{ default: ImageMetadata }>(
|
|||
);
|
||||
|
||||
// Récupération des posts photo filtrés par langue
|
||||
const allPhotoBlogPosts = (await getCollection('photoBlogPosts'))
|
||||
.filter(post => (post.data.lang ?? 'fr') === lang);
|
||||
const allPhotoBlogPosts = await getLocalizedCollection('photoBlogPosts', 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(),
|
||||
category: z.enum(['dev', 'comedy', 'photo']),
|
||||
date: z.date().optional(),
|
||||
category: z.enum(['dev', 'comedy', 'photo']).optional(),
|
||||
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().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
featured: z.boolean().optional(),
|
||||
draft: z.boolean().optional(),
|
||||
lang: z.enum(['fr', 'en', 'ar']).default('fr'),
|
||||
}).transform((data) => ({
|
||||
...data,
|
||||
dateFormatted: formatDate(data.date, data.lang),
|
||||
dateFormatted: data.date ? formatDate(data.date, data.lang) : undefined,
|
||||
})),
|
||||
});
|
||||
|
||||
|
|
@ -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(),
|
||||
company: z.string().optional(),
|
||||
companyUrl: z.string().url().optional(),
|
||||
logo: z.string().optional(),
|
||||
location: z.string().optional(),
|
||||
startDate: z.string(),
|
||||
startDate: z.string().optional(),
|
||||
endDate: z.string().optional(),
|
||||
technologies: z.array(z.string()).optional(),
|
||||
type: z.enum(['employment', 'freelance', 'teaching', 'community', 'entrepreneurship']),
|
||||
featured: z.boolean().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
type: z.enum(['employment', 'freelance', 'teaching', 'community', 'entrepreneurship']).optional(),
|
||||
featured: z.boolean().optional(),
|
||||
draft: z.boolean().optional(),
|
||||
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(),
|
||||
coverImage: z.string(),
|
||||
date: z.date().optional(),
|
||||
coverImage: z.string().optional(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
featured: z.boolean().default(false),
|
||||
draft: z.boolean().default(false),
|
||||
featured: z.boolean().optional(),
|
||||
draft: z.boolean().optional(),
|
||||
lang: z.enum(['fr', 'en', 'ar']).default('fr'),
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
---
|
||||
role: "مهندس معماري للواجهات"
|
||||
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
|
||||
location: "عن بُعد / غرونوبل"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
---
|
||||
role: "Frontend Architect"
|
||||
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
|
||||
location: "Remote / Grenoble"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Architecte frontend"
|
|||
company: "ARaymond"
|
||||
companyUrl: "https://www.araymond.com/"
|
||||
logo: "araymond.png"
|
||||
location: "Grenoble"
|
||||
startDate: "2022-01"
|
||||
endDate: "2023-01"
|
||||
location: "Télétravail / Grenoble"
|
||||
startDate: "2022-07"
|
||||
endDate: "2023-07"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Nx", "Vite"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
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,13 +1,5 @@
|
|||
---
|
||||
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,13 +1,6 @@
|
|||
---
|
||||
role: "حرفي برمجيات / مؤسس مشارك"
|
||||
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"
|
||||
location: "عن بُعد / بوردو"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "Software Craftsman / Cofounder"
|
||||
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"
|
||||
location: "Remote / Bordeaux"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Software Craftsman / Cofondateur"
|
|||
company: "DisMoi"
|
||||
companyUrl: "https://github.com/dis-moi"
|
||||
logo: "dismoi.png"
|
||||
location: "Remote"
|
||||
startDate: "2019-01"
|
||||
endDate: "2021-06"
|
||||
location: "Télétravail / Bordeaux"
|
||||
startDate: "2019-02"
|
||||
endDate: "2021-04"
|
||||
technologies: ["TypeScript", "React.js", "Redux", "Web Extension", "Node.js"]
|
||||
type: "entrepreneurship"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
---
|
||||
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,12 +1,5 @@
|
|||
---
|
||||
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,9 +2,10 @@
|
|||
role: "Enseignant en développement"
|
||||
company: "ESN 81"
|
||||
companyUrl: "https://www.esn81.fr/"
|
||||
logo: "esn81.png"
|
||||
location: "Castres"
|
||||
startDate: "2020-09"
|
||||
endDate: "2021-06"
|
||||
startDate: "2020-01"
|
||||
endDate: "2021-07"
|
||||
technologies: ["JavaScript", "Node.js"]
|
||||
type: "teaching"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "مطوّر ويب"
|
||||
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"
|
||||
location: "بور مارلي"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
---
|
||||
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: "Versailles"
|
||||
startDate: "2002-06"
|
||||
endDate: "2002-12"
|
||||
location: "Port-Marly"
|
||||
startDate: "2002-02"
|
||||
endDate: "2002-11"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL"]
|
||||
type: "employment"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "مهندس برمجيات أول"
|
||||
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"
|
||||
location: "سان جيرمان أون لاي"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
---
|
||||
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: "Versailles"
|
||||
startDate: "2011-01"
|
||||
endDate: "2015-12"
|
||||
location: "Saint-Germain-en-Laye"
|
||||
startDate: "2011-12"
|
||||
endDate: "2015-06"
|
||||
technologies: ["PHP", "Symfony", "JavaScript", "MySQL", "Linux"]
|
||||
type: "employment"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
role: "مطوّر ويب وبرمجيات"
|
||||
company: "مستقل"
|
||||
location: "إيل دو فرانس"
|
||||
startDate: "2003-01"
|
||||
endDate: "2006-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL", "Linux"]
|
||||
type: "freelance"
|
||||
location: "شاتو"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
---
|
||||
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: "Île-de-France"
|
||||
startDate: "2003-01"
|
||||
location: "Chatou"
|
||||
startDate: "2003-08"
|
||||
endDate: "2006-12"
|
||||
technologies: ["PHP", "JavaScript", "HTML", "MySQL", "Linux"]
|
||||
type: "freelance"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
---
|
||||
role: "مدير تقني"
|
||||
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"
|
||||
location: "عن بُعد / ليون"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
---
|
||||
role: "CTO"
|
||||
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"
|
||||
location: "Remote / Lyon"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
role: "CTO"
|
||||
company: "GoBuild (Go-Decision)"
|
||||
companyUrl: "https://www.gobuild.fr"
|
||||
location: "Lyon"
|
||||
startDate: "2020-06"
|
||||
endDate: "2022-01"
|
||||
logo: "go-decision.png"
|
||||
location: "Télétravail / Lyon"
|
||||
startDate: "2020-02"
|
||||
endDate: "2022-06"
|
||||
technologies: ["TypeScript", "React.js", "Elixir", "PostgreSQL", "Docker"]
|
||||
type: "employment"
|
||||
type: "freelance"
|
||||
lang: "fr"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "مهندس برمجيات fullstack"
|
||||
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"
|
||||
location: "عن بُعد / باريس"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "Fullstack Software Engineer"
|
||||
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"
|
||||
location: "Remote / Paris"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ role: "Ingénieur logiciel fullstack"
|
|||
company: "Libeo"
|
||||
companyUrl: "https://www.libeo.io/"
|
||||
logo: "libeo.png"
|
||||
location: "Remote"
|
||||
startDate: "2021-01"
|
||||
endDate: "2021-06"
|
||||
location: "Télétravail / Paris"
|
||||
startDate: "2021-02"
|
||||
endDate: "2021-05"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "GraphQL"]
|
||||
type: "freelance"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
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,13 +1,6 @@
|
|||
---
|
||||
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: "Remote"
|
||||
startDate: "2023-02"
|
||||
endDate: "2024-01"
|
||||
location: "Télétravail"
|
||||
startDate: "2023-12"
|
||||
endDate: "2024-04"
|
||||
technologies: ["TypeScript", "React.js", "Node.js", "NestJS", "PostgreSQL"]
|
||||
type: "freelance"
|
||||
lang: "fr"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
---
|
||||
role: "مؤسّس ومدير عام"
|
||||
company: "Team Logics"
|
||||
location: "فرساي"
|
||||
startDate: "2007-01"
|
||||
endDate: "2011-12"
|
||||
technologies: ["PHP", "CakePHP", "JavaScript", "MySQL", "Linux"]
|
||||
type: "entrepreneurship"
|
||||
featured: true
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,5 @@
|
|||
---
|
||||
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,9 +1,10 @@
|
|||
---
|
||||
role: "Fondateur & CEO"
|
||||
company: "Team Logics"
|
||||
logo: "team-logics.png"
|
||||
location: "Versailles"
|
||||
startDate: "2007-01"
|
||||
endDate: "2011-12"
|
||||
endDate: "2011-11"
|
||||
technologies: ["PHP", "CakePHP", "JavaScript", "MySQL", "Linux"]
|
||||
type: "entrepreneurship"
|
||||
featured: true
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "مطوّر رئيسي"
|
||||
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
|
||||
location: "عن بُعد / مونتروي"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
---
|
||||
role: "Lead Developer"
|
||||
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
|
||||
location: "Remote / Montreuil"
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ role: "Lead Developer"
|
|||
company: "Urssaf Caisse nationale"
|
||||
companyUrl: "https://www.urssaf.fr/"
|
||||
logo: "urssaf.png"
|
||||
location: "Remote / Paris"
|
||||
location: "Télétravail / Montreuil"
|
||||
startDate: "2024-02"
|
||||
technologies: ["TypeScript", "React.js", "Publicodes", "Node.js", "GitHub"]
|
||||
type: "freelance"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
---
|
||||
role: "مطوّر رئيسي ← قائد تقني"
|
||||
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
|
||||
location: "سان دوني"
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,5 @@
|
|||
---
|
||||
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: "Paris"
|
||||
startDate: "2016-02"
|
||||
endDate: "2019-06"
|
||||
location: "Saint-Denis"
|
||||
startDate: "2016-01"
|
||||
endDate: "2019-03"
|
||||
technologies: ["TypeScript", "JavaScript", "React.js", "Redux", "redux-saga", "RxJS", "Node.js", "Webpack"]
|
||||
type: "freelance"
|
||||
featured: true
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
title: "تصوير إيرول"
|
||||
description: "أراد إيرول صورًا له لإعداد كتاب أعمال. عملنا طوال اليوم لتنويع الأجواء..."
|
||||
date: 2011-10-02
|
||||
coverImage: "18-Eroll-Shooting-1-19.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "عملية المحفظة 2012"
|
||||
description: "توزيع محافظ مدرسية مجانية في مدارس محرومة من طرف جمعية محلية (JCI)، طنجة، المغرب."
|
||||
date: 2012-09-30
|
||||
coverImage: "35-Moroccan-Schoolgirls.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "جولة في طنجة"
|
||||
description: "جولة فوتوغرافية في شوارع طنجة."
|
||||
date: 2012-05-26
|
||||
coverImage: "01-Observer-le-changement.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "هلسنكي"
|
||||
description: "اختفى الثلج من هلسنكي وسرعان ما أفسح المجال للربيع..."
|
||||
date: 2013-05-15
|
||||
coverImage: "01-Library-of-University-of-Helsinki.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "نزهة في إفران"
|
||||
description: "نزهة شتوية في جبال الأطلس المتوسط."
|
||||
date: 2013-01-13
|
||||
coverImage: "03-3.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "London Calling"
|
||||
description: "عطلة نهاية أسبوع فوتوغرافية في لندن."
|
||||
date: 2014-07-15
|
||||
coverImage: "01-The-sky-inside.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "تجوال في مدينة طنجة القديمة"
|
||||
description: "أثناء التجوال في أزقة طنجة القديمة، صادفت ساعاتيًا، ونجّارًا، وقمرًا عملاقًا..."
|
||||
date: 2014-08-10
|
||||
coverImage: "01-The-watchmaker.jpg"
|
||||
tags: []
|
||||
featured: true
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +4,6 @@ description: |
|
|||
إنيغما كانت مسابقة بحث عن الكنز بين المدارس نظّمها المركز العالي للدراسات CESIM يوم السبت، تحت عنوان «البحث عن كنز ابن بطوطة المنسي». 4 فرق طنجاوية دُعيت لتمثيل مؤسساتها.
|
||||
|
||||
تغطية.
|
||||
date: 2015-04-25
|
||||
coverImage: "01-Enigma-v1.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@ 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,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "لا رياح في لاس كويفاس"
|
||||
description: "كان من المفترض أن يكون يومًا مثاليًا لتطيير طائرتنا الورقية: مشمس وعاصف. مشمس كان، لكن الرياح لم تأتِ أبدًا."
|
||||
date: 2015-01-10
|
||||
coverImage: "13-No-wind-at-Las-Cuevas.jpg"
|
||||
tags: []
|
||||
featured: false
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
title: "زفاف أورور وتوما"
|
||||
description: "كان لي شرف ومتعة أن أكون شاهد توما في زفافه الجميل مع أورور. ليس سهلًا التصوير في نفس الوقت، لكن كل الصور مليئة بالحب."
|
||||
date: 2015-09-26
|
||||
coverImage: "10-Mariage-Aurore-Thomas-10.jpg"
|
||||
tags: []
|
||||
featured: true
|
||||
draft: false
|
||||
lang: ar
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,6 +1,5 @@
|
|||
{
|
||||
"title": "ثقافات وتقاليد",
|
||||
"subtitle": "ثراء التقاليد الإنسانية",
|
||||
"order": 4,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Cultures & Traditions",
|
||||
"subtitle": "Richness of human traditions",
|
||||
"order": 4,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "محرّكات",
|
||||
"subtitle": "ميكانيكا وقوة في حركة",
|
||||
"order": 7,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Engines",
|
||||
"subtitle": "Mechanics and power in motion",
|
||||
"order": 7,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "يوميات",
|
||||
"subtitle": "لحظات من الحياة اليومية",
|
||||
"order": 8,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Everyday Life",
|
||||
"subtitle": "Moments of everyday life",
|
||||
"order": 8,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "موسيقى واحتفالات",
|
||||
"subtitle": "نغمات وأغانٍ واهتزازات تحتفي بلحظات حياتنا الكبيرة والصغيرة",
|
||||
"order": 5,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Music & Celebrations",
|
||||
"subtitle": "Notes, songs and vibrations celebrating life's big and small moments",
|
||||
"order": 5,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "طبيعة",
|
||||
"subtitle": "سحر العالم الطبيعي",
|
||||
"order": 3,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Nature",
|
||||
"subtitle": "The magic of the natural world",
|
||||
"order": 3,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "مناظر طبيعية",
|
||||
"subtitle": "جمال المناظر والأماكن",
|
||||
"order": 2,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Landscapes",
|
||||
"subtitle": "Beauty of landscapes and places",
|
||||
"order": 2,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "بورتريهات",
|
||||
"subtitle": "تعابير ومشاعر ملتقطة",
|
||||
"order": 1,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Portraits",
|
||||
"subtitle": "Captured expressions and emotions",
|
||||
"order": 1,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "رياضة",
|
||||
"subtitle": "حركة وجهد وتجاوز للذات",
|
||||
"order": 6,
|
||||
"lang": "ar"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"title": "Sports",
|
||||
"subtitle": "Movement, effort and pushing limits",
|
||||
"order": 6,
|
||||
"lang": "en"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
---
|
||||
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,11 +1,6 @@
|
|||
---
|
||||
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,12 +1,6 @@
|
|||
---
|
||||
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,12 +1,6 @@
|
|||
---
|
||||
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,9 +1,6 @@
|
|||
---
|
||||
title: "ICU"
|
||||
description: "منصة مشاركة صور عبر الإنترنت، مشروع شخصي تاريخي."
|
||||
date: 2005-01-01
|
||||
category: "dev"
|
||||
technologies: ["PHP", "JavaScript", "MySQL"]
|
||||
lang: "ar"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
---
|
||||
title: "ICU"
|
||||
description: "Online photo sharing platform, a historical personal project."
|
||||
date: 2005-01-01
|
||||
category: "dev"
|
||||
technologies: ["PHP", "JavaScript", "MySQL"]
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
---
|
||||
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,12 +1,6 @@
|
|||
---
|
||||
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,9 +1,6 @@
|
|||
---
|
||||
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