1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-05-29 22:37:44 +02:00

Compare commits

...

22 Commits

Author SHA1 Message Date
117c41b1c3 chore(release): 2.12.0 [skip ci] 2023-07-02 14:59:12 +00:00
b92704b77d feat: increase duration work experience Numerize 2023-07-02 16:50:32 +02:00
bab7581283 fix: update dependencies to latest 2023-07-02 16:42:39 +02:00
988fceb2aa chore(release): 2.11.0 [skip ci] 2023-06-18 10:23:59 +00:00
5211ba1489 feat(skills): add Arch Linux 2023-06-18 12:18:24 +02:00
6886480cef chore(release): 2.10.0 [skip ci] 2023-06-16 21:30:51 +00:00
d78e50638e test: fix with new anchor link behavior in blog posts 2023-06-16 23:26:09 +02:00
3b76195d71 feat(blog): add anchor links for titles/headers 2023-06-16 23:14:25 +02:00
2dc63ba933 chore: maintenance 2023-06-16 22:56:53 +02:00
336f067c52 fix(posts): add explanations for Git (cherry-pick + merge squash) 2023-06-16 22:36:20 +02:00
5fd7f77b6d fix: justify align text in blog posts 2023-06-16 21:48:47 +02:00
db0c708c04 chore(release): 2.9.0 [skip ci] 2023-05-31 18:39:59 +00:00
9d44671fed feat: continue migrating to full name instead of nickname 2023-05-31 20:09:08 +02:00
7bcc5f972c chore(release): 2.8.0 [skip ci] 2023-05-30 19:57:02 +00:00
61172d59e3 feat: migrate progressively to full name instead of nickname 2023-05-30 21:51:27 +02:00
7c0f11ab7d chore(release): 2.7.3 [skip ci] 2023-05-29 15:45:42 +00:00
670897fa78 fix: improve spelling consistency 2023-05-29 17:44:26 +02:00
b88246b668 chore: usage of next start 2023-05-29 17:33:45 +02:00
87fbfe4940 chore(release): 2.7.2 [skip ci] 2023-05-29 15:29:07 +00:00
271aa60247 test: update with new changes 2023-05-29 17:26:06 +02:00
ba34e314c9 fix: update name with full name and nickname 2023-05-29 17:10:14 +02:00
f41bc644b1 fix(deps): remove next-pwa dependency 2023-05-29 16:24:49 +02:00
62 changed files with 2768 additions and 3877 deletions

View File

@ -1,5 +1,5 @@
{ {
"name": "Divlo", "name": "theoludwig",
"dockerComposeFile": "./docker-compose.yml", "dockerComposeFile": "./docker-compose.yml",
"service": "workspace", "service": "workspace",
"workspaceFolder": "/workspace", "workspaceFolder": "/workspace",

View File

@ -1,2 +1,2 @@
COMPOSE_PROJECT_NAME=divlo COMPOSE_PROJECT_NAME=theoludwig
PORT=3000 PORT=3000

View File

@ -16,7 +16,7 @@ jobs:
language: ['javascript'] language: ['javascript']
steps: steps:
- uses: 'actions/checkout@v3.5.2' - uses: 'actions/checkout@v3.5.3'
- name: 'Initialize CodeQL' - name: 'Initialize CodeQL'
uses: 'github/codeql-action/init@v2' uses: 'github/codeql-action/init@v2'

View File

@ -10,7 +10,7 @@ jobs:
build: build:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.5.2' - uses: 'actions/checkout@v3.5.3'
- name: 'Setup Node.js' - name: 'Setup Node.js'
uses: 'actions/setup-node@v3.6.0' uses: 'actions/setup-node@v3.6.0'

View File

@ -10,7 +10,7 @@ jobs:
lint: lint:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.5.2' - uses: 'actions/checkout@v3.5.3'
- name: 'Setup Node.js' - name: 'Setup Node.js'
uses: 'actions/setup-node@v3.6.0' uses: 'actions/setup-node@v3.6.0'

View File

@ -8,7 +8,7 @@ jobs:
release: release:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.5.2' - uses: 'actions/checkout@v3.5.3'
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false

View File

@ -10,7 +10,7 @@ jobs:
test-unit: test-unit:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.5.2' - uses: 'actions/checkout@v3.5.3'
- name: 'Setup Node.js' - name: 'Setup Node.js'
uses: 'actions/setup-node@v3.6.0' uses: 'actions/setup-node@v3.6.0'
@ -27,7 +27,7 @@ jobs:
test-e2e: test-e2e:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.5.0' - uses: 'actions/checkout@v3.5.3'
- name: 'Setup Node.js' - name: 'Setup Node.js'
uses: 'actions/setup-node@v3.6.0' uses: 'actions/setup-node@v3.6.0'

View File

@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
<contact@divlo.fr>. <contact@theoludwig.fr>.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View File

@ -1,10 +1,10 @@
# 💡 Contributing # 💡 Contributing
Thanks a lot for your interest in contributing to **divlo.fr**! 🎉 Thanks a lot for your interest in contributing to **theoludwig.fr**! 🎉
## Code of Conduct ## Code of Conduct
**divlo.fr** adopted the [Contributor Covenant](https://www.contributor-covenant.org/) as its Code of Conduct, and we expect project participants to adhere to it. Please read [the full text](./CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated. **theoludwig.fr** adopted the [Contributor Covenant](https://www.contributor-covenant.org/) as its Code of Conduct, and we expect project participants to adhere to it. Please read [the full text](./CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated.
## Types of contributions ## Types of contributions
@ -15,13 +15,13 @@ Thanks a lot for your interest in contributing to **divlo.fr**! 🎉
## Pull Requests ## Pull Requests
- **Please first discuss** the change you wish to make via [issue](https://github.com/Divlo/Divlo/issues) before making a change. It might avoid a waste of your time. - **Please first discuss** the change you wish to make via [issue](https://github.com/theoludwig/theoludwig/issues) before making a change. It might avoid a waste of your time.
- Ensure your code respect linting. - Ensure your code respect linting.
- Make sure your **code passes the tests**. - Make sure your **code passes the tests**.
If you're adding new features to **divlo.fr**, please include tests. If you're adding new features to **theoludwig.fr**, please include tests.
## Commits ## Commits
@ -29,7 +29,7 @@ The commit message guidelines adheres to [Conventional Commits](https://www.conv
## Getting Started ## Getting Started
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/Divlo/Divlo) [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/theoludwig/theoludwig)
### Prerequisites ### Prerequisites
@ -40,10 +40,10 @@ The commit message guidelines adheres to [Conventional Commits](https://www.conv
```sh ```sh
# Clone the repository # Clone the repository
git clone https://github.com/Divlo/Divlo.git git clone git@github.com:theoludwig/theoludwig.git
# Go to the project root # Go to the project root
cd Divlo cd theoludwig
# Configure environment variables # Configure environment variables
cp .env.example .env cp .env.example .env
@ -68,4 +68,4 @@ docker compose up --build
### Services started ### Services started
- website: `http://127.0.0.1:3000` - `website`: <http://127.0.0.1:3000>

View File

@ -1,9 +1,9 @@
FROM node:18.16.0 AS builder-dependencies FROM node:18.16.1 AS builder-dependencies
WORKDIR /usr/src/application WORKDIR /usr/src/application
COPY ./package*.json ./ COPY ./package*.json ./
RUN npm clean-install RUN npm clean-install
FROM node:18.16.0 AS builder FROM node:18.16.1 AS builder
WORKDIR /usr/src/application WORKDIR /usr/src/application
COPY --from=builder-dependencies /usr/src/application/node_modules ./node_modules COPY --from=builder-dependencies /usr/src/application/node_modules ./node_modules
COPY ./ ./ COPY ./ ./

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) Divlo Copyright (c) Théo LUDWIG
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,18 +1,18 @@
<h1 align="center"><a href="https://divlo.fr/">Divlo</a></h1> <h1 align="center"><a href="https://theoludwig.fr/">Théo LUDWIG</a></h1>
<p align="center"> <p align="center">
<strong>Developer Full Stack • Open-Source enthusiast</strong> <strong>Developer Full Stack • Open-Source enthusiast</strong>
</p> </p>
<p align="center"> <p align="center">
<a href="https://github.com/Divlo"><img alt="GitHub" src="https://img.shields.io/badge/-GitHub-5A5A5A?style=flat&labelColor=5A5A5A&logo=github&logoColor=white"/></a> <a href="https://github.com/theoludwig"><img alt="GitHub" src="https://img.shields.io/badge/-GitHub-5A5A5A?style=flat&labelColor=5A5A5A&logo=github&logoColor=white"/></a>
<a href="https://gitlab.com/Divlo"><img alt="GitLab" src="https://img.shields.io/badge/-GitLab-303030?style=flat&labelColor=303030&logo=gitlab&logoColor=white"/></a> <a href="https://gitlab.com/theoludwig"><img alt="GitLab" src="https://img.shields.io/badge/-GitLab-303030?style=flat&labelColor=303030&logo=gitlab&logoColor=white"/></a>
<a href="https://www.npmjs.com/~divlo"><img alt="npm" src="https://img.shields.io/badge/-npm-c4302b?style=flat&labelColor=c4302b&logo=npm&logoColor=white"/></a> <a href="https://www.npmjs.com/~theoludwig"><img alt="npm" src="https://img.shields.io/badge/-npm-c4302b?style=flat&labelColor=c4302b&logo=npm&logoColor=white"/></a>
<a href="https://twitter.com/Divlo_FR"><img alt="Twitter" src="https://img.shields.io/badge/-Twitter-1ca0f1?style=flat&labelColor=1ca0f1&logo=twitter&logoColor=white"/></a> <a href="https://twitter.com/theoludwig_"><img alt="Twitter" src="https://img.shields.io/badge/-Twitter-1ca0f1?style=flat&labelColor=1ca0f1&logo=twitter&logoColor=white"/></a>
<a href="https://www.youtube.com/channel/UCfEKQzI3c8vmZOrsTOi5spA"><img alt="YouTube" src="https://img.shields.io/badge/-YouTube-c4302b?style=flat&labelColor=c4302b&logo=youtube&logoColor=white"/></a> <a href="https://www.youtube.com/@theo_ludwig"><img alt="YouTube" src="https://img.shields.io/badge/-YouTube-c4302b?style=flat&labelColor=c4302b&logo=youtube&logoColor=white"/></a>
<a href="https://www.twitch.tv/divlo"><img alt="Twitch" src="https://img.shields.io/badge/-Twitch-9147FF?style=flat&labelColor=9147FF&logo=twitch&logoColor=white"/></a> <a href="https://www.twitch.tv/theoludwig"><img alt="Twitch" src="https://img.shields.io/badge/-Twitch-9147FF?style=flat&labelColor=9147FF&logo=twitch&logoColor=white"/></a>
<a href="https://www.divlo.fr"><img alt="Website" src="https://img.shields.io/badge/-Website-181818?style=flat&labelColor=181818&logo=Google-Chrome&logoColor=white"/></a> <a href="https://theoludwig.fr/"><img alt="Website" src="https://img.shields.io/badge/-Website-181818?style=flat&labelColor=181818&logo=Google-Chrome&logoColor=white"/></a>
<a href="mailto:contact@divlo.fr"><img alt="Email" src="https://img.shields.io/badge/-contact@divlo.fr-2F7EBE?style=flat&labelColor=2F7EBE&logo=minutemailer&logoColor=white"/></a> <a href="mailto:contact@theoludwig.fr"><img alt="Email" src="https://img.shields.io/badge/-contact@theoludwig.fr-2F7EBE?style=flat&labelColor=2F7EBE&logo=minutemailer&logoColor=white"/></a>
</p> </p>
<hr /> <hr />
@ -21,16 +21,16 @@
```json ```json
{ {
"name": "Divlo", "name": "Théo LUDWIG",
"pronouns": "He/Him", "pronouns": "He/Him",
"birthDate": "31/03/2003", "birthDate": "31/03/2003",
"nationality": "Alsace, France", "nationality": "Alsace, France",
"interests": ["Open-Source enthusiast", "Passionate about High-Tech"], "interests": ["Open-Source enthusiast", "Passionate about High-Tech"],
"skills": { "skills": {
"programmingLanguages": ["JavaScript/TypeScript", "Python", "C/C++", "PHP"], "programmingLanguages": ["JavaScript/TypeScript", "Python", "C/C++", "PHP"],
"frontEnd": ["HTML", "CSS", "Tailwind CSS", "React.js/Next.js"], "frontend": ["HTML", "CSS", "Tailwind CSS", "React.js/Next.js"],
"backEnd": ["Laravel", "Node.js", "Fastify", "PostgreSQL"], "backend": ["Laravel", "Node.js", "Fastify", "PostgreSQL"],
"tools": ["GNU/Linux", "Ubuntu", "Visual Studio Code", "Git", "Docker"] "tools": ["GNU/Linux", "Arch Linux", "Visual Studio Code", "Git", "Docker"]
} }
} }
``` ```
@ -40,6 +40,6 @@
## 📈 Statistics ## 📈 Statistics
<p align=center> <p align=center>
<img height=175 align="center" src="https://github-readme-stats.vercel.app/api?username=Divlo&show_icons=true&theme=dark" /> <img height=175 align="center" src="https://github-readme-stats.vercel.app/api?username=theoludwig&show_icons=true&theme=dark" />
<img height=175 align="center" src="https://github-readme-stats.vercel.app/api/top-langs/?username=Divlo&hide=html,css,javascript&langs_count=8&layout=compact&theme=dark" /> <img height=175 align="center" src="https://github-readme-stats.vercel.app/api/top-langs/?username=theoludwig&hide=html,css,javascript&langs_count=8&layout=compact&theme=dark" />
</p> </p>

View File

@ -11,7 +11,7 @@ export const Footer: React.FC<FooterProps> = (props) => {
const { version } = props const { version } = props
const versionLink = useMemo(() => { const versionLink = useMemo(() => {
return `https://github.com/Divlo/Divlo/releases/tag/v${version}` return `https://github.com/theoludwig/theoludwig/releases/tag/v${version}`
}, [version]) }, [version])
return ( return (
@ -21,7 +21,7 @@ export const Footer: React.FC<FooterProps> = (props) => {
href='/' href='/'
className='text-yellow hover:underline dark:text-yellow-dark' className='text-yellow hover:underline dark:text-yellow-dark'
> >
Divlo Théo LUDWIG
</Link>{' '} </Link>{' '}
| {t('common:all-rights-reserved')} | {t('common:all-rights-reserved')}
</p> </p>

View File

@ -9,10 +9,10 @@ interface HeadProps {
export const Head: React.FC<HeadProps> = (props) => { export const Head: React.FC<HeadProps> = (props) => {
const { const {
title = 'Divlo', title = 'Théo LUDWIG',
image = 'https://divlo.fr/images/icons/icon-96x96.png', image = 'https://theoludwig.fr/images/icon-96x96.png',
description = 'Divlo - Developer Full Stack • Passionate about High-Tech', description = 'Théo LUDWIG - Developer Full Stack • Passionate about High-Tech',
url = 'https://divlo.fr/' url = 'https://theoludwig.fr/'
} = props } = props
return ( return (
@ -23,7 +23,7 @@ export const Head: React.FC<HeadProps> = (props) => {
{/* Meta Tag */} {/* Meta Tag */}
<meta name='viewport' content='width=device-width, initial-scale=1.0' /> <meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='description' content={description} /> <meta name='description' content={description} />
<meta name='Language' content='fr, en' /> <meta name='Language' content='fr-FR, en-US' />
<meta name='theme-color' content='#ffd800' /> <meta name='theme-color' content='#ffd800' />
{/* Open Graph Metadata */} {/* Open Graph Metadata */}
@ -32,7 +32,7 @@ export const Head: React.FC<HeadProps> = (props) => {
<meta property='og:url' content={url} /> <meta property='og:url' content={url} />
<meta property='og:image' content={image} /> <meta property='og:image' content={image} />
<meta property='og:description' content={description} /> <meta property='og:description' content={description} />
<meta property='og:locale' content='fr_FR, en_US' /> <meta property='og:locale' content='fr-FR, en-US' />
<meta property='og:site_name' content={title} /> <meta property='og:site_name' content={title} />
{/* Twitter card Metadata */} {/* Twitter card Metadata */}
@ -40,18 +40,6 @@ export const Head: React.FC<HeadProps> = (props) => {
<meta name='twitter:description' content={description} /> <meta name='twitter:description' content={description} />
<meta name='twitter:title' content={title} /> <meta name='twitter:title' content={title} />
<meta name='twitter:image' content={image} /> <meta name='twitter:image' content={image} />
{/* Google Verification */}
<meta
name='google-site-verification'
content='j9CQEbSuYydXytr6gdkTfam_xX_pU97NSpVH3Bq-6f4'
/>
{/* PWA Data */}
<link rel='manifest' href='/manifest.json' />
<meta name='apple-mobile-web-app-capable' content='yes' />
<meta name='mobile-web-app-capable' content='yes' />
<link rel='apple-touch-icon' href={image} />
</NextHead> </NextHead>
) )
} }

View File

@ -19,12 +19,12 @@ export const Header: React.FC<HeaderProps> = (props) => {
quality={100} quality={100}
width={60} width={60}
height={60} height={60}
src='/images/divlo_icon_small.png' src='/images/icon_small.png'
alt='Divlo' alt='Théo LUDWIG'
priority priority
/> />
<strong className='ml-1 hidden font-headline font-semibold text-yellow dark:text-yellow-dark xs:block'> <strong className='ml-1 hidden font-headline font-semibold text-yellow dark:text-yellow-dark xs:block'>
Divlo Théo LUDWIG
</strong> </strong>
</div> </div>
</Link> </Link>

View File

@ -12,22 +12,22 @@ export const OpenSource: React.FC = () => {
<Repository <Repository
name='nodejs/node' name='nodejs/node'
description='Node.js JavaScript runtime 🐢🚀' description='Node.js JavaScript runtime 🐢🚀'
href='https://github.com/nodejs/node/commits?author=Divlo' href='https://github.com/nodejs/node/commits?author=theoludwig'
/> />
<Repository <Repository
name='standard/standard' name='standard/standard'
description='🌟 JavaScript Style Guide, with linter & automatic code fixer' description='🌟 JavaScript Style Guide, with linter & automatic code fixer'
href='https://github.com/standard/standard/commits?author=Divlo' href='https://github.com/standard/standard/commits?author=theoludwig'
/> />
<Repository <Repository
name='nrwl/nx' name='nrwl/nx'
description='Smart, Extensible Build Framework' description='Smart, Extensible Build Framework'
href='https://github.com/nrwl/nx/commits?author=Divlo' href='https://github.com/nrwl/nx/commits?author=theoludwig'
/> />
<Repository <Repository
name='vercel/next.js' name='vercel/next.js'
description='The React Framework for Production' description='The React Framework for Production'
href='https://github.com/vercel/next.js/commits?author=Divlo' href='https://github.com/vercel/next.js/commits?author=theoludwig'
/> />
</div> </div>
</div> </div>

View File

@ -5,11 +5,8 @@ export const ProfileInformation: React.FC = () => {
return ( return (
<div className='mb-6 border-b-2 border-gray-600 pb-2 font-headline dark:border-gray-400'> <div className='mb-6 border-b-2 border-gray-600 pb-2 font-headline dark:border-gray-400'>
<h1 className='mb-2 text-4xl'> <h1 className='mb-2 text-4xl font-semibold text-yellow dark:text-yellow-dark'>
{t('home:about.i-am')}{' '} Théo LUDWIG
<strong className='font-semibold text-yellow dark:text-yellow-dark'>
Divlo
</strong>
</h1> </h1>
<h2 className='mb-3 text-base'>{t('home:about.description')}</h2> <h2 className='mb-3 text-base'>{t('home:about.description')}</h2>
</div> </div>

View File

@ -1,7 +1,7 @@
import useTranslation from 'next-translate/useTranslation' import useTranslation from 'next-translate/useTranslation'
import { useMemo } from 'react' import { useMemo } from 'react'
import { DIVLO_BIRTHDAY, DIVLO_BIRTHDAY_DATE, getAge } from 'utils/getAge' import { BIRTH_DATE, BIRTH_DATE_STRING, getAge } from 'utils/getAge'
import { ProfileItem } from './ProfileItem' import { ProfileItem } from './ProfileItem'
@ -9,21 +9,24 @@ export const ProfileList: React.FC = () => {
const { t } = useTranslation('home') const { t } = useTranslation('home')
const age = useMemo(() => { const age = useMemo(() => {
return getAge(DIVLO_BIRTHDAY) return getAge(BIRTH_DATE)
}, []) }, [])
return ( return (
<ul className='m-0 list-none p-0'> <ul className='m-0 list-none p-0'>
<ProfileItem title={t('home:about.full-name')} value='Théo LUDWIG' /> <ProfileItem
title={t('home:about.pronouns')}
value={t('home:about.pronouns-value')}
/>
<ProfileItem <ProfileItem
title={t('home:about.birth-date')} title={t('home:about.birth-date')}
value={`${DIVLO_BIRTHDAY_DATE} (${age} ${t('home:about.years-old')})`} value={`${BIRTH_DATE_STRING} (${age} ${t('home:about.years-old')})`}
/> />
<ProfileItem title={t('home:about.nationality')} value='Alsace, France' /> <ProfileItem title={t('home:about.nationality')} value='Alsace, France' />
<ProfileItem <ProfileItem
title='Email' title='Email'
value='contact@divlo.fr' value='contact@theoludwig.fr'
link='mailto:contact@divlo.fr' link='mailto:contact@theoludwig.fr'
/> />
</ul> </ul>
) )

View File

@ -1,11 +1,11 @@
import Image from 'next/image' import Image from 'next/image'
import DivloLogo from 'public/images/divlo_logo.png' import Logo from 'public/images/logo.png'
export const ProfileLogo: React.FC = () => { export const ProfileLogo: React.FC = () => {
return ( return (
<div className='max-h-[370px] max-w-[370px] px-2 py-6'> <div className='max-h-[370px] max-w-[370px] px-2 py-6'>
<Image quality={100} src={DivloLogo} alt='Divlo' priority /> <Image quality={100} src={Logo} alt='Théo LUDWIG' priority />
</div> </div>
) )
} }

View File

@ -10,28 +10,34 @@ import { NPMIcon } from './SocialMediaIcons/NPMIcon'
export const SocialMediaList: React.FC = () => { export const SocialMediaList: React.FC = () => {
return ( return (
<ul className='social-media-list m-0 mt-2 list-none py-4 text-center'> <ul className='social-media-list m-0 mt-2 list-none py-4 text-center'>
<SocialMediaItem link='https://github.com/Divlo' ariaLabel='GitHub'> <SocialMediaItem link='https://github.com/theoludwig' ariaLabel='GitHub'>
<GitHubIcon /> <GitHubIcon />
</SocialMediaItem> </SocialMediaItem>
<SocialMediaItem link='https://gitlab.com/Divlo' ariaLabel='GitLab'> <SocialMediaItem link='https://gitlab.com/theoludwig' ariaLabel='GitLab'>
<GitLabIcon /> <GitLabIcon />
</SocialMediaItem> </SocialMediaItem>
<SocialMediaItem link='https://www.npmjs.com/~divlo' ariaLabel='NPM'> <SocialMediaItem link='https://www.npmjs.com/~theoludwig' ariaLabel='NPM'>
<NPMIcon /> <NPMIcon />
</SocialMediaItem> </SocialMediaItem>
<SocialMediaItem link='https://twitter.com/Divlo_FR' ariaLabel='Twitter'> <SocialMediaItem
link='https://twitter.com/theoludwig_'
ariaLabel='Twitter'
>
<TwitterIcon /> <TwitterIcon />
</SocialMediaItem> </SocialMediaItem>
<SocialMediaItem <SocialMediaItem
link='https://www.youtube.com/c/Divlo' link='https://www.youtube.com/@theo_ludwig'
ariaLabel='YouTube' ariaLabel='YouTube'
> >
<YouTubeIcon /> <YouTubeIcon />
</SocialMediaItem> </SocialMediaItem>
<SocialMediaItem link='https://www.twitch.tv/divlo' ariaLabel='Twitch'> <SocialMediaItem
link='https://www.twitch.tv/theoludwig'
ariaLabel='Twitch'
>
<TwitchIcon /> <TwitchIcon />
</SocialMediaItem> </SocialMediaItem>
<SocialMediaItem link='mailto:contact@divlo.fr' ariaLabel='Email'> <SocialMediaItem link='mailto:contact@theoludwig.fr' ariaLabel='Email'>
<EmailIcon /> <EmailIcon />
</SocialMediaItem> </SocialMediaItem>
</ul> </ul>

View File

@ -33,10 +33,10 @@ export const SkillComponent: React.FC<SkillComponentProps> = (props) => {
> >
<div className='text-center'> <div className='text-center'>
<Image <Image
className='inline h-auto w-auto' className='inline h-16 w-16'
quality={100} quality={100}
width={60} width={64}
height={60} height={64}
alt={skill} alt={skill}
src={image} src={image}
/> />

View File

@ -9,21 +9,20 @@ export const Skills: React.FC = () => {
return ( return (
<> <>
<SkillsSection title={t('home:skills.languages')}> <SkillsSection title={t('home:skills.languages')}>
<SkillComponent skill='JavaScript' />
<SkillComponent skill='TypeScript' /> <SkillComponent skill='TypeScript' />
<SkillComponent skill='Python' /> <SkillComponent skill='Python' />
<SkillComponent skill='C/C++' /> <SkillComponent skill='C/C++' />
<SkillComponent skill='PHP' /> <SkillComponent skill='PHP' />
</SkillsSection> </SkillsSection>
<SkillsSection title='Front-end'> <SkillsSection title='Frontend'>
<SkillComponent skill='HTML' /> <SkillComponent skill='HTML' />
<SkillComponent skill='CSS' /> <SkillComponent skill='CSS' />
<SkillComponent skill='Tailwind CSS' /> <SkillComponent skill='Tailwind CSS' />
<SkillComponent skill='React.js (+ Next.js)' /> <SkillComponent skill='React.js (+ Next.js)' />
</SkillsSection> </SkillsSection>
<SkillsSection title='Back-end'> <SkillsSection title='Backend'>
<SkillComponent skill='Laravel' /> <SkillComponent skill='Laravel' />
<SkillComponent skill='Node.js' /> <SkillComponent skill='Node.js' />
<SkillComponent skill='Fastify' /> <SkillComponent skill='Fastify' />
@ -32,7 +31,7 @@ export const Skills: React.FC = () => {
<SkillsSection title={t('home:skills.software-tools')}> <SkillsSection title={t('home:skills.software-tools')}>
<SkillComponent skill='GNU/Linux' /> <SkillComponent skill='GNU/Linux' />
<SkillComponent skill='Ubuntu' /> <SkillComponent skill='Arch Linux' />
<SkillComponent skill='Visual Studio Code' /> <SkillComponent skill='Visual Studio Code' />
<SkillComponent skill='Git' /> <SkillComponent skill='Git' />
<SkillComponent skill='Docker' /> <SkillComponent skill='Docker' />

View File

@ -88,20 +88,20 @@ export const skills = {
}, },
'Visual Studio Code': { 'Visual Studio Code': {
link: 'https://code.visualstudio.com/', link: 'https://code.visualstudio.com/',
image: '/images/skills/Visual_Studio_Code.png' image: '/images/skills/VisualStudioCode.png'
}, },
Git: { Git: {
link: 'https://git-scm.com/', link: 'https://git-scm.com/',
image: '/images/skills/Git.png' image: '/images/skills/Git.png'
}, },
Hyper: {
link: 'https://hyper.is/',
image: '/images/skills/Hyper.svg'
},
Ubuntu: { Ubuntu: {
link: 'https://ubuntu.com/', link: 'https://ubuntu.com/',
image: '/images/skills/Ubuntu.png' image: '/images/skills/Ubuntu.png'
}, },
'Arch Linux': {
link: 'https://archlinux.org/',
image: '/images/skills/ArchLinux.png'
},
'GNU/Linux': { 'GNU/Linux': {
link: 'https://www.gnu.org/', link: 'https://www.gnu.org/',
image: '/images/skills/GNU-Linux.png' image: '/images/skills/GNU-Linux.png'

View File

@ -4,13 +4,13 @@ describe('<Footer />', () => {
it('should render with appropriate link tag version', () => { it('should render with appropriate link tag version', () => {
const version = '1.0.0' const version = '1.0.0'
cy.mount(<Footer version={version} />) cy.mount(<Footer version={version} />)
cy.contains('Divlo') cy.contains('Théo LUDWIG')
.get('[data-cy=version-link]') .get('[data-cy=version-link]')
.should('have.text', version) .should('have.text', version)
.should( .should(
'have.attr', 'have.attr',
'href', 'href',
`https://github.com/Divlo/Divlo/releases/tag/v${version}` `https://github.com/theoludwig/theoludwig/releases/tag/v${version}`
) )
}) })
}) })

View File

@ -38,7 +38,7 @@ describe('Common > Header', () => {
describe('Switch Language', () => { describe('Switch Language', () => {
it('should switch language from EN (default) to FR', () => { it('should switch language from EN (default) to FR', () => {
cy.get('h1').contains('I am Divlo') cy.get('h1').contains('Théo LUDWIG')
cy.get('[data-cy=language-flag-text]').contains('EN') cy.get('[data-cy=language-flag-text]').contains('EN')
cy.get('[data-cy=languages-list]').should('not.be.visible') cy.get('[data-cy=languages-list]').should('not.be.visible')
cy.get('[data-cy=language-click]').click() cy.get('[data-cy=language-click]').click()
@ -46,7 +46,7 @@ describe('Common > Header', () => {
cy.get('[data-cy=languages-list] > li:first-child').contains('FR').click() cy.get('[data-cy=languages-list] > li:first-child').contains('FR').click()
cy.get('[data-cy=languages-list]').should('not.be.visible') cy.get('[data-cy=languages-list]').should('not.be.visible')
cy.get('[data-cy=language-flag-text]').contains('FR') cy.get('[data-cy=language-flag-text]').contains('FR')
cy.get('h1').contains('Je suis Divlo') cy.get('h1').contains('Théo LUDWIG')
}) })
it('should close the language list menu when clicking outside', () => { it('should close the language list menu when clicking outside', () => {

View File

@ -3,7 +3,7 @@ describe('Page /blog/[slug]', () => {
cy.visit('/blog/hello-world') cy.visit('/blog/hello-world')
cy.get('[data-cy=language-flag-text]').should('not.exist') cy.get('[data-cy=language-flag-text]').should('not.exist')
cy.get('h1').should('have.text', '👋 Hello, world!') cy.get('h1').should('have.text', '👋 Hello, world!')
cy.get('.prose a').should('have.attr', 'target', '_blank') cy.get('.prose a:visible').should('have.attr', 'target', '_blank')
}) })
it("should redirect to /404 if the blog post doesn't exist", () => { it("should redirect to /404 if the blog post doesn't exist", () => {

View File

@ -1,7 +1,7 @@
services: services:
divlo: theoludwig:
container_name: ${COMPOSE_PROJECT_NAME} container_name: ${COMPOSE_PROJECT_NAME}
image: 'divlo' image: 'theoludwig'
build: build:
context: './' context: './'
ports: ports:

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr"> <html lang="fr-FR">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />

View File

@ -12,9 +12,9 @@
"modern-normalize": "2.0.0" "modern-normalize": "2.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "20.2.1", "@types/node": "20.3.3",
"date-and-time": "3.0.0", "date-and-time": "3.0.2",
"vite": "4.3.8", "vite": "4.3.9",
"vite-plugin-html": "3.2.0" "vite-plugin-html": "3.2.0"
} }
}, },
@ -370,68 +370,10 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": { "node_modules/@jridgewell/source-map": {
"version": "0.3.3", "version": "0.3.4",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.4.tgz",
"integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "integrity": "sha512-KE/SxsDqNs3rrWwFHcRh15ZLVFrI0YoZtgAdIyIq9k5hUNmiWRXXThPomIxHuL20sLdgzbDFyvkUMna14bvtrw==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.18",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "3.1.0",
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
"node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true "dev": true
}, },
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
@ -483,15 +425,15 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.2.1", "version": "20.3.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz",
"integrity": "sha512-DqJociPbZP1lbZ5SQPk4oag6W7AyaGMO6gSfRwq3PWl4PXTwJpRQJhDq4W0kzrg3w6tJ1SwlvGZ5uKFHY13LIg==", "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==",
"dev": true "dev": true
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.8.2", "version": "8.9.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
"dev": true, "dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@ -682,9 +624,9 @@
} }
}, },
"node_modules/date-and-time": { "node_modules/date-and-time": {
"version": "3.0.0", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-3.0.0.tgz", "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-3.0.2.tgz",
"integrity": "sha512-uuzXp/mvv6jEMLiP5QzERSQPzHqYnv9i8NZ8BS5kYeB2sakv74EewQiCS4Ahxwq3In+9fYZhGztuDHRVzIOkFQ==", "integrity": "sha512-MOqlRertOQmQI7ySbz6dKLM7Rxm9dgcPuBI9IL7NVe0UGqHPK+6hWSKVhLrVHxlSgQQtocE2R7+HFOf5aMz8vw==",
"dev": true "dev": true
}, },
"node_modules/dom-serializer": { "node_modules/dom-serializer": {
@ -753,12 +695,15 @@
} }
}, },
"node_modules/dotenv": { "node_modules/dotenv": {
"version": "16.0.3", "version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
},
"funding": {
"url": "https://github.com/motdotla/dotenv?sponsor=1"
} }
}, },
"node_modules/dotenv-expand": { "node_modules/dotenv-expand": {
@ -838,9 +783,9 @@
"dev": true "dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.12", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@ -1020,9 +965,9 @@
} }
}, },
"node_modules/jake": { "node_modules/jake": {
"version": "10.8.6", "version": "10.8.7",
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.6.tgz", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz",
"integrity": "sha512-G43Ub9IYEFfu72sua6rzooi8V8Gz2lkfk48rW20vEWCGizeaEPlKB1Kh8JIA84yQbiAEfqlPmSpGgCKKxH3rDA==", "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"async": "^3.2.3", "async": "^3.2.3",
@ -1203,9 +1148,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.23", "version": "8.4.24",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz",
"integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -1270,9 +1215,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "3.22.0", "version": "3.26.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.22.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.0.tgz",
"integrity": "sha512-imsigcWor5Y/dC0rz2q0bBt9PabcL3TORry2hAa6O6BuMvY71bqHyfReAz5qyAqiQATD1m70qdntqBfBQjVWpQ==", "integrity": "sha512-YzJH0eunH2hr3knvF3i6IkLO/jTjAEwU4HoMUbQl4//Tnl3ou0e7P5SjxdDr8HQJdeUJShlbEHXrrnEHy1l7Yg==",
"dev": true, "dev": true,
"bin": { "bin": {
"rollup": "dist/bin/rollup" "rollup": "dist/bin/rollup"
@ -1349,13 +1294,13 @@
} }
}, },
"node_modules/terser": { "node_modules/terser": {
"version": "5.17.4", "version": "5.18.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.17.4.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.18.2.tgz",
"integrity": "sha512-jcEKZw6UPrgugz/0Tuk/PVyLAPfMBJf5clnGueo45wTweoV8yh7Q7PEkhkJ5uuUbC7zAxEcG3tqNr1bstkQ8nw==", "integrity": "sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.2", "@jridgewell/source-map": "^0.3.3",
"acorn": "^8.5.0", "acorn": "^8.8.2",
"commander": "^2.20.0", "commander": "^2.20.0",
"source-map-support": "~0.5.20" "source-map-support": "~0.5.20"
}, },
@ -1385,9 +1330,9 @@
} }
}, },
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.5.2", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
"integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==", "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==",
"dev": true "dev": true
}, },
"node_modules/universalify": { "node_modules/universalify": {
@ -1400,9 +1345,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "4.3.8", "version": "4.3.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.8.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
"integrity": "sha512-uYB8PwN7hbMrf4j1xzGDk/lqjsZvCDbt/JC5dyfxc19Pg8kRm14LinK/uq+HSLNswZEoKmweGdtpbnxRtrAXiQ==", "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"esbuild": "^0.17.5", "esbuild": "^0.17.5",

View File

@ -13,9 +13,9 @@
"modern-normalize": "2.0.0" "modern-normalize": "2.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "20.2.1", "@types/node": "20.3.3",
"date-and-time": "3.0.0", "date-and-time": "3.0.2",
"vite": "4.3.8", "vite": "4.3.9",
"vite-plugin-html": "3.2.0" "vite-plugin-html": "3.2.0"
} }
} }

View File

@ -1,5 +1,5 @@
import { DIVLO_BIRTHDAY, getAge } from '../../utils/getAge.ts' import { BIRTH_DATE, getAge } from '../../utils/getAge.ts'
const yearOld = document.getElementById('year-old') const yearOld = document.getElementById('year-old')
yearOld.textContent = getAge(DIVLO_BIRTHDAY).toString() yearOld.textContent = getAge(BIRTH_DATE).toString()

View File

@ -1,8 +1,8 @@
{ {
"about": { "about": {
"i-am": "I am",
"description": "Developer Full Stack • Open-Source enthusiast", "description": "Developer Full Stack • Open-Source enthusiast",
"full-name": "Full name", "pronouns": "Pronouns",
"pronouns-value": "He/Him",
"birth-date": "Birth date", "birth-date": "Birth date",
"years-old": "years old", "years-old": "years old",
"nationality": "Nationality", "nationality": "Nationality",
@ -17,7 +17,7 @@
}, },
{ {
"title": "Open-Source enthusiast", "title": "Open-Source enthusiast",
"description": "For me, everyone should work, solve problems, build things and think together.<br/> The website is open-source on <a class='text-yellow dark:text-yellow-dark hover:underline' href='https://github.com/Divlo/Divlo' target='_blank' rel='noopener noreferrer'>GitHub</a>." "description": "For me, everyone should work, solve problems, build things and think together.<br/> The website is open-source on <a class='text-yellow dark:text-yellow-dark hover:underline' href='https://github.com/theoludwig/theoludwig' target='_blank' rel='noopener noreferrer'>GitHub</a>."
}, },
{ {
"title": "Passionate about High-Tech", "title": "Passionate about High-Tech",

View File

@ -1,8 +1,8 @@
{ {
"about": { "about": {
"i-am": "Je suis",
"description": "Développeur Full Stack • Enthousiaste de l'Open-Source", "description": "Développeur Full Stack • Enthousiaste de l'Open-Source",
"full-name": "Prénom NOM", "pronouns": "Pronoms",
"pronouns-value": "Il/Lui",
"birth-date": "Date de naissance", "birth-date": "Date de naissance",
"years-old": "ans", "years-old": "ans",
"nationality": "Nationalité", "nationality": "Nationalité",
@ -17,7 +17,7 @@
}, },
{ {
"title": "Enthousiaste de l'Open-Source", "title": "Enthousiaste de l'Open-Source",
"description": "Pour moi, tout le monde devrait travailler, résoudre des problèmes, construire des choses et réfléchir ensemble. <br/> Le site est open-source sur <a class='text-yellow dark:text-yellow-dark hover:underline' href='https://github.com/Divlo/Divlo' target='_blank' rel='noopener noreferrer'>GitHub</a>." "description": "Pour moi, tout le monde devrait travailler, résoudre des problèmes, construire des choses et réfléchir ensemble. <br/> Le site est open-source sur <a class='text-yellow dark:text-yellow-dark hover:underline' href='https://github.com/theoludwig/theoludwig' target='_blank' rel='noopener noreferrer'>GitHub</a>."
}, },
{ {
"title": "Passionné de High-Tech", "title": "Passionné de High-Tech",

View File

@ -1,7 +1,3 @@
const nextPWA = require('next-pwa')({
disable: process.env.NODE_ENV !== 'production',
dest: 'public'
})
const nextTranslate = require('next-translate-plugin') const nextTranslate = require('next-translate-plugin')
/** @type {import("next").NextConfig} */ /** @type {import("next").NextConfig} */
@ -10,4 +6,4 @@ const nextConfig = {
output: 'standalone' output: 'standalone'
} }
module.exports = nextTranslate(nextPWA(nextConfig)) module.exports = nextTranslate(nextConfig)

6031
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
{ {
"name": "divlo", "name": "theoludwig",
"version": "2.7.1", "version": "2.12.0",
"private": true, "private": true,
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Divlo/Divlo" "url": "https://github.com/theoludwig/theoludwig"
}, },
"engines": { "engines": {
"node": ">=16.0.0", "node": ">=16.0.0",
@ -17,12 +17,12 @@
"lint:commit": "commitlint", "lint:commit": "commitlint",
"lint:editorconfig": "editorconfig-checker", "lint:editorconfig": "editorconfig-checker",
"lint:markdown": "markdownlint-cli2", "lint:markdown": "markdownlint-cli2",
"lint:eslint": "eslint \".\" --ignore-path \".gitignore\"", "lint:eslint": "eslint . --ignore-path .gitignore",
"lint:prettier": "prettier \".\" --check --ignore-path \".gitignore\"", "lint:prettier": "prettier . --check --ignore-path .gitignore",
"lint:staged": "lint-staged", "lint:staged": "lint-staged",
"test:unit": "cypress run --component", "test:unit": "cypress run --component",
"test:html-w3c-validator": "start-server-and-test \"start\" \"http://127.0.0.1:3000\" \"html-w3c-validator\"", "test:html-w3c-validator": "start-server-and-test \"start\" \"http://127.0.0.1:3000\" \"html-w3c-validator\"",
"test:e2e": "start-server-and-test \"start\" \"http://127.0.0.1:3000\" \"cypress run\"", "test:e2e": "start-server-and-test \"start\" http://127.0.0.1:3000 \"cypress run\"",
"test:dev": "start-server-and-test \"dev\" \"http://127.0.0.1:3000\" \"cypress open\"", "test:dev": "start-server-and-test \"dev\" \"http://127.0.0.1:3000\" \"cypress open\"",
"resume:build": "node ./jsonresume-theme-custom/build.js", "resume:build": "node ./jsonresume-theme-custom/build.js",
"release": "semantic-release", "release": "semantic-release",
@ -30,22 +30,21 @@
"postinstall": "husky install" "postinstall": "husky install"
}, },
"dependencies": { "dependencies": {
"@fontsource/montserrat": "5.0.0", "@fontsource/montserrat": "5.0.3",
"@fortawesome/fontawesome-svg-core": "6.4.0", "@fortawesome/fontawesome-svg-core": "6.4.0",
"@fortawesome/free-brands-svg-icons": "6.4.0", "@fortawesome/free-brands-svg-icons": "6.4.0",
"@fortawesome/free-solid-svg-icons": "6.4.0", "@fortawesome/free-solid-svg-icons": "6.4.0",
"@fortawesome/react-fontawesome": "0.2.0", "@fortawesome/react-fontawesome": "0.2.0",
"@giscus/react": "2.2.8", "@giscus/react": "2.3.0",
"clsx": "1.2.1", "clsx": "1.2.1",
"date-and-time": "3.0.0", "date-and-time": "3.0.2",
"gray-matter": "4.0.3", "gray-matter": "4.0.3",
"html-react-parser": "3.0.16", "html-react-parser": "4.0.0",
"katex": "0.16.7", "katex": "0.16.8",
"next": "13.4.3", "next": "13.4.7",
"next-mdx-remote": "4.4.1", "next-mdx-remote": "4.4.1",
"next-pwa": "5.6.0",
"next-themes": "0.2.1", "next-themes": "0.2.1",
"next-translate": "2.0.5", "next-translate": "2.4.4",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"read-pkg": "8.0.0", "read-pkg": "8.0.0",
@ -55,47 +54,47 @@
"remark-gfm": "3.0.1", "remark-gfm": "3.0.1",
"remark-math": "5.1.1", "remark-math": "5.1.1",
"sharp": "0.32.1", "sharp": "0.32.1",
"shiki": "0.14.2", "shiki": "0.14.3",
"unified": "10.1.2", "unified": "10.1.2",
"unist-util-visit": "4.1.2", "unist-util-visit": "4.1.2",
"universal-cookie": "4.0.4" "universal-cookie": "4.0.4"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "17.6.3", "@commitlint/cli": "17.6.6",
"@commitlint/config-conventional": "17.6.3", "@commitlint/config-conventional": "17.6.6",
"@saithodev/semantic-release-backmerge": "3.2.0", "@saithodev/semantic-release-backmerge": "3.2.0",
"@semantic-release/git": "10.0.1", "@semantic-release/git": "10.0.1",
"@tailwindcss/typography": "0.5.9", "@tailwindcss/typography": "0.5.9",
"@tsconfig/strictest": "2.0.1", "@tsconfig/strictest": "2.0.1",
"@types/node": "20.2.1", "@types/node": "20.3.3",
"@types/react": "18.2.6", "@types/react": "18.2.14",
"@types/unist": "2.0.6", "@types/unist": "2.0.6",
"@typescript-eslint/eslint-plugin": "5.59.6", "@typescript-eslint/eslint-plugin": "5.60.1",
"autoprefixer": "10.4.14", "autoprefixer": "10.4.14",
"cypress": "12.12.0", "cypress": "12.16.0",
"editorconfig-checker": "5.0.1", "editorconfig-checker": "5.1.1",
"eslint": "8.41.0", "eslint": "8.44.0",
"eslint-config-conventions": "9.0.0", "eslint-config-conventions": "10.0.0",
"eslint-config-next": "13.4.3", "eslint-config-next": "13.4.7",
"eslint-config-prettier": "8.8.0", "eslint-config-prettier": "8.8.0",
"eslint-plugin-import": "2.27.5", "eslint-plugin-import": "2.27.5",
"eslint-plugin-prettier": "4.2.1", "eslint-plugin-prettier": "4.2.1",
"eslint-plugin-promise": "6.1.1", "eslint-plugin-promise": "6.1.1",
"eslint-plugin-unicorn": "47.0.0", "eslint-plugin-unicorn": "47.0.0",
"html-w3c-validator": "1.3.0", "html-w3c-validator": "1.4.0",
"husky": "8.0.3", "husky": "8.0.3",
"jsonresume-theme-custom": "file:./jsonresume-theme-custom", "jsonresume-theme-custom": "file:./jsonresume-theme-custom",
"lint-staged": "13.2.2", "lint-staged": "13.2.3",
"markdownlint-cli2": "0.7.1", "markdownlint-cli2": "0.8.1",
"markdownlint-rule-relative-links": "1.2.0", "markdownlint-rule-relative-links": "2.1.0",
"next-translate-plugin": "2.0.5", "next-translate-plugin": "2.4.4",
"postcss": "8.4.23", "postcss": "8.4.24",
"prettier": "2.8.8", "prettier": "2.8.8",
"prettier-plugin-tailwindcss": "0.3.0", "prettier-plugin-tailwindcss": "0.3.0",
"semantic-release": "21.0.2", "semantic-release": "21.0.6",
"start-server-and-test": "2.0.0", "start-server-and-test": "2.0.0",
"tailwindcss": "3.3.2", "tailwindcss": "3.3.2",
"typescript": "5.0.4", "typescript": "5.0.4",
"vercel": "29.3.6" "vercel": "31.0.1"
} }
} }

View File

@ -13,7 +13,7 @@ const Error404: NextPage<Error404Props> = (props) => {
return ( return (
<> <>
<Head title='404 | Divlo' /> <Head title='404 | Théo LUDWIG' />
<ErrorPage <ErrorPage
statusCode={404} statusCode={404}
message={t('errors:not-found')} message={t('errors:not-found')}

View File

@ -13,7 +13,7 @@ const Error500: NextPage<Error500Props> = (props) => {
return ( return (
<> <>
<Head title='500 | Divlo' /> <Head title='500 | Théo LUDWIG' />
<ErrorPage <ErrorPage
statusCode={500} statusCode={500}
message={t('errors:server-error')} message={t('errors:server-error')}

View File

@ -1,6 +1,9 @@
import type { GetStaticProps, GetStaticPaths, NextPage } from 'next' import type { GetStaticProps, GetStaticPaths, NextPage } from 'next'
import Link from 'next/link'
import Image from 'next/image' import Image from 'next/image'
import { MDXRemote } from 'next-mdx-remote' import { MDXRemote } from 'next-mdx-remote'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faLink } from '@fortawesome/free-solid-svg-icons'
import date from 'date-and-time' import date from 'date-and-time'
import Giscus from '@giscus/react' import Giscus from '@giscus/react'
import { useTheme } from 'next-themes' import { useTheme } from 'next-themes'
@ -17,6 +20,26 @@ interface BlogPostPageProps extends FooterProps {
post: Post post: Post
} }
const Heading = (
props: React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
>
): JSX.Element => {
const { children, id = '' } = props
return (
<h2 {...props} className='group'>
<Link
href={`#${id}`}
className='invisible !text-black group-hover:visible dark:!text-white'
>
<FontAwesomeIcon className='mr-2 inline h-4 w-4' icon={faLink} />
</Link>
{children}
</h2>
)
}
const BlogPostPage: NextPage<BlogPostPageProps> = (props) => { const BlogPostPage: NextPage<BlogPostPageProps> = (props) => {
const { version, post } = props const { version, post } = props
@ -25,7 +48,7 @@ const BlogPostPage: NextPage<BlogPostPageProps> = (props) => {
return ( return (
<> <>
<Head <Head
title={`${post.frontmatter.title} | Divlo`} title={`${post.frontmatter.title} | Théo LUDWIG`}
description={post.frontmatter.description} description={post.frontmatter.description}
/> />
@ -42,6 +65,12 @@ const BlogPostPage: NextPage<BlogPostPageProps> = (props) => {
<MDXRemote <MDXRemote
{...post.source} {...post.source}
components={{ components={{
h1: Heading,
h2: Heading,
h3: Heading,
h4: Heading,
h5: Heading,
h6: Heading,
img: (properties) => { img: (properties) => {
const { src = '', alt = 'Blog Image' } = properties const { src = '', alt = 'Blog Image' } = properties
const source = src.replace('../public/', '/') const source = src.replace('../public/', '/')
@ -69,7 +98,7 @@ const BlogPostPage: NextPage<BlogPostPageProps> = (props) => {
/> />
<Giscus <Giscus
id='comments' id='comments'
repo='Divlo/Divlo' repo='theoludwig/theoludwig'
repoId='MDEwOlJlcG9zaXRvcnkzNTg5NDg1NDQ=' repoId='MDEwOlJlcG9zaXRvcnkzNTg5NDg1NDQ='
category='General' category='General'
categoryId='DIC_kwDOFWUewM4CQ_WK' categoryId='DIC_kwDOFWUewM4CQ_WK'

View File

@ -21,7 +21,7 @@ const BlogPage: NextPage<BlogPageProps> = (props) => {
return ( return (
<> <>
<Head title='Blog | Divlo' description={blogDescription} /> <Head title='Blog | Théo LUDWIG' description={blogDescription} />
<Header /> <Header />
<main className='flex flex-1 flex-col flex-wrap items-center'> <main className='flex flex-1 flex-col flex-wrap items-center'>

View File

@ -21,7 +21,7 @@ Git was originally authored by [Linus Torvalds](https://en.wikipedia.org/wiki/Li
Git allows: Git allows:
- to be able to work with several people on the same codebase. - to work with several people on the same codebase.
- track changes to know who did what and when. - track changes to know who did what and when.
- revert changes. - revert changes.
@ -122,6 +122,13 @@ git checkout <branch>
# Merge a branch into the current branch # Merge a branch into the current branch
git merge <branch> git merge <branch>
# Combine multiple commits of a branch into one for a merge
git merge --squash <branch>
# Change several past commits (interactive rebase)
# HEAD points to the current consulted commit.
git rebase --interactive HEAD~<number-of-commits>
# Delete a branch # Delete a branch
git branch --delete <branch> git branch --delete <branch>
git push <remote> --delete <branch> git push <remote> --delete <branch>
@ -132,14 +139,11 @@ git fetch --prune
# Revert a commit # Revert a commit
git revert <commit> git revert <commit>
# Change several past commits (interactive rebase)
# HEAD points to the current consulted commit.
git rebase --interactive HEAD~<number-of-commits>
# Reset the current branch, delete all commits since <branch> (without removing the changes) # Reset the current branch, delete all commits since <branch> (without removing the changes)
git reset --soft <branch> git reset --soft <branch>
# Apply the changes introduced by some existing commits # Apply the changes introduced by some existing commits
# (by first being on the branch where you want to apply the commit)
git cherry-pick <commit> git cherry-pick <commit>
``` ```

View File

@ -13,11 +13,11 @@ This blog is here to document my journey of learning computer science, explainin
The idea is that I will share my knowledge with you (readers), and hopefully help you to learn too. The idea is that I will share my knowledge with you (readers), and hopefully help you to learn too.
Keep in mind that I will not translate the posts in French, all the posts will be written in English, as I'm not a native English speaker, I will probably make mistakes, feel free to open pull requests on [GitHub](https://github.com/Divlo/Divlo) to correct them. 😊 Keep in mind that I will not translate the posts in French, all the posts will be written in English, as I'm not a native English speaker, I will probably make mistakes, feel free to open pull requests on [GitHub](https://github.com/theoludwig/theoludwig) to correct them. 😊
I plan to publish new posts when I have something new to share. There's no schedule, so stay tuned! I plan to publish new posts when I have something new to share. There's no schedule, so stay tuned!
To stay informed of new blog post and to ask questions, feel free to follow me on Twitter: [@Divlo_FR](https://twitter.com/Divlo_FR). To stay informed of new blog post and to ask questions, feel free to follow me on Twitter: [@theoludwig\_](https://twitter.com/theoludwig_).
## Project based learning ## Project based learning
@ -33,7 +33,7 @@ I learn something new, because it solved a "real life" problem I had encountered
In this section, I will explain what technologies I used to make this blog, and what are the technical choices I had to do. In this section, I will explain what technologies I used to make this blog, and what are the technical choices I had to do.
The code of this website is open source on [GitHub](https://github.com/Divlo/Divlo), so you can see the code and contribute to it. The code of this website is open source on [GitHub](https://github.com/theoludwig/theoludwig), so you can see the code and contribute to it.
### Technologies ### Technologies

View File

@ -333,11 +333,11 @@ def maximum_subarray_sum_linear(array: list[int]) -> int:
Problems solving is a very complicated and large topic, and also a very important skill to have as a software developer. Problems solving is a very complicated and large topic, and also a very important skill to have as a software developer.
To improve our problems solving skills, we can regularly practice with [programming challenges](https://github.com/Divlo/programming-challenges). To improve our problems solving skills, we can regularly practice with [programming challenges](https://github.com/theoludwig/programming-challenges).
## Sources ## Sources
- [Wikipedia - Competitive programming](https://en.wikipedia.org/wiki/Competitive_programming) - [Wikipedia - Competitive programming](https://en.wikipedia.org/wiki/Competitive_programming)
- [Frontend Masters - The Last Algorithms Course You'll Need](https://frontendmasters.com/courses/algorithms/) - [Frontend Masters - The Last Algorithms Course You'll Need](https://frontendmasters.com/courses/algorithms/)
- [Big-O Cheat Sheet](https://www.bigocheatsheet.com/) - [Big-O Cheat Sheet](https://www.bigocheatsheet.com/)
- [programming challenges](https://github.com/Divlo/programming-challenges) - [programming challenges](https://github.com/theoludwig/programming-challenges)

View File

@ -7,13 +7,13 @@ publishedOn: '2022-04-11T10:24:55.206Z'
Hello! 👋 Hello! 👋
After months of hard work, [Thream v1.0.0](https://www.thream.divlo.fr/) has been released! 🎉 After months of hard work, [Thream v1.0.0](https://thream.divlo.fr/) has been released! 🎉
[**Thream**](https://www.thream.divlo.fr/) is your open-source platform to stay close with your friends and communities, talk, chat, collaborate, share and have fun. [**Thream**](https://thream.divlo.fr/) is your open-source platform to stay close with your friends and communities, talk, chat, collaborate, share and have fun.
## Presentation ## Presentation
[**Thream**](https://www.thream.divlo.fr/) is a social network to stay close with your friends and communities to talk, chat, collaborate and share. [**Thream**](https://thream.divlo.fr/) is a social network to stay close with your friends and communities to talk, chat, collaborate and share.
The project is largely inspired by [Discord](https://discord.com), a proprietary instant messaging service, but differentiates itself by its **non-profit open source philosophy** and will integrate special features. The project is largely inspired by [Discord](https://discord.com), a proprietary instant messaging service, but differentiates itself by its **non-profit open source philosophy** and will integrate special features.
@ -23,11 +23,11 @@ The idea is that a user can create an account to authenticate with an email addr
![The Thream app on a community page](../public/images/posts/thream-v1-0-0/thream-ui.png) ![The Thream app on a community page](../public/images/posts/thream-v1-0-0/thream-ui.png)
[**Thream**](https://www.thream.divlo.fr/) is a website that works on any recent browser, accessible on [thream.divlo.fr](https://www.thream.divlo.fr/). [**Thream**](https://thream.divlo.fr/) is a website that works on any recent browser, accessible on [thream.divlo.fr](https://thream.divlo.fr/).
## History ## History
The idea for the project has existed since May 13, 2020, symbolized by a [publication on Twitter](https://twitter.com/Divlo_FR/status/1260638175246135296) by the creator: Divlo. The idea for the project has existed since May 13, 2020, symbolized by a [publication on Twitter](https://twitter.com/theoludwig_/status/1260638175246135296) by the creator: Théo LUDWIG.
The main goal is to put into **practice knowledge in web development** and computer science in general on a concrete project that can **easily evolve over time** where you can add many features. The main goal is to put into **practice knowledge in web development** and computer science in general on a concrete project that can **easily evolve over time** where you can add many features.
@ -116,4 +116,4 @@ The other interest of the project is that it is completely **open-source**, and
Feel free to give feebacks and suggestions to improve the project, and to report any bug you find. Feel free to give feebacks and suggestions to improve the project, and to report any bug you find.
**Thream** is available: [**thream.divlo.fr**](https://www.thream.divlo.fr/). **Thream** is available: [**thream.divlo.fr**](https://thream.divlo.fr/).

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,51 +0,0 @@
{
"name": "Divlo",
"short_name": "Divlo",
"icons": [
{
"src": "images/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "images/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "images/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "images/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffd800",
"background_color": "#181818",
"start_url": "/",
"display": "standalone"
}

View File

@ -6,14 +6,14 @@
"basics": { "basics": {
"name": "Théo LUDWIG", "name": "Théo LUDWIG",
"label": "Développeur Full Stack • Étudiant", "label": "Développeur Full Stack • Étudiant",
"image": "https://divlo.fr/images/logo_orange.png", "image": "https://theoludwig.fr/images/logo_orange.png",
"email": "contact@divlo.fr", "email": "contact@theoludwig.fr",
"age": "31/03/2003", "age": "31/03/2003",
"location": { "location": {
"address": "Alsace, France" "address": "Alsace, France"
}, },
"url": "https://divlo.fr", "url": "https://theoludwig.fr",
"summary": "Je suis étudiant à l'université suivant la formation \"BUT Informatique\" et me forme en autodidacte dans l'informatique en suivant des formations en ligne. <br/> Je mets en pratique tout ce que j'apprends et réalise de nombreux projets (disponible sur <a href=\"https://divlo.fr\">divlo.fr</a>)." "summary": "Je suis étudiant à l'université suivant la formation \"BUT Informatique\" et me forme en autodidacte dans l'informatique en suivant des formations en ligne. <br/> Je mets en pratique tout ce que j'apprends et réalise de nombreux projets (disponible sur <a href=\"https://theoludwig.fr\">theoludwig.fr</a>)."
}, },
"education": [ "education": [
{ {
@ -66,8 +66,8 @@
"location": "4 Rue Sophie Germain, 67720 Hœrdt", "location": "4 Rue Sophie Germain, 67720 Hœrdt",
"position": "Stagiaire Développeur Web", "position": "Stagiaire Développeur Web",
"startDate": "2023-04-11", "startDate": "2023-04-11",
"endDate": "2023-06-23", "endDate": "2023-07-26",
"duration": "3 mois" "duration": "4 mois"
}, },
{ {
"summary": "Agent administratif - Numérisation et archivage des plans électriques initialement sous format papier calque.", "summary": "Agent administratif - Numérisation et archivage des plans électriques initialement sous format papier calque.",
@ -105,7 +105,7 @@
"website": "https://www.wildcodeschool.fr/", "website": "https://www.wildcodeschool.fr/",
"name": "Wild Code School", "name": "Wild Code School",
"location": "32 Rue du Bass. d'Austerlitz, 67100 Strasbourg", "location": "32 Rue du Bass. d'Austerlitz, 67100 Strasbourg",
"position": "Initiation métier développeur web", "position": "Initiation métier Développeur web",
"startDate": "2019-06-24", "startDate": "2019-06-24",
"endDate": "2019-06-28", "endDate": "2019-06-28",
"duration": "1 semaine" "duration": "1 semaine"
@ -136,16 +136,16 @@
}, },
{ {
"keywords": ["HTML", "CSS", "Tailwind CSS", "React.js/Next.js"], "keywords": ["HTML", "CSS", "Tailwind CSS", "React.js/Next.js"],
"name": "Front-end" "name": "Frontend"
}, },
{ {
"keywords": ["Laravel", "Node.js", "Fastify", "PostgreSQL"], "keywords": ["Laravel", "Node.js", "Fastify", "PostgreSQL"],
"name": "Back-end" "name": "Backend"
}, },
{ {
"keywords": [ "keywords": [
"GNU/Linux", "GNU/Linux",
"Ubuntu", "Arch Linux",
"Visual Studio Code", "Visual Studio Code",
"Git", "Git",
"Docker" "Docker"

View File

@ -8,7 +8,19 @@
} }
.prose { .prose {
@apply !max-w-5xl text-gray dark:text-gray-300; @apply !max-w-5xl scroll-smooth text-gray dark:text-gray-300;
}
.prose p {
@apply text-justify;
}
.prose [id]::before {
content: '';
display: block;
height: 90px;
margin-top: -90px;
visibility: hidden;
} }
.prose a, .prose a,

View File

@ -1,11 +1,11 @@
export const DIVLO_BIRTHDAY_DAY = '31' as const export const BIRTH_DATE_DAY = '31' as const
export const DIVLO_BIRTHDAY_MONTH = '03' as const export const BIRTH_DATE_MONTH = '03' as const
export const DIVLO_BIRTHDAY_YEAR = '2003' as const export const BIRTH_DATE_YEAR = '2003' as const
export const DIVLO_BIRTHDAY_DATE = export const BIRTH_DATE_STRING =
`${DIVLO_BIRTHDAY_DAY}/${DIVLO_BIRTHDAY_MONTH}/${DIVLO_BIRTHDAY_YEAR}` as const `${BIRTH_DATE_DAY}/${BIRTH_DATE_MONTH}/${BIRTH_DATE_YEAR}` as const
export const DIVLO_BIRTHDAY_DATE_ISO_8061 = export const BIRTH_DATE_ISO_8601 =
`${DIVLO_BIRTHDAY_YEAR}-${DIVLO_BIRTHDAY_MONTH}-${DIVLO_BIRTHDAY_DAY}` as const `${BIRTH_DATE_YEAR}-${BIRTH_DATE_MONTH}-${BIRTH_DATE_DAY}` as const
export const DIVLO_BIRTHDAY = new Date(DIVLO_BIRTHDAY_DATE_ISO_8061) export const BIRTH_DATE = new Date(BIRTH_DATE_ISO_8601)
/** /**
* Calculates the age of a person based on their birth date * Calculates the age of a person based on their birth date