Add prettier configuration

This commit is contained in:
Hazem Krimi
2023-07-01 00:38:49 +01:00
parent de22cafb12
commit 5e01140d6e
57 changed files with 1896 additions and 1718 deletions
+32 -32
View File
@@ -4,45 +4,45 @@ import IconButton from '../components/IconButton';
import { Wrapper } from '../styles/404';
const NotFound = () => {
const router = useRouter();
const router = useRouter();
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>404 Not Found | Hazem Krimi</title>
</Head>
<Wrapper>
<h1>404: This page could not be found</h1>
<div className='back' onClick={() => router.push('/')}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Go Home</span>
</div>
</Wrapper>
</>
);
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>404 Not Found | Hazem Krimi</title>
</Head>
<Wrapper>
<h1>404: This page could not be found</h1>
<div className='back' onClick={() => router.push('/')}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Go Home</span>
</div>
</Wrapper>
</>
);
};
export default NotFound;
+39 -39
View File
@@ -20,50 +20,50 @@ import { initStyles } from '../utils/styles';
NProgress.configure({ showSpinner: false });
const App = ({ Component, pageProps }: AppProps) => {
const router = useRouter();
const router = useRouter();
useEffect(() => {
router.events.on('routeChangeStart', () => {
NProgress.start();
});
useEffect(() => {
router.events.on('routeChangeStart', () => {
NProgress.start();
});
router.events.on('routeChangeComplete', url => {
NProgress.done();
pageview(url);
});
router.events.on('routeChangeComplete', (url) => {
NProgress.done();
pageview(url);
});
router.events.on('routeChangeError', () => {
NProgress.done();
});
router.events.on('routeChangeError', () => {
NProgress.done();
});
return () => {
router.events.off('routeChangeComplete', url => {
pageview(url);
});
};
}, [router.events]);
return () => {
router.events.off('routeChangeComplete', (url) => {
pageview(url);
});
};
}, [router.events]);
return (
<>
<Script
id='styles-init'
strategy='afterInteractive'
dangerouslySetInnerHTML={{
__html: initStyles()
}}
/>
<Theme>
<SharedStyles>
<GlobalStyles />
<Container>
<Nav />
<Component {...pageProps} />
<Footer />
</Container>
</SharedStyles>
</Theme>
</>
);
return (
<>
<Script
id='styles-init'
strategy='afterInteractive'
dangerouslySetInnerHTML={{
__html: initStyles(),
}}
/>
<Theme>
<SharedStyles>
<GlobalStyles />
<Container>
<Nav />
<Component {...pageProps} />
<Footer />
</Container>
</SharedStyles>
</Theme>
</>
);
};
export default App;
+72 -55
View File
@@ -1,4 +1,10 @@
import Document, { DocumentContext, Html, Head, Main, NextScript } from 'next/document';
import Document, {
DocumentContext,
Html,
Head,
Main,
NextScript,
} from 'next/document';
import { ServerStyleSheet } from 'styled-components';
@@ -6,63 +12,74 @@ import { GOOGLE_ANALYTICS_KEY, initAnalytics } from '../utils/gtag';
import { initStyles } from '../utils/styles';
class Doc extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
});
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
}
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render() {
return (
<Html>
<Head>
<link rel='shortcut icon' href='/light-favicon.png' id='light-favicon'></link>
<link rel='shortcut icon' href='/dark-favicon.png' id='dark-favicon'></link>
<link rel='preconnect' href='https://fonts.gstatic.com' />
<link
href='https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;700&display=swap'
rel='stylesheet'
/>
<script src={`https://www.googletagmanager.com/gtag/js?id=${GOOGLE_ANALYTICS_KEY}`} />
<script
id='analytics-init'
dangerouslySetInnerHTML={{
__html: initAnalytics()
}}
/>
<script
id='styles-init'
dangerouslySetInnerHTML={{
__html: initStyles()
}}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
render() {
return (
<Html>
<Head>
<link
rel='shortcut icon'
href='/light-favicon.png'
id='light-favicon'
></link>
<link
rel='shortcut icon'
href='/dark-favicon.png'
id='dark-favicon'
></link>
<link rel='preconnect' href='https://fonts.gstatic.com' />
<link
href='https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;700&display=swap'
rel='stylesheet'
/>
<script
src={`https://www.googletagmanager.com/gtag/js?id=${GOOGLE_ANALYTICS_KEY}`}
/>
<script
id='analytics-init'
dangerouslySetInnerHTML={{
__html: initAnalytics(),
}}
/>
<script
id='styles-init'
dangerouslySetInnerHTML={{
__html: initStyles(),
}}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default Doc;
+105 -101
View File
@@ -14,126 +14,130 @@ import readingTime from 'reading-time';
import Image from 'next/image';
interface Props {
source: MDXRemoteSerializeResult;
frontMatter: any;
text: string;
source: MDXRemoteSerializeResult;
frontMatter: any;
text: string;
}
const BlogPost = ({ source, frontMatter, text }: Props) => {
const router = useRouter();
const stats = readingTime(text);
const htmlOverrides = { code: CodeBlock };
const mdxComponents = {};
const router = useRouter();
const stats = readingTime(text);
const htmlOverrides = { code: CodeBlock };
const mdxComponents = {};
useEffect(() => {
window.scrollTo(0, 0);
}, []);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.`
}
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
}
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.`
}
/>
<meta property='og:title' content={`${frontMatter?.title} | Hazem Krimi`} />
<meta
name='keywords'
content={
frontMatter?.tags
? frontMatter.tags.join(' ')
: `Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js`
}
/>
<title>{`${frontMatter?.title} | Hazem Krimi`}</title>
</Head>
<Wrapper>
<div className='meta'>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>{frontMatter?.title}</h1>
<p>{frontMatter?.description}</p>
<p>
By <b>{frontMatter?.author}</b> on <b>{frontMatter?.date}</b> ({stats.text})
</p>
{frontMatter?.tags ? (
<div className='tags-wrapper'>
{frontMatter.tags.map((tag: string, index: number) => (
<span key={index}>#{tag}&nbsp;</span>
))}
</div>
) : null}
{frontMatter?.image ? (
<div className='image'>
<Image alt={frontMatter?.title} src={frontMatter?.image} fill />
</div>
) : null}
<hr />
</div>
<MDXProvider components={{ ...htmlOverrides, ...mdxComponents }}>
<div className='content'>
<MDXRemote {...source} />
</div>
</MDXProvider>
</Wrapper>
</>
);
}
/>
<meta
property='og:title'
content={`${frontMatter?.title} | Hazem Krimi`}
/>
<meta
name='keywords'
content={
frontMatter?.tags
? frontMatter.tags.join(' ')
: `Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js`
}
/>
<title>{`${frontMatter?.title} | Hazem Krimi`}</title>
</Head>
<Wrapper>
<div className='meta'>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>{frontMatter?.title}</h1>
<p>{frontMatter?.description}</p>
<p>
By <b>{frontMatter?.author}</b> on <b>{frontMatter?.date}</b> (
{stats.text})
</p>
{frontMatter?.tags ? (
<div className='tags-wrapper'>
{frontMatter.tags.map((tag: string, index: number) => (
<span key={index}>#{tag}&nbsp;</span>
))}
</div>
) : null}
{frontMatter?.image ? (
<div className='image'>
<Image alt={frontMatter?.title} src={frontMatter?.image} fill />
</div>
) : null}
<hr />
</div>
<MDXProvider components={{ ...htmlOverrides, ...mdxComponents }}>
<div className='content'>
<MDXRemote {...source} />
</div>
</MDXProvider>
</Wrapper>
</>
);
};
export default BlogPost;
export const getStaticPaths: GetStaticPaths = async () => {
const paths = getBlogPostsSlugs();
return {
paths,
fallback: false
};
const paths = getBlogPostsSlugs();
return {
paths,
fallback: false,
};
};
export const getStaticProps: GetStaticProps = async ({ params }: any) => {
const blogPostContent = await getBlogPostdata(params.slug);
const blogPostContent = await getBlogPostdata(params.slug);
if (!blogPostContent)
return {
props: {
source: undefined,
frontMatter: undefined
}
};
if (!blogPostContent)
return {
props: {
source: undefined,
frontMatter: undefined,
},
};
const { data, content } = matter(blogPostContent);
const mdxSource = await serialize(content, {
scope: data
});
const { data, content } = matter(blogPostContent);
const mdxSource = await serialize(content, {
scope: data,
});
return {
props: {
source: mdxSource,
frontMatter: data,
text: content
}
};
return {
props: {
source: mdxSource,
frontMatter: data,
text: content,
},
};
};
+56 -56
View File
@@ -6,69 +6,69 @@ import IconButton from '../../components/IconButton';
import Head from 'next/head';
interface Props {
blogPosts: {
title: string;
author: string;
description: string;
image?: string;
slug: string;
date: string;
tags?: string[];
}[];
blogPosts: {
title: string;
author: string;
description: string;
image?: string;
slug: string;
date: string;
tags?: string[];
}[];
}
const Index = ({ blogPosts }: Props) => {
const router = useRouter();
const router = useRouter();
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is a Full Stack JavaScript Developer and a Software Engineering Enthusiast'
/>
<link rel='canonical' href='https://hazemkrimi.tech/blog' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is a Full Stack JavaScript Developer and a Software Engineering Enthusiast'
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News'
/>
<title>Blog | Hazem Krimi</title>
</Head>
<Wrapper>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>Blog</h1>
<div className='articles-wrapper'>
{blogPosts.length !== 0 ? (
blogPosts.map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/blog/${slug}`} />
))
) : (
<h4>Nothing for now</h4>
)}
</div>
</Wrapper>
</>
);
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is a Full Stack JavaScript Developer and a Software Engineering Enthusiast'
/>
<link rel='canonical' href='https://hazemkrimi.tech/blog' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is a Full Stack JavaScript Developer and a Software Engineering Enthusiast'
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News'
/>
<title>Blog | Hazem Krimi</title>
</Head>
<Wrapper>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>Blog</h1>
<div className='articles-wrapper'>
{blogPosts.length !== 0 ? (
blogPosts.map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/blog/${slug}`} />
))
) : (
<h4>Nothing for now</h4>
)}
</div>
</Wrapper>
</>
);
};
export default Index;
export const getStaticProps = async () => {
const blogPosts = getBlogPosts();
return {
props: {
blogPosts
}
};
const blogPosts = getBlogPosts();
return {
props: {
blogPosts,
},
};
};
+113 -95
View File
@@ -6,110 +6,128 @@ import Input from '../components/Input';
import MDXButton from '../components/MDXButton';
const About = () => {
const [form, setForm] = useState<{ name: string; email: string; message: string }>({
name: '',
email: '',
message: ''
});
const [state, Submit] = useForm(`${process.env.NEXT_PUBLIC_FORMSPREE_KEY}`);
const [submitted, setSubmitted] = useState<boolean>(false);
const [form, setForm] = useState<{
name: string;
email: string;
message: string;
}>({
name: '',
email: '',
message: '',
});
const [state, Submit] = useForm(`${process.env.NEXT_PUBLIC_FORMSPREE_KEY}`);
const [submitted, setSubmitted] = useState<boolean>(false);
const handleChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setForm({ ...form, [event.target.name]: event.target.value });
};
const handleChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
setForm({ ...form, [event.target.name]: event.target.value });
};
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
try {
await Submit(event);
setSubmitted(true);
} finally {
setTimeout(() => setSubmitted(false), 1000);
setForm({ name: '', email: '', message: '' });
}
};
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
try {
await Submit(event);
setSubmitted(true);
} finally {
setTimeout(() => setSubmitted(false), 1000);
setForm({ name: '', email: '', message: '' });
}
};
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>Contact | Hazem Krimi</title>
</Head>
<Wrapper>
<div className='content'>
<div>
<h1>Contact Me {submitted && <span className='success'>Message sent </span>}</h1>
<form className='contact' onSubmit={handleSubmit}>
<Input
type='text'
placeholder='Name'
variant='small'
name='name'
required
value={form.name}
onChange={handleChange}
/>
<ValidationError className='error' prefix='Name' field='name' errors={state.errors} />
<Input
type='text'
placeholder='Email'
variant='small'
name='email'
required
value={form.email}
onChange={handleChange}
/>
<ValidationError
className='error'
prefix='Email'
field='email'
errors={state.errors}
/>
<Input
type='text'
placeholder='Message'
variant='big'
name='message'
required
value={form.message}
onChange={handleChange}
/>
<ValidationError
className='error'
prefix='Message'
field='message'
errors={state.errors}
/>
<MDXButton type='submit' variant='action' disabled={state.submitting || submitted}>
Submit
</MDXButton>
</form>
</div>
</div>
</Wrapper>
</>
);
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>Contact | Hazem Krimi</title>
</Head>
<Wrapper>
<div className='content'>
<div>
<h1>
Contact Me{' '}
{submitted && <span className='success'>Message sent </span>}
</h1>
<form className='contact' onSubmit={handleSubmit}>
<Input
type='text'
placeholder='Name'
variant='small'
name='name'
required
value={form.name}
onChange={handleChange}
/>
<ValidationError
className='error'
prefix='Name'
field='name'
errors={state.errors}
/>
<Input
type='text'
placeholder='Email'
variant='small'
name='email'
required
value={form.email}
onChange={handleChange}
/>
<ValidationError
className='error'
prefix='Email'
field='email'
errors={state.errors}
/>
<Input
type='text'
placeholder='Message'
variant='big'
name='message'
required
value={form.message}
onChange={handleChange}
/>
<ValidationError
className='error'
prefix='Message'
field='message'
errors={state.errors}
/>
<MDXButton
type='submit'
variant='action'
disabled={state.submitting || submitted}
>
Submit
</MDXButton>
</form>
</div>
</div>
</Wrapper>
</>
);
};
export default About;
+91 -88
View File
@@ -8,106 +8,109 @@ import Card from '../components/Card';
import Head from 'next/head';
interface Props {
blogPosts: {
title: string;
author: string;
description: string;
slug: string;
date: string;
tags?: string[];
}[];
projects: {
title: string;
description: string;
slug: string;
date: string;
tags?: string[];
}[];
blogPosts: {
title: string;
author: string;
description: string;
slug: string;
date: string;
tags?: string[];
}[];
projects: {
title: string;
description: string;
slug: string;
date: string;
tags?: string[];
}[];
}
const Index = ({ blogPosts, projects }: Props) => {
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>Hazem Krimi</title>
</Head>
<Wrapper>
<Hero />
<div className='content'>
<h1>About</h1>
<div className='about'>
<p>
Experienced Full Stack developer with a focus on building user-friendly web and cross-platform mobile applications using cutting-edge technologies. Passionate about ongoing learning and staying up-to-date with the latest trends in software engineering.
</p>
</div>
{projects.length !== 0 && (
<>
<h1>Projects</h1>
<Button href='/projects' className='blue'>
See More
</Button>
<div className='projects'>
<div className='projects-wrapper'>
{projects.slice(0, 3).map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/projects/${slug}`} />
))}
</div>
</div>
</>
)}
{blogPosts.length !== 0 && (
<>
<h1>Blog</h1>
<Button href='/blog' className='blue'>
See More
</Button>
<div className='blog'>
<div className='articles-wrapper'>
{blogPosts.slice(0, 3).map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/blog/${slug}`} />
))}
</div>
</div>
</>
)}
</div>
</Wrapper>
</>
);
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>Hazem Krimi</title>
</Head>
<Wrapper>
<Hero />
<div className='content'>
<h1>About</h1>
<div className='about'>
<p>
Experienced Full Stack developer with a focus on building
user-friendly web and cross-platform mobile applications using
cutting-edge technologies. Passionate about ongoing learning and
staying up-to-date with the latest trends in software engineering.
</p>
</div>
{projects.length !== 0 && (
<>
<h1>Projects</h1>
<Button href='/projects' className='blue'>
See More
</Button>
<div className='projects'>
<div className='projects-wrapper'>
{projects.slice(0, 3).map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/projects/${slug}`} />
))}
</div>
</div>
</>
)}
{blogPosts.length !== 0 && (
<>
<h1>Blog</h1>
<Button href='/blog' className='blue'>
See More
</Button>
<div className='blog'>
<div className='articles-wrapper'>
{blogPosts.slice(0, 3).map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/blog/${slug}`} />
))}
</div>
</div>
</>
)}
</div>
</Wrapper>
</>
);
};
export default Index;
export const getStaticProps: GetStaticProps = async () => {
const blogPosts = getBlogPosts();
const projects = getProjects();
return {
props: {
blogPosts,
projects
}
};
const blogPosts = getBlogPosts();
const projects = getProjects();
return {
props: {
blogPosts,
projects,
},
};
};
+115 -104
View File
@@ -14,129 +14,140 @@ import MDXButton from '../../components/MDXButton';
import Image from 'next/image';
interface Props {
source: MDXRemoteSerializeResult;
frontMatter: any;
source: MDXRemoteSerializeResult;
frontMatter: any;
}
const Project = ({ source, frontMatter }: Props) => {
const router = useRouter();
const htmlOverrides = { code: CodeBlock };
const mdxComponents = { Button: MDXButton };
const router = useRouter();
const htmlOverrides = { code: CodeBlock };
const mdxComponents = { Button: MDXButton };
useEffect(() => {
window.scrollTo(0, 0);
}, []);
useEffect(() => {
window.scrollTo(0, 0);
}, []);
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.`
}
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
}
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content={
frontMatter?.description
? frontMatter.description
: `Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.`
}
/>
<meta property='og:title' content={`${frontMatter?.title} | Hazem Krimi`} />
<meta
name='keywords'
content={
frontMatter?.tags
? frontMatter.tags.join(' ')
: `Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js`
}
/>
<title>{`${frontMatter?.title} | Hazem Krimi`}</title>
</Head>
<Wrapper>
<div className='meta'>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>{frontMatter?.title}</h1>
<p>{frontMatter?.description}</p>
{frontMatter?.tags ? (
<div className='tags-wrapper'>
{frontMatter.tags.map((tag: string, index: number) => (
<span key={index}>#{tag}&nbsp;</span>
))}
</div>
) : null}
{frontMatter?.image && !frontMatter?.hideImage ? (
<div className='image'>
<Image alt={frontMatter?.title} src={frontMatter?.image} fill />
</div>
) : null}
<hr />
</div>
<MDXProvider components={{ ...htmlOverrides, ...mdxComponents }}>
<div className='content'>
<MDXRemote {...source} />
<h1>Showcase</h1>
<div className='showcase-buttons'>
<MDXButton variant='action' link={frontMatter?.demo} target='_blank'>
Demo
</MDXButton>
<MDXButton variant='outline' link={frontMatter?.code} target='_blank'>
Source Code
</MDXButton>
</div>
</div>
</MDXProvider>
</Wrapper>
</>
);
}
/>
<meta
property='og:title'
content={`${frontMatter?.title} | Hazem Krimi`}
/>
<meta
name='keywords'
content={
frontMatter?.tags
? frontMatter.tags.join(' ')
: `Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js`
}
/>
<title>{`${frontMatter?.title} | Hazem Krimi`}</title>
</Head>
<Wrapper>
<div className='meta'>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>{frontMatter?.title}</h1>
<p>{frontMatter?.description}</p>
{frontMatter?.tags ? (
<div className='tags-wrapper'>
{frontMatter.tags.map((tag: string, index: number) => (
<span key={index}>#{tag}&nbsp;</span>
))}
</div>
) : null}
{frontMatter?.image && !frontMatter?.hideImage ? (
<div className='image'>
<Image alt={frontMatter?.title} src={frontMatter?.image} fill />
</div>
) : null}
<hr />
</div>
<MDXProvider components={{ ...htmlOverrides, ...mdxComponents }}>
<div className='content'>
<MDXRemote {...source} />
<h1>Showcase</h1>
<div className='showcase-buttons'>
<MDXButton
variant='action'
link={frontMatter?.demo}
target='_blank'
>
Demo
</MDXButton>
<MDXButton
variant='outline'
link={frontMatter?.code}
target='_blank'
>
Source Code
</MDXButton>
</div>
</div>
</MDXProvider>
</Wrapper>
</>
);
};
export default Project;
export const getStaticPaths: GetStaticPaths = async () => {
const paths = getPorjectsSlugs();
return {
paths,
fallback: false
};
const paths = getPorjectsSlugs();
return {
paths,
fallback: false,
};
};
export const getStaticProps: GetStaticProps = async ({ params }: any) => {
const projectContent = await getProjectdata(params.slug);
const projectContent = await getProjectdata(params.slug);
if (!projectContent)
return {
props: {
source: undefined,
frontMatter: undefined
}
};
if (!projectContent)
return {
props: {
source: undefined,
frontMatter: undefined,
},
};
const { data, content } = matter(projectContent);
const mdxSource = await serialize(content, {
scope: data
});
const { data, content } = matter(projectContent);
const mdxSource = await serialize(content, {
scope: data,
});
return {
props: {
source: mdxSource,
frontMatter: data
}
};
return {
props: {
source: mdxSource,
frontMatter: data,
},
};
};
+55 -55
View File
@@ -6,74 +6,74 @@ import IconButton from '../../components/IconButton';
import Head from 'next/head';
interface Props {
projects: {
title: string;
description: string;
image?: string;
slug: string;
date: string;
tags?: string[];
}[];
projects: {
title: string;
description: string;
image?: string;
slug: string;
date: string;
tags?: string[];
}[];
}
const Index = ({ projects }: Props) => {
const router = useRouter();
const router = useRouter();
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
return (
<>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta name='author' content='Hazem Krimi' />
<meta
name='description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
/>
<link rel='canonical' href='https://hazemkrimi.tech' />
<meta property='og:image' content='/logo.png' />
<meta
property='og:description'
content='Hazem Krimi is an experienced Full Stack developer with a focus on building user-friendly
web and cross-platform mobile applications using cutting-edge
technologies. Passionate about ongoing learning and staying up-to-date
with the latest trends in software engineering.'
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>Projects | Hazem Krimi</title>
</Head>
<Wrapper>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>Projects</h1>
<div className='projects-wrapper'>
{projects.length !== 0 ? (
projects.map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/projects/${slug}`} />
))
) : (
<h4>Nothing for now</h4>
)}
</div>
</Wrapper>
</>
);
/>
<meta property='og:title' content='Hazem Krimi' />
<meta
name='keywords'
content='Hazem, Krimi, Hazem Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, TypeScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News, Software Developer, Software Engineer, Full Stack TypeScript Developer, Next.js'
/>
<title>Projects | Hazem Krimi</title>
</Head>
<Wrapper>
<div className='back' onClick={() => router.back()}>
<IconButton alt='Back' icon='/icons/arrow-left.svg' />
<span>Back</span>
</div>
<h1>Projects</h1>
<div className='projects-wrapper'>
{projects.length !== 0 ? (
projects.map(({ slug, ...rest }) => (
<Card {...rest} key={slug} href={`/projects/${slug}`} />
))
) : (
<h4>Nothing for now</h4>
)}
</div>
</Wrapper>
</>
);
};
export default Index;
export const getStaticProps = async () => {
const projects = getProjects();
return {
props: {
projects
}
};
const projects = getProjects();
return {
props: {
projects,
},
};
};