From 6b29ce9b1574e78dd6191629ddcdb986b4a03ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20LUDWIG?= Date: Mon, 31 Jul 2023 19:06:46 +0200 Subject: [PATCH] feat: rewrite to Next.js v13 app directory Improvements: - Hide switch theme input (ugly little white square) - i18n without subpath (e.g: /fr or /en), same url whatever the locale used --- app/error.tsx | 21 ++ styles/global.css => app/globals.css | 0 app/layout.tsx | 71 +++++++ app/loading.tsx | 11 ++ app/not-found.tsx | 12 ++ app/page.tsx | 59 ++++++ components/ErrorPage.tsx | 57 +++--- components/Footer.tsx | 42 ---- components/Footer/FooterText.tsx | 19 ++ components/Footer/FooterVersion.tsx | 28 +++ components/Footer/index.tsx | 14 ++ components/Head.tsx | 45 ----- components/Header/Language/LanguageFlag.tsx | 24 --- .../Header/{Language => Locales}/Arrow.tsx | 0 components/Header/Locales/LocaleFlag.tsx | 30 +++ .../Header/{Language => Locales}/index.tsx | 51 +++-- components/Header/SwitchTheme.tsx | 2 +- components/Header/index.tsx | 19 +- components/Interests/index.tsx | 15 +- components/Loader/Loader.module.css | 39 ++++ components/Loader/Loader.tsx | 33 ++++ components/OpenSource/index.tsx | 8 +- components/Portfolio/index.tsx | 15 +- .../Profile/ProfileDescriptionBottom.tsx | 8 +- components/Profile/ProfileInfo.tsx | 8 +- components/Profile/ProfileList/index.tsx | 28 ++- components/Profile/index.tsx | 6 +- components/Providers.tsx | 15 ++ components/Skills/Skill.tsx | 19 +- components/Skills/index.tsx | 8 +- .../curriculum-vitae.jsonc | 0 curriculum-vitae/vite.config.ts | 2 +- cypress/component/Footer.cy.tsx | 16 -- cypress/e2e/common/Header.cy.ts | 26 +-- cypress/e2e/pages/blog/[slug].cy.ts | 2 +- i18n.json | 10 - i18n/i18n.client.ts | 12 ++ i18n/i18n.server.ts | 20 ++ i18n/i18n.ts | 32 +++ .../translations/en-US}/common.json | 4 +- .../translations/en-US}/errors.json | 0 .../en => i18n/translations/en-US}/home.json | 0 .../translations/fr-FR}/common.json | 4 +- .../translations/fr-FR}/errors.json | 0 .../fr => i18n/translations/fr-FR}/home.json | 0 middleware.ts | 53 +++++ next.config.js | 11 +- package-lock.json | 185 +++++++++--------- package.json | 10 +- pages/404.tsx | 32 --- pages/500.tsx | 32 --- pages/_app.tsx | 33 ---- pages/_document.tsx | 15 -- pages/blog/[slug].tsx | 152 -------------- pages/blog/index.tsx | 81 -------- pages/index.tsx | 81 -------- .../{languages/en.svg => locales/en-US.svg} | 0 .../{languages/fr.svg => locales/fr-FR.svg} | 0 tailwind.config.js | 5 +- tsconfig.json | 9 +- utils/constants.ts | 8 + 61 files changed, 755 insertions(+), 787 deletions(-) create mode 100644 app/error.tsx rename styles/global.css => app/globals.css (100%) create mode 100644 app/layout.tsx create mode 100644 app/loading.tsx create mode 100644 app/not-found.tsx create mode 100644 app/page.tsx delete mode 100644 components/Footer.tsx create mode 100644 components/Footer/FooterText.tsx create mode 100644 components/Footer/FooterVersion.tsx create mode 100644 components/Footer/index.tsx delete mode 100644 components/Head.tsx delete mode 100644 components/Header/Language/LanguageFlag.tsx rename components/Header/{Language => Locales}/Arrow.tsx (100%) create mode 100644 components/Header/Locales/LocaleFlag.tsx rename components/Header/{Language => Locales}/index.tsx (58%) create mode 100644 components/Loader/Loader.module.css create mode 100644 components/Loader/Loader.tsx create mode 100644 components/Providers.tsx rename curriculum-vitae.jsonc => curriculum-vitae/curriculum-vitae.jsonc (100%) delete mode 100644 cypress/component/Footer.cy.tsx delete mode 100644 i18n.json create mode 100644 i18n/i18n.client.ts create mode 100644 i18n/i18n.server.ts create mode 100644 i18n/i18n.ts rename {locales/en => i18n/translations/en-US}/common.json (60%) rename {locales/en => i18n/translations/en-US}/errors.json (100%) rename {locales/en => i18n/translations/en-US}/home.json (100%) rename {locales/fr => i18n/translations/fr-FR}/common.json (60%) rename {locales/fr => i18n/translations/fr-FR}/errors.json (100%) rename {locales/fr => i18n/translations/fr-FR}/home.json (100%) create mode 100644 middleware.ts delete mode 100644 pages/404.tsx delete mode 100644 pages/500.tsx delete mode 100644 pages/_app.tsx delete mode 100644 pages/_document.tsx delete mode 100644 pages/blog/[slug].tsx delete mode 100644 pages/blog/index.tsx delete mode 100644 pages/index.tsx rename public/images/{languages/en.svg => locales/en-US.svg} (100%) rename public/images/{languages/fr.svg => locales/fr-FR.svg} (100%) create mode 100644 utils/constants.ts diff --git a/app/error.tsx b/app/error.tsx new file mode 100644 index 0000000..5dcf921 --- /dev/null +++ b/app/error.tsx @@ -0,0 +1,21 @@ +'use client' + +import { useEffect } from 'react' + +import { ErrorPage } from '@/components/ErrorPage' + +export interface ErrorHandlingProps { + error: Error +} + +const ErrorHandling = (props: ErrorHandlingProps): JSX.Element => { + const { error } = props + + useEffect(() => { + console.error(error) + }, [error]) + + return +} + +export default ErrorHandling diff --git a/styles/global.css b/app/globals.css similarity index 100% rename from styles/global.css rename to app/globals.css diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..1c3463d --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,71 @@ +import type { Metadata } from 'next' + +import '@fontsource/montserrat/400.css' +import '@fontsource/montserrat/600.css' +import './globals.css' + +import { Providers } from '@/components/Providers' +import { Header } from '@/components/Header' +import { Footer } from '@/components/Footer' +import { getI18n } from '@/i18n/i18n.server' + +const title = 'Théo LUDWIG' +const description = + 'Théo LUDWIG - Developer Full Stack • Open-Source enthusiast' +const image = '/images/icon-96x96.png' +const url = new URL('https://theoludwig.fr') +const locale = 'fr-FR, en-US' + +export const metadata: Metadata = { + title, + description, + metadataBase: url, + openGraph: { + title, + description, + url, + siteName: title, + images: [ + { + url: image, + width: 96, + height: 96 + } + ], + locale, + type: 'website' + }, + icons: { + icon: '/images/icon-96x96.png' + }, + twitter: { + card: 'summary', + title, + description, + images: [image] + } +} + +interface RootLayoutProps { + children: React.ReactNode +} + +const RootLayout = (props: RootLayoutProps): JSX.Element => { + const { children } = props + + const i18n = getI18n() + + return ( + + + +
+ {children} +