import FeedIcon from '@assets/images/icon-feed.svg'; import ButtonLink from '@components/atoms/buttons/button-link'; import Envelop from '@components/atoms/icons/envelop'; import Column, { type ColumnProps } from '@components/atoms/layout/column'; import Section, { type SectionProps } from '@components/atoms/layout/section'; import List, { type ListItem } from '@components/atoms/lists/list'; import ResponsiveImage, { type ResponsiveImageProps, } from '@components/molecules/images/responsive-image'; import Columns, { type ColumnsProps, } from '@components/molecules/layout/columns'; import CardsList, { type CardsListItem, } from '@components/organisms/layout/cards-list'; import Layout from '@components/templates/layout/layout'; import HomePageContent from '@content/pages/homepage.mdx'; import { getArticlesCard } from '@services/graphql/articles'; import styles from '@styles/pages/home.module.scss'; import { ArticleCard } from '@ts/types/app'; import { loadTranslation, type Messages } from '@utils/helpers/i18n'; import useSettings from '@utils/hooks/use-settings'; import { NestedMDXComponents } from 'mdx/types'; import { GetStaticProps, NextPage } from 'next'; import Head from 'next/head'; import Script from 'next/script'; import { ReactElement } from 'react'; import { useIntl } from 'react-intl'; import { Graph, WebPage } from 'schema-dts'; type HomeProps = { recentPosts: ArticleCard[]; translation?: Messages; }; /** * Home page. */ const HomePage: NextPage = ({ recentPosts }) => { const intl = useIntl(); /** * Retrieve a list of coding links. * * @returns {JSX.Element} - A list of links. */ const CodingLinks = (): JSX.Element => { const links: ListItem[] = [ { id: 'web-development', value: ( {intl.formatMessage({ defaultMessage: 'Web development', description: 'HomePage: link to web development thematic', id: 'vkF/RP', })} ), }, { id: 'projects', value: ( {intl.formatMessage({ defaultMessage: 'Projects', description: 'HomePage: link to projects', id: 'N44SOc', })} ), }, ]; return ; }; /** * Retrieve a list of Coldark repositories. * * @returns {JSX.Element} - A list of links. */ const ColdarkRepos = (): JSX.Element => { const links: ListItem[] = [ { id: 'coldark-github', value: ( {intl.formatMessage({ defaultMessage: 'Github', description: 'HomePage: Github link', id: '3f3PzH', })} ), }, { id: 'coldark-gitlab', value: ( {intl.formatMessage({ defaultMessage: 'Gitlab', description: 'HomePage: Gitlab link', id: '7AnwZ7', })} ), }, ]; return ; }; /** * Retrieve a list of links related to Free thematic. * * @returns {JSX.Element} - A list of links. */ const LibreLinks = (): JSX.Element => { const links: ListItem[] = [ { id: 'free', value: ( {intl.formatMessage({ defaultMessage: 'Free', description: 'HomePage: link to free thematic', id: 'w8GrOf', })} ), }, { id: 'linux', value: ( {intl.formatMessage({ defaultMessage: 'Linux', description: 'HomePage: link to Linux thematic', id: 'jASD7k', })} ), }, ]; return ; }; /** * Retrieve the Shaarli link. * * @returns {JSX.Element} - A list of links */ const ShaarliLink = (): JSX.Element => { const links: ListItem[] = [ { id: 'shaarli', value: ( {intl.formatMessage({ defaultMessage: 'Shaarli', description: 'HomePage: link to Shaarli', id: 'i5L19t', })} ), }, ]; return ; }; /** * Retrieve the additional links. * * @returns {JSX.Element} - A list of links. */ const MoreLinks = (): JSX.Element => { const links: ListItem[] = [ { id: 'contact-me', value: ( {intl.formatMessage({ defaultMessage: 'Contact me', description: 'HomePage: contact button text', id: 'sO/Iwj', })} ), }, { id: 'rss-feed', value: ( {intl.formatMessage({ defaultMessage: 'Subscribe', description: 'HomePage: RSS feed subscription text', id: 'T4YA64', })} ), }, ]; return ; }; /** * Get a cards list of recent posts. * * @returns {JSX.Element} - The cards list. */ const getRecentPosts = (): JSX.Element => { const posts: CardsListItem[] = recentPosts.map((post) => { return { cover: post.cover, id: post.slug, meta: { publication: { date: post.dates.publication } }, title: post.title, url: `/article/${post.slug}`, }; }); return ( ); }; /** * Create the page sections. * * @param {object} obj - An object containing the section body. * @param {ReactElement[]} obj.children - The section body. * @returns {JSX.Element} A section element. */ const getSection = ({ children, variant, }: { children: ReactElement[]; variant: SectionProps['variant']; }): JSX.Element => { const [headingEl, ...content] = children; const title = headingEl.props.children; return (
); }; const components: NestedMDXComponents = { CodingLinks: CodingLinks, ColdarkRepos: ColdarkRepos, Column: (props: ColumnProps) => , Columns: (props: ColumnsProps) => ( ), Image: (props: ResponsiveImageProps) => , LibreLinks: LibreLinks, MoreLinks: MoreLinks, RecentPosts: getRecentPosts, Section: getSection, ShaarliLink: ShaarliLink, }; const { website } = useSettings(); const pageTitle = intl.formatMessage( { defaultMessage: '{websiteName} | Front-end developer: WordPress/React', description: 'HomePage: SEO - Page title', id: 'PXp2hv', }, { websiteName: website.name } ); const pageDescription = intl.formatMessage( { defaultMessage: '{websiteName} is a front-end developer located in France. He codes and he writes mostly about web development and open-source.', description: 'HomePage: SEO - Meta description', id: 'tMuNTy', }, { websiteName: website.name } ); const webpageSchema: WebPage = { '@id': `${website.url}/#home`, '@type': 'WebPage', name: pageTitle, description: pageDescription, author: { '@id': `${website.url}/#branding` }, creator: { '@id': `${website.url}/#branding` }, editor: { '@id': `${website.url}/#branding` }, inLanguage: website.locales.default, license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr', reviewedBy: { '@id': `${website.url}/#branding` }, url: `${website.url}`, }; const schemaJsonLd: Graph = { '@context': 'https://schema.org', '@graph': [webpageSchema], }; return ( {pageTitle}