First version

This commit is contained in:
2024-11-02 17:58:27 +01:00
parent f3a40e2804
commit e5a4ed6271
46 changed files with 6129 additions and 0 deletions

24
.dockerignore Normal file
View File

@ -0,0 +1,24 @@
node_modules
# Output
.output
.vercel
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
Dockerfile
.git/

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
node_modules
# Output
.output
.vercel
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

1
.npmrc Normal file
View File

@ -0,0 +1 @@
engine-strict=true

4
.prettierignore Normal file
View File

@ -0,0 +1,4 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock

15
.prettierrc Normal file
View File

@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

19
Dockerfile Normal file
View File

@ -0,0 +1,19 @@
FROM node:18.19-alpine AS builder
ARG VITE_EXTRA_HEAD
WORKDIR /app-builder
COPY ./package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM docker.io/library/nginx:1.27.2
# Enable 404.html page
RUN sed -i '12s/#//' /etc/nginx/conf.d/default.conf && cat /etc/nginx/conf.d/default.conf
COPY --from=builder /app-builder/build /usr/share/nginx/html

16
LICENCE Normal file
View File

@ -0,0 +1,16 @@
MIT License
Copyright (c) 2024-present Arnaud Scheffler
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,2 +1,24 @@
# arnaudscheffler.fr
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.

33
eslint.config.js Normal file
View File

@ -0,0 +1,33 @@
import prettier from 'eslint-config-prettier';
import js from '@eslint/js';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import ts from 'typescript-eslint';
export default ts.config(
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs['flat/recommended'],
prettier,
...svelte.configs['flat/prettier'],
{
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
},
{
files: ['**/*.svelte'],
languageOptions: {
parserOptions: {
parser: ts.parser
}
}
},
{
ignores: ['build/', '.svelte-kit/', 'dist/']
}
);

5086
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

37
package.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "landing",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "eslint . && prettier --check .",
"format": "prettier --write ."
},
"devDependencies": {
"@iconify/svelte": "^4.0.2",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/enhanced-img": "^0.3.10",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tailwindcss/typography": "^0.5.15",
"@types/eslint": "^9.6.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.7.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0",
"globals": "^15.0.0",
"prettier": "^3.3.2",
"prettier-plugin-svelte": "^3.2.6",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^3.4.9",
"typescript": "^5.0.0",
"typescript-eslint": "^8.0.0",
"vite": "^5.0.3"
}
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};

29
src/app.css Normal file
View File

@ -0,0 +1,29 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&family=Roboto:wght@300;400;600&display=swap');
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
@layer base {
body {
@apply bg-gray-100 text-gray-600 text-lg font-light font-roboto;
}
.font-roboto {
font-family: 'Roboto', sans-serif;
}
.font-poppins {
font-family: 'Poppins', sans-serif;
}
.font-outline-2 {
@apply text-transparent;
-webkit-text-stroke: 2px rgb(156 163 175);
}
.font-outline-3 {
@apply text-transparent;
-webkit-text-stroke: 3px rgb(156 163 175);
}
}

13
src/app.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

16
src/app.html Normal file
View File

@ -0,0 +1,16 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/png" href="%sveltekit.assets%/favicon-48x48.png" sizes="48x48" />
<link rel="icon" type="image/svg+xml" href="%sveltekit.assets%/favicon.svg" />
<link rel="shortcut icon" href="%sveltekit.assets%/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png" />
<link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div class="relative max-w-screen-xl mx-auto px-5">%sveltekit.body%</div>
</body>
</html>

17
src/lib/Error.svelte Normal file
View File

@ -0,0 +1,17 @@
<script lang="ts">
export let statusCode: number;
export let message: string;
</script>
<div class="flex flex-col justify-center items-center h-screen">
<div class="code flex text-9xl text-primary-600">{statusCode}</div>
<h1 class="text-4xl font-normal">{message}</h1>
<div class="mt-3 mb-1 flex justify-center">
<a
href="/"
class="bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded-full"
>
Retourner à l'accueil
</a>
</div>
</div>

24
src/lib/Footer.svelte Normal file
View File

@ -0,0 +1,24 @@
<script lang="ts">
import Icon from '@iconify/svelte';
import { firstName, lastName, socialNetworks } from './data/global';
const year = new Date().getFullYear();
</script>
<div class="flex flex-wrap items-center justify-center" id="contact">
{#each socialNetworks as socialNetwork}
<div class="p-5">
<a
href={socialNetwork.url}
target="_blank"
title={socialNetwork.title}
rel="noopener"
data-umami-event={`Social ${socialNetwork.title} button`}
>
<Icon icon={socialNetwork.icon} class="text-5xl" />
</a>
</div>
{/each}
</div>
<div class="pb-5 text-center text-lg font-light">© {year} {firstName} {lastName}</div>

72
src/lib/Navbar.svelte Normal file
View File

@ -0,0 +1,72 @@
<script lang="ts">
import Icon from '@iconify/svelte';
import { menu, title } from './data/global';
const logo = '/img/logo.svg';
export let mobileMenu: boolean;
</script>
<div class="flex items-center justify-between py-5">
<div class="flex items-center">
<a href="/">
<img src={logo} class="py-5 w-10 lg:w-14 min-w-10" alt="logo" title="logo" />
</a>
<a href="/">
<h1 class="text-lg lg:text-xl px-2 lg:px-3 font-medium">{title}</h1>
</a>
</div>
<div class="hidden lg:block">
<ul class="flex items-center">
{#each menu as item}
<li class="px-5">
<a
href={item.link}
title={item.name}
target={item.target}
class="cursor-pointer font-normal text-base"
data-umami-event={`Nav ${item.name}`}
>
{item.name}
</a>
</li>
{/each}
</ul>
</div>
<div class="block lg:hidden mt-2">
<button on:click={() => (mobileMenu = true)}>
<i class="bx bx-menu text-3xl"></i>
<Icon icon="bx-menu" class="text-3xl" />
</button>
</div>
</div>
<div
class="pointer-events-none fixed inset-0 min-h-screen bg-black bg-opacity-75 opacity-0 lg:hidden"
class:opacity-100={mobileMenu}
class:pointer-events-auto={mobileMenu}
on:click={() => (mobileMenu = false)}
>
<div class="absolute right-0 min-h-screen bg-gray-200 py-5 px-10 w-2/3 sm:w-1/3">
<button class="absolute top-0 right-0 mt-9 mr-4">
<i class="bx bx-x text-4xl"></i>
<Icon icon="bx-x" class="text-3xl" />
</button>
<ul class="mt-12 flex flex-col">
{#each menu as item}
<li class="py-2">
<a
href={item.link}
title={item.name}
target={item.target}
class="cursor-pointer font-normal"
data-umami-event={`Nav mobile ${item.name}`}
>
{item.name}
</a>
</li>
{/each}
</ul>
</div>
</div>

59
src/lib/data/global.ts Normal file
View File

@ -0,0 +1,59 @@
export const title = 'Arnaud Scheffler';
export const meta = {
description:
"Je suis Arnaud Scheffler, un passionné d'informatique avec plus de 7 ans d'expérience dans la création de solutions digitales innovantes et performantes."
};
export const firstName = 'Arnaud';
export const lastName = 'Scheffler';
export const menu = [
{
name: 'Compétences',
link: '/#skills'
},
// {
// name: 'Projets',
// link: '#projects'
// },
{
name: 'Expériences',
link: '/#experiences'
},
{
name: 'Formations',
link: '/#educations'
},
{
name: 'Contact',
link: '/#contact'
}
];
export const socialNetworks = [
{
title: 'Linkedin',
icon: 'mdi:linkedin',
url: 'https://www.linkedin.com/in/arnaud-scheffler/'
},
{
title: 'GitHub',
icon: 'mdi:github',
url: 'https://github.com/ArnaudScheffler'
},
{
title: 'Gitea',
icon: 'simple-icons:gitea',
url: 'https://git.s-algo.com/explore/repos/'
},
{
title: 'malt',
icon: 'simple-icons:malt',
url: 'https://www.malt.fr/profile/arnaudscheffler'
},
{
title: 'codeur.com',
icon: 'mdi:letter-c-box',
url: 'https://www.codeur.com/-arnaud-scheffler'
}
];

143
src/lib/data/landing.ts Normal file
View File

@ -0,0 +1,143 @@
import { meta, title } from './global';
export const title1 = 'Stratégie';
export const title2 = 'Réalisation';
export const title3 = 'Innovation';
export const text1 = meta.description;
export const text2 =
"J'accompagne les entreprises dans leurs projets stratégiques, de la conception à la mise en œuvre, pour des solutions numériques sur mesure et impactantes.";
export const text3 =
"Je consacre une part importante de mon temps à la veille technologique, ce qui me permet de rester à la pointe des innovations du secteur. Cette expertise me permet d'apporter des solutions novatrices aux entreprises, optimisant ainsi leurs performances et leur croissance. N'hésitez pas à découvrir comment je peux contribuer à votre projet !";
export const imgTitle = title;
export let skills: Skill[] = [
{
icon: 'eos-icons:project-outlined',
title: 'Gestion de projet',
text: 'Conduite de projets avec une approche axée sur la meilleure option stratégique, intégrant lanalyse des besoins, la gestion des contraintes, ladaptation aux changements, et le respect des coûts et délais.'
},
{
icon: 'mdi:code',
title: 'Développement full-stack',
text: 'Expertise en développement full-stack avec maîtrise de Python, Svelte, TypeScript et Supabase, intégrant des workflows CI/CD optimisés via GitHub Actions et GitLab pour des déploiements fluides et performants.'
},
{
icon: 'carbon:ai',
title: 'IA / Chatbot',
text: 'Développement de solutions IA et chatbots intelligents, intégrant des techniques de Retrieval-Augmented Generation (RAG) et des standards de sécurité avancés pour des interactions utilisateur enrichies, sécurisées, et des réponses précises adaptées aux besoins des entreprises.'
},
{
icon: 'mdi:docker',
title: 'Infrastructure',
text: 'Maîtrise des infrastructures modernes avec Docker, Kubernetes et le cloud pour déployer des applications SaaS robustes, en configurant les éléments nécessaires pour garantir performance et évolutivité.'
},
{
icon: 'mdi:web',
title: 'Création de site web',
text: 'Conception de sites web modernes et sur mesure, alliant simplicité et optimisation SEO pour une visibilité renforcée et une expérience utilisateur fluide.'
},
{
icon: 'material-symbols:home-work-outline',
title: 'Self hosting',
text: 'Mise en place de solutions en self-hosting, garantissant souveraineté et contrôle total des données pour les entreprises soucieuses de leur indépendance technologique et de la sécurité de leurs informations.'
}
];
export let experiences: Experience[] = [
{
company: 'Pyxis Support',
role: 'Directeur de la division digitale',
date: '2021 - 2024',
description: [
// "En tant que premier profil technique recruté, j'ai joué un rôle central dans la création dun nouvel axe commercial dans une entreprise de conseil spécialisée dans les marchés publics. Mon impact s'est concrétisé par le développement de deux applications SaaS innovantes : MA-IA et LEX-IA.",
// 'Maîtrise du Cycle de Vie des Produits SaaS',
// "J'ai orchestré l'intégralité du processus de création et de gestion de nos solutions :|- Analyse approfondie et optimisation du besoin|- Conception de solutions techniques|- Sélection des technologies|- Développement et tests|- Gestion du déploiement et de la maintenance opérationnelle|- Optimisation continue des coûts et de la performance",
// "Ma contribution s'est étendue au-delà du technique, influençant directement les décisions stratégiques de l'entreprise, notamment en matière de modèle économique et de partenariats.",
// 'Innovation technologique au cœur de la stratégie',
// "J'ai privilégié l'adoption de technologies émergentes pour garantir notre avantage concurrentiel :|- Front-end : Svelte|- Back-end : Supabase, FastAPI, Celery|- IA et ML : Intégration de LLM dans des Chatbots (Claude, ChatGPT)|- Recherche : Elasticsearch|- Infrastructure : Kubernetes, GitLab CI/CD, Grafana, Prometheus, Loki|- Outils complémentaires : Stripe, Brevo",
// 'Leadership et développement déquipe',
// "Au cours de ces trois années, j'ai constitué et dirigé une équipe pluridisciplinaire de 7 experts, comprenant des développeurs front-end, back-end, ainsi que des spécialistes en Machine Learning et Intelligence Artificielle. Mon rôle de manager a consisté à :|- Recruter des talents diversifiés et complémentaires|- Favoriser un environnement de travail collaboratif et innovant|- Assurer le développement professionnel de chaque membre de l'équipe",
// "Cette expérience démontre ma capacité à allier expertise technique, vision stratégique et leadership, contribuant ainsi de manière significative à la croissance et à l'innovation dans le secteur des marchés publics.",
"En tant que premier profil technique dans une entreprise de conseil spécialisée en marchés publics, j'ai joué un rôle clé dans la création d'un nouvel axe commercial, notamment en développant deux applications SaaS innovantes : MA-IA et LEX-IA.",
'Maîtrise du Cycle de Vie des Produits SaaS',
"J'ai piloté chaque étape du cycle de vie des produits SaaS : de lanalyse des besoins à la sélection technologique, en passant par le développement, le déploiement et la maintenance, tout en optimisant coûts et performances. Mon expertise a également influencé des décisions stratégiques liées aux modèles économiques et aux partenariats.",
'Innovation Technologique',
"J'ai intégré des technologies émergentes pour renforcer notre compétitivité, incluant Svelte (front-end), Supabase, FastAPI, Kubernetes, Elasticsearch, et des LLM pour les chatbots (Claude, ChatGPT), tout en assurant un écosystème fiable avec GitLab CI/CD et des outils de monitoring (Grafana, Prometheus, Loki).",
'Leadership et Développement dÉquipe',
"En trois ans, j'ai constitué et dirigé une équipe pluridisciplinaire de 7 experts, créant un environnement de travail innovant et propice au développement professionnel de chacun.",
"Cette expérience illustre mon aptitude à combiner expertise technique, vision stratégique et leadership, contribuant ainsi de manière significative à l'innovation dans le secteur des marchés publics."
]
},
{
company: 'Pyxis Support',
role: 'Développeur full stack - Freelance',
date: '2021 (2 mois)',
description: [
"En tant que freelance, j'ai conçu et mis en œuvre une solution complète et performante dans le domaine des marchés publics. Ce projet répond à un besoin crucial des entités publiques : simplifier et accélérer la rédaction de leurs appels d'offres.",
'Le fonctionnement de lapplication est le suivant :|- scrapping des sites sources (DCE et avis)|- traitement et consolidation des données|- mise à disposition dune interface de recherche avec de nombreux filtres',
'Stack technologique :|- Backend : Python, FastAPI|- Base de données : Elasticsearch|- Frontend : Plugin WordPress personnalisé|- Déploiement : Docker, VPS',
"En complément, j'ai développé une application novatrice permettant l'automatisation de traitements complexes sur des fichiers Excel. Cet outil, conçu pour être utilisé sans compétences techniques avancées, offre :|- Une interface utilisateur simple|- Des fichiers d'entrée et de sortie au format Excel|- Un système de configuration flexible pour personnaliser les opérations au format Excel",
'Ces solutions sur mesure démontrent ma capacité à répondre aux besoins spécifiques des clients en alliant expertise technique et compréhension approfondie des enjeux métier.'
]
},
{
company: 'FM Logistic Corporate',
role: 'Développeur Intégration Talend',
date: '2018 - 2021',
description: [
// "Au sein de l'équipe d'intégration, j'ai joué un rôle clé dans la conception et la mise en œuvre de solutions de transfert de données sophistiquées. Utilisant la plateforme Talend, j'ai développé des flux d'échange de données robustes et efficaces, tant pour les communications internes qu'externes. Ces solutions ont impliqué l'utilisation de divers patterns ETL, ESB et API REST, interconnectant une multitude de sources et destinations, notamment S3, SFTP et diverses bases de données.",
// 'Innovation dans la simplification des processus ETL',
// "Dans un souci d'optimisation, j'ai conçu et implémenté une solution novatrice visant à simplifier la mise en place de flux ETL. Cette approche a permis de réduire le déploiement de nouveaux flux à une simple étape de configuration. Le défi majeur consistait à développer cette solution sans recourir à de nouveaux outils, tout en minimisant les développements spécifiques pour obtenir l'adhésion de la direction. Cette innovation, désormais centrale dans les opérations de l'entreprise, témoigne de ma capacité à allier efficacité opérationnelle et vision stratégique.",
// "Contribution à la modernisation du Système d'Information",
// "Mon expertise a également été sollicitée dans le cadre de nombreux projets de modernisation du SI et de sélection d'outils technologiques. J'ai notamment participé activement à :|- L'évaluation et le choix des technologies permettant la création dune plateforme dindustrialisation de création dAPI|- La sélection dun outil de contrôle de code source et de CI/CD|- L'implémentation de solutions de Change Data Capture (CDC)",
// "Ces contributions démontrent ma capacité à naviguer dans un environnement technologique en constante évolution et à prendre des décisions éclairées pour l'avenir de l'infrastructure IT de l'entreprise."
"Au sein de l'équipe d'intégration, j'ai joué un rôle clé dans la conception et la mise en œuvre de solutions de transfert de données avancées à l'aide de la plateforme Talend. J'ai développé des flux d'échange de données robustes et efficaces pour les communications internes et externes, en intégrant divers patterns ETL, ESB et API REST pour interconnecter de multiples sources, telles que S3, SFTP et diverses bases de données.",
"Innovation dans l'Optimisation des Processus ETL",
"Pour simplifier les processus ETL, j'ai conçu une solution innovante qui réduit le déploiement de nouveaux flux à une simple étape de configuration. J'ai relevé le défi de développer cette solution sans outils supplémentaires et en limitant les développements spécifiques, obtenant ainsi l'adhésion de la direction. Cette approche, désormais au cœur des opérations de l'entreprise, illustre ma capacité à allier efficacité opérationnelle et vision stratégique.",
"Modernisation du Système d'Information",
"Mon expertise a également été mise à profit dans divers projets de modernisation du système d'information et de sélection d'outils technologiques, notamment en participant à :|- L'évaluation et le choix des technologies pour créer une plateforme dindustrialisation des API|- La sélection d'un outil de contrôle de code source et de CI/CD|- L'implémentation de solutions de Change Data Capture (CDC)",
"Ces contributions témoignent de ma capacité à évoluer dans un environnement technologique dynamique et à prendre des décisions éclairées pour lavenir de linfrastructure IT de l'entreprise."
]
}
];
export let educations: Education[] = [
{
title: "Master 2 spécialisation Systèmes d'Information Décisionnels",
location: 'UFR MIM Metz (57)',
date: '2020',
description:
'Fouille de données, Intelligence Artificielle, Conception de systèmes daide à la décision, Optimisation, Conception orientée objet avancée, Sécurité des systèmes, Projet suivant la méthodologie AGILE'
},
{
title: 'Licence Informatique',
location: 'Faculté des Sciences et Technologies Nancy (54)',
date: '2018',
description:
'Programmation orientée objet, interfaces graphiques, Web, réseau, optimisation, sécurité, théorie des langages Réalisation de nombreux projets (jeu en ligne, IA jeu Othello etc.)'
}
];
export let projects: Project[] = [
{
name: 'Mon super projet 1',
description: [
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A accusamus quo quas, ipsam commodi recusandae dolorum beatae soluta numquam impedit ad itaque ut facere cum. Asperiores voluptate quibusdam fuga ducimus?',
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A accusamus quo quas, ipsam commodi recusandae dolorum beatae soluta numquam impedit ad itaque ut facere cum. Asperiores voluptate quibusdam fuga ducimus?',
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A accusamus quo quas, ipsam commodi recusandae dolorum beatae soluta numquam impedit ad itaque ut facere cum. Asperiores voluptate quibusdam fuga ducimus?'
],
link: 'https://git.s-algo.com'
},
{
name: 'Mon super projet 2',
description: [
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A accusamus quo quas, ipsam commodi recusandae dolorum beatae soluta numquam impedit ad itaque ut facere cum. Asperiores voluptate quibusdam fuga ducimus?',
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A accusamus quo quas, ipsam commodi recusandae dolorum beatae soluta numquam impedit ad itaque ut facere cum. Asperiores voluptate quibusdam fuga ducimus?',
'Lorem ipsum dolor sit amet consectetur adipisicing elit. A accusamus quo quas, ipsam commodi recusandae dolorum beatae soluta numquam impedit ad itaque ut facere cum. Asperiores voluptate quibusdam fuga ducimus?'
]
}
];

View File

@ -0,0 +1,20 @@
<script lang="ts">
export let educations: Education[];
</script>
<div class="-mx-5 grid md:grid-cols-2 gap-7 p-5">
{#each educations as education}
<div class="rounded-xl p-7 sm:p-9 lg:px-6 xl:px-9 bg-gray-50">
<div>
<h3 class="text-lg font-medium sm:text-xl lg:text-lg xl:text-xl">
{education.title}
</h3>
<h4 class="text-l font-light">{education.location}</h4>
<h4 class="mb-4 text-l font-light">{education.date}</h4>
<p class="text-lg font-light">
{education.description}
</p>
</div>
</div>
{/each}
</div>

View File

@ -0,0 +1,35 @@
<script lang="ts">
export let experiences: Experience[];
</script>
<div class="relative mx-auto mb-6 md:mt-12 flex w-full flex-col">
<span class="left-1/4 absolute inset-y-0 ml-10 hidden w-0.5 bg-gray-300 md:block"></span>
{#each experiences as experience}
<div class="mt-8 flex flex-col text-center md:flex-row md:text-left">
<div class="md:w-1/4">
<div class="justify-center md:justify-start font-light text-3xl">
{experience.company}
</div>
</div>
<div class="md:w-3/4">
<div class="relative flex md:pl-16">
<span
class="absolute left-7 top-1 hidden h-6 w-6 rounded-full border-2 border-gray-300 bg-white md:block"
></span>
<div class="mt-1 flex">
<div class="md:-mt-1 md:pl-16">
<span class="block font-semibold">{experience.date}</span>
<span class="block pt-2 font-header text-xl font-semibold">{experience.role}</span>
<span class="block pt-2 text-xl font-light">
{#each experience.description as text}
<p class="py-2">{@html text.replaceAll('|', '<br/>')}</p>
{/each}
</span>
</div>
</div>
</div>
</div>
</div>
{/each}
</div>

View File

@ -0,0 +1,46 @@
<script lang="ts">
import { imgTitle, text1, text2, text3, title1, title2, title3 } from '$lib/data/landing';
</script>
<div class="w-full flex items-center justify-center">
<div class="w-full">
<div class="md:flex lg:space-x-5 xl:space-x-10 items-center py-2">
<div
class="text-5xl sm:text-7xl lg:text-8xl xl:text-8xl text-center md:text-left text-gray-400 font-poppins font-semibold pb-5 md:pb-0"
>
{title1.toUpperCase()}
</div>
<div class="text-lg xl:text-xl text-center font-light p-2 md:p-10">
{text1}
</div>
</div>
<div class="md:flex items-center justify-center py-2 space-x-5 xl:space-x-10">
<div class="items-center justify-center flex p-5 md:p-0">
<enhanced:img
src="/static/img/profile.jpg"
class="w-28 xl:w-36 rounded-full"
alt={imgTitle}
title={imgTitle}
/>
</div>
<div
class="text-5xl sm:text-7xl lg:text-8xl xl:text-8xl font-outline-2 lg:font-outline-3 text-center md:text-right font-poppins font-semibold py-5 md:py-0"
>
{title2.toUpperCase()}
</div>
</div>
<div class="md:flex lg:space-x-5 xl:space-x-10 items-center py-2">
<div class="text-lg xl:text-xl text-center font-light p-2 md:p-10">
{text2}
</div>
<div
class="text-5xl sm:text-7xl lg:text-8xl xl:text-8xl text-gray-600 text-center md:text-right font-poppins font-semibold py-5 md:py-0"
>
{title3.toUpperCase()}
</div>
</div>
</div>
</div>
<div class="text-lg xl:text-xl text-center font-light p-2 md:p-10">
{text3}
</div>

View File

@ -0,0 +1,23 @@
<script lang="ts">
export let projects: Project[];
</script>
{#each projects as project}
<div class="mb-9 px-7 p-5 sm:p-9 lg:px-6 xl:px-9 border-b-2 border-gray-300 last:border-b-0">
<div>
<h3 class="mb-4 font-light text-3xl">{project.name}</h3>
{#each project.description as text}
<p class="md:pl-10 py-2 text-xl font-light">
{text}
</p>
{/each}
</div>
{#if project.link}
<div class="mt-5">
<a href={project.link} target="_blank" class="text-blue-500 hover:underline"
>{project.link}</a
>
</div>
{/if}
</div>
{/each}

View File

@ -0,0 +1,21 @@
<script lang="ts">
import Icon from '@iconify/svelte';
export let skills: Skill[];
</script>
<div class="-mx-5 grid md:grid-cols-2 lg:grid-cols-3 gap-7 text-center p-5">
{#each skills as skill}
<!-- <div class="px-5"> -->
<!-- w-full md:basis-1/2 lg:basis-1/3 -->
<div class="rounded-xl bg-gray-50 p-2 sm:p-8 lg:px-6 xl:px-9">
<Icon icon={skill.icon} class="text-5xl mx-auto mb-5" />
<div>
<h3 class="mb-4 text-lg font-medium sm:text-xl lg:text-lg xl:text-xl">{skill.title}</h3>
<p class="text-lg font-light">
{skill.text}
</p>
</div>
</div>
<!-- </div> -->
{/each}
</div>

View File

@ -0,0 +1,10 @@
<script lang="ts">
export let id: string | undefined = undefined;
</script>
<h2
class="text-4xl md:text-5xl lg:text-7xl p-5 text-center font-medium font-poppins text-gray-400"
{id}
>
<slot />
</h2>

31
src/lib/landing/type.d.ts vendored Normal file
View File

@ -0,0 +1,31 @@
type Skill = {
icon: string;
title: string;
text: string;
};
type Experience = {
company: string;
role: string;
date: string;
description: string[];
};
type Education = {
title: string;
location: string;
date: string;
description: string;
};
type Project = {
name: string;
link?: string;
description: string[];
};
type Testimonial = {
text: string;
name: string;
role: string;
};

15
src/routes/+layout.svelte Normal file
View File

@ -0,0 +1,15 @@
<script lang="ts">
import { title, meta } from '$lib/data/global';
import '../app.css';
let { children } = $props();
</script>
{@render children()}
<svelte:head>
<title>{title}</title>
<meta name="description" content={meta.description} />
{#if import.meta.env.VITE_EXTRA_HEAD}
{@html import.meta.env.VITE_EXTRA_HEAD}
{/if}
</svelte:head>

1
src/routes/+layout.ts Normal file
View File

@ -0,0 +1 @@
export const prerender = true;

37
src/routes/+page.svelte Normal file
View File

@ -0,0 +1,37 @@
<script lang="ts">
import { educations, experiences, projects, skills } from '$lib/data/landing';
import Footer from '$lib/Footer.svelte';
import Educations from '$lib/landing/Educations.svelte';
import Experiences from '$lib/landing/Experiences.svelte';
import Hero from '$lib/landing/Hero.svelte';
import Projects from '$lib/landing/Projects.svelte';
import Skills from '$lib/landing/Skills.svelte';
import Title from '$lib/landing/Title.svelte';
import Navbar from '$lib/Navbar.svelte';
let mobileMenu = false;
</script>
<div class:overflow-hidden={mobileMenu} class:max-h-screen={mobileMenu}>
<nav>
<Navbar bind:mobileMenu />
</nav>
<main>
<Hero />
<Title id={'skills'}>Compétences</Title>
<Skills {skills} />
<!-- <Title id={'projects'}>Projets</Title>
<Projects {projects} /> -->
<Title id={'experiences'}>Expériences professionelles</Title>
<Experiences {experiences} />
<Title id={'educations'}>Formations</Title>
<Educations {educations} />
</main>
<footer>
<Footer />
</footer>
</div>

View File

@ -0,0 +1,5 @@
<script lang="ts">
import Error from '$lib/Error.svelte';
</script>
<Error statusCode={404} message="Page non trouvée" />

View File

@ -0,0 +1,5 @@
<script lang="ts">
import Error from '$lib/Error.svelte';
</script>
<Error statusCode={500} message="Erreur interne" />

BIN
static/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/favicon-48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

3
static/favicon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

143
static/img/logo.svg Normal file
View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="512"
height="512"
viewBox="0 0 135.46666 135.46666"
version="1.1"
id="svg1"
xml:space="preserve"
sodipodi:docname="logo_v3.svg"
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="0.34346083"
inkscape:cx="91.713516"
inkscape:cy="598.32151"
inkscape:window-width="1728"
inkscape:window-height="1052"
inkscape:window-x="0"
inkscape:window-y="65"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" /><defs
id="defs1"><inkscape:path-effect
effect="bspline"
id="path-effect14"
is_visible="true"
lpeversion="1.3"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false"
uniform="false" /><inkscape:path-effect
effect="bspline"
id="path-effect7"
is_visible="true"
lpeversion="1.3"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false"
uniform="false" /><inkscape:path-effect
effect="fillet_chamfer"
id="path-effect6"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" /><inkscape:path-effect
effect="bspline"
id="path-effect5"
is_visible="true"
lpeversion="1.3"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false"
uniform="false" /><inkscape:path-effect
effect="bspline"
id="path-effect4"
is_visible="true"
lpeversion="1.3"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false"
uniform="false" /><inkscape:path-effect
effect="bspline"
id="path-effect3"
is_visible="true"
lpeversion="1.3"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false"
uniform="false" /><inkscape:path-effect
effect="spiro"
id="path-effect1"
is_visible="true"
lpeversion="1" /></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
transform="translate(10.307214,-7.3421366)"><path
style="fill:none;stroke:#4d4d4d;stroke-width:10;stroke-linecap:round;stroke-dasharray:none"
d="m 324.81285,205.70011 36.5506,-73.04499"
id="path1"
inkscape:path-effect="#path-effect1"
inkscape:original-d="m 324.81285,205.70011 c 12.02772,-23.24 24.52288,-49.805 36.5506,-73.04499"
transform="matrix(0.41079526,0,0,0.41079526,-128.52919,20.711065)"
sodipodi:nodetypes="cc" /><path
style="display:inline;fill:none;stroke:#4d4d4d;stroke-width:6.28;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
d="m 54.625658,108.20078 c 14.626665,29.17935 29.252994,58.35803 36.923402,73.66005 7.670409,15.30202 8.384199,16.72599 9.08934,17.43798 0.70515,0.712 1.40163,0.712 2.09812,0.712 19.57162,0 39.14324,0 58.71486,0"
id="path2"
inkscape:path-effect="#path-effect14"
inkscape:original-d="m 54.625658,108.20078 c 14.626667,29.17935 29.252993,58.35803 43.87999,87.53804 0.713821,1.42403 1.427608,2.848 2.141412,4.27199 0.69649,0 2.08946,0 2.08946,0 0,0 39.14324,0 58.71486,0"
transform="matrix(0.65415066,0,0,0.65415066,-0.85310631,-25.60325)"
sodipodi:nodetypes="cccsc" /><path
style="display:inline;fill:none;stroke:#4d4d4d;stroke-width:10;stroke-linecap:round;stroke-dasharray:none"
d="m 642.00137,170.97712 c -0.42021,-4.45345 -0.84043,-8.9069 -2.83709,-13.94948 -1.99667,-5.04258 -5.56979,-10.67427 -10.7159,-14.81645 -5.14611,-4.14218 -11.8652,-6.79482 -20.20745,-8.1554 -8.34226,-1.36057 -18.30768,-1.42907 -28.27309,-1.49757"
id="path3"
inkscape:path-effect="#path-effect3"
inkscape:original-d="m 642.00137,170.97712 c -0.42021,-4.45345 -0.84043,-8.9069 -1.26064,-13.36036 -3.57312,-5.6317 -7.14624,-11.26339 -10.71936,-16.8951 -6.7191,-2.65264 -13.43819,-5.30529 -20.15729,-7.95794 -9.96541,-0.0685 -19.93083,-0.137 -29.89624,-0.2055"
sodipodi:nodetypes="csccc"
transform="matrix(0.41079526,0,0,0.41079526,-153.78127,20.666452)" /><path
style="fill:none;stroke:#4d4d4d;stroke-width:10;stroke-linecap:round;stroke-dasharray:none"
d="m 544.63766,131.60872 c -5.73181,-0.28109 -11.46357,-0.56218 -17.05465,-2.88057 -5.59108,-2.31839 -11.04137,-6.67401 -14.90112,-12.82017 -3.85975,-6.14617 -6.12869,-14.08238 -5.63932,-22.036628 0.48937,-7.954249 3.73697,-15.925635 8.64026,-21.930044 4.90329,-6.00441 11.46168,-10.041126 20.31931,-11.745829 8.85762,-1.704703 20.01344,-1.077191 35.58006,-0.749476 15.56662,0.327715 35.5426,0.355594 55.519,0.383474"
id="path6"
inkscape:path-effect="#path-effect7"
inkscape:original-d="m 544.63766,131.60872 c -5.73181,-0.28109 -11.46357,-0.56218 -17.19535,-0.84327 -5.45038,-4.35569 -10.90067,-8.71131 -16.35112,-13.06705 -2.26905,-7.93659 -4.53799,-15.8728 -6.80705,-23.809431 3.2478,-7.971865 6.4954,-15.943253 9.7432,-23.915115 6.55878,-4.036956 13.11717,-8.073673 19.67595,-12.110627 11.15647,0.627549 22.31229,1.255061 33.46876,1.88261 19.97677,0.02788 39.95275,0.05576 59.92915,0.08364"
sodipodi:nodetypes="cccccccc"
transform="matrix(0.41079526,0,0,0.41079526,-148.56417,20.666452)" /></g></svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
static/img/profile.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

21
static/site.webmanifest Normal file
View File

@ -0,0 +1,21 @@
{
"name": "Arnaud Scheffler",
"short_name": "Arnaud Scheffler",
"icons": [
{
"src": "/web-app-manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/web-app-manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

18
svelte.config.js Normal file
View File

@ -0,0 +1,18 @@
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
}
};
export default config;

12
tailwind.config.ts Normal file
View File

@ -0,0 +1,12 @@
import typography from '@tailwindcss/typography';
import type { Config } from 'tailwindcss';
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: [typography]
} as Config;

19
tsconfig.json Normal file
View File

@ -0,0 +1,19 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}

7
vite.config.ts Normal file
View File

@ -0,0 +1,7 @@
import { enhancedImages } from '@sveltejs/enhanced-img';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [enhancedImages(), sveltekit()]
});