現代オープンソースポートフォリオの開発👨🏾💻
43970 ワード
かなりの時間の間、私は私のポートフォリオウェブサイトに取り組んでいましたwww.josemukorivo.com . 私が私がインターンシップをしていたとき、私がこれの前に使っていたポートフォリオは、2018年に戻って開発されました.最近、私はそれが時代遅れであると感じました、実際、サイトが発射の後、決して更新されませんでした.
私はポートフォリオの開発者遊び場として考えることが好きですので、時々、10のレプリカとKubernetes😃 単に開発者がいくつかのクールなKubernetes機能をテストしたいので.ここでの私のポイントは、私が選んだスタックがポートフォリオのためのオーバーキルであるかもしれないということです😎?
私がポートフォリオを開発し始める前に、私は私が私のポートフォリオが欲しかったもののwiflamesをつくることによって始めました.私はペンと小さな本を使ってこれらの無線を作成しました.以下はポートフォリオのサンプルワイヤーフレームです.
ワイレッドズを設計した後figma 私が開発に使用した実際のデザインのために.ポートフォリオ上のすべては、開発中にいくつかのものが追加されたFigmaで設計されていないことに注意してください、私はデザインを変更したので、コード化されていないfigmaに設計されたいくつかのものもあります.以下は、デザインの最初の反復がどう図のように見えたかです.
デザインの後の次のものは、ウェブサイトのために内容を生成していました.私にとって、それは難しいステージのうちの1つでした、しかし、幸いに、私はあまりに多くの内容が欲しくありませんでした.信じられるGitHub Copilot いくつかの内容で私を助けてくれた🤔, 私は、AIがその利益であることを意味します👌🏼.
コンテンツのデザインと生成後、ポートフォリオの開発を開始しました.私が詳細に入る前に、あなたに私にポートフォリオを供給しているもののいくつかのリストを与えさせました.
React UI用
NextJS SSG/SSR/ISSG
Tailwind css スタイリング クラス名衝突なしでCSSモジュールスタイル
Mailchimp Vercel GitHub Framer motion TypeScript 開発は最も興味深いステージだったので、私はおそらくここでもう少し多くの時間を過ごすつもりです.このポートフォリオのコアではReactJS . 私はすべてのコンポーネントを作成するために反応を使用します.下記は再利用可能なサンプルです
ボタン.TSX
ボタン.モジュールです.SCSS
これらの小さなコンポーネント
このポートフォリオはライトモードとダークモードの両方を持っています.これはテールウインドのダークモードサポートによって簡単になりました.サイトを最初に訪れたとき、あなたのシステムの設定でダークモードが有効になっているかどうかを確認します.暗闇と光のモードを切り替えることができますボタンもあります.私もテーマを切り替えるためのカスタムフックを作成し、私はそれのコードを表示させてください.
useTheme hook
使用例
これは単純なポートフォリオのウェブサイトだったにもかかわらず、私はそれが検索エンジンフレンドリーであることを確認しなければならなかった.私は
ページ.TSX
例ページ用法
私はまた、ソーシャルメディア上で共有するときにサイトがいくつかの良い意見を持っていることを確認するためにいくつかのオープングラフタグを使用しました.
私のブログはストレートから来ています、そして、私はNextjsを使っているので、そのようにビルド時間でブログ内容でページを構築します.nextjsの詳細は見つかりますhere
私は、ウェブサイトをカスタマイズするためのウィジェットを追加しました.それは、ユーザーが光と暗いモードを切り替えるために使用するものですが、彼らはまた、色相フィルタを適用するか、右から左に読む人々のために有用であるかもしれないテキストの配置を変更するには、ウェブサイトを黒と白に変えるためにそれを使用することができます.他の機能を働かせると、このウィジェットはまだ開発中です.このウィジェットのアイデアは私のものから来ました.
私はまた、私はWeb開発といくつかのクラウド技術についていくつかのヒントを共有するメーリングリストを運営している.購読すれば嬉しいです😎. メーリングリストはmailchimpを使用して実行されます.
このポートフォリオはVercel そして、私がGithubの上で主要な支店に押すたびに、それは再建します.
私は他の人々がそれから学ぶことができて、また、改善するのを助けるように、私のポートフォリオをオープンソースしました.あなたは自由にフォークし、レポと常に改善と他のクールな機能とプル要求を提出するために歓迎スター😎.
ここへのリンクはrepository
コードをコピーしないでください、そして、変更なしでそれをホストしてください.あなたが私のもののように正確に見えないようにデザインと他のものを変えるようにしてくださいwww.josemukorivo.com 常に有り難いです.
私はこの記事が何かを助けてくれることを願っています.あなたは私に従うか、私の購読することができますmailing list 私が働いていることに関する若干の情報を得るために.
旧ウェブサイトヒーローセクション
概要
私はポートフォリオの開発者遊び場として考えることが好きですので、時々、10のレプリカとKubernetes😃 単に開発者がいくつかのクールなKubernetes機能をテストしたいので.ここでの私のポイントは、私が選んだスタックがポートフォリオのためのオーバーキルであるかもしれないということです😎?
デザイン
私がポートフォリオを開発し始める前に、私は私が私のポートフォリオが欲しかったもののwiflamesをつくることによって始めました.私はペンと小さな本を使ってこれらの無線を作成しました.以下はポートフォリオのサンプルワイヤーフレームです.
ワイレッドズを設計した後figma 私が開発に使用した実際のデザインのために.ポートフォリオ上のすべては、開発中にいくつかのものが追加されたFigmaで設計されていないことに注意してください、私はデザインを変更したので、コード化されていないfigmaに設計されたいくつかのものもあります.以下は、デザインの最初の反復がどう図のように見えたかです.
内容
デザインの後の次のものは、ウェブサイトのために内容を生成していました.私にとって、それは難しいステージのうちの1つでした、しかし、幸いに、私はあまりに多くの内容が欲しくありませんでした.信じられるGitHub Copilot いくつかの内容で私を助けてくれた🤔, 私は、AIがその利益であることを意味します👌🏼.
開発
コンテンツのデザインと生成後、ポートフォリオの開発を開始しました.私が詳細に入る前に、あなたに私にポートフォリオを供給しているもののいくつかのリストを与えさせました.
React UI用
NextJS SSG/SSR/ISSG
Tailwind css スタイリング
Button
コンポーネントとそのスタイル.ボタン.TSX
import {
FC,
forwardRef,
useRef,
ButtonHTMLAttributes,
JSXElementConstructor,
} from 'react';
import Link from 'next/link';
import cn from 'classnames';
import s from './Button.module.scss';
import { mergeRefs } from '@utils/index';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
href?: string;
className?: string;
disabled?: boolean;
loading?: boolean;
target?: '_blank' | '_self' | '_parent' | '_top';
size?: 'sm' | 'md' | 'lg';
type?: 'button' | 'submit' | 'reset';
variant?: 'primary' | 'secondary' | 'naked';
as?: 'button' | 'a' | JSXElementConstructor<any>;
}
export const Button: FC<ButtonProps> = forwardRef((props, buttonRef) => {
const {
as: Tag = 'button',
variant = 'naked',
size = 'md',
type = 'button',
target = '_self',
href,
className,
disabled,
children,
...rest
} = props;
const ref = useRef<typeof Tag>(null);
const classes = cn(
s.root,
{
[s.primary]: variant === 'primary',
[s.secondary]: variant === 'secondary',
[s.naked]: variant === 'naked',
[s.sm]: size === 'sm',
[s.md]: size === 'md',
[s.lg]: size === 'lg',
[s.disabled]: disabled,
},
className
);
return (
<>
{href ? (
<Tag ref={mergeRefs([ref, buttonRef])} {...rest}>
<Link href={href}>
<a className={classes} target={target}>
{children}
</a>
</Link>
</Tag>
) : (
<Tag
ref={mergeRefs([ref, buttonRef])}
disabled={disabled}
className={classes}
{...rest}
>
{children}
</Tag>
)}
</>
);
});
Button.displayName = 'Button';
ボタン.モジュールです.SCSS
.root {
@apply mb-1 inline-block transition duration-200 ease-linear;
}
.primary {
@apply bg-rose-500 text-white ring-rose-500 ring-offset-2 hover:bg-rose-600 hover:ring dark:ring-offset-slate-900 2xl:ring-offset-4;
}
.secondary {
@apply bg-slate-800 text-white ring-slate-800 ring-offset-2 hover:bg-slate-900 hover:ring dark:bg-slate-700 dark:ring-slate-700 dark:ring-offset-slate-900 2xl:ring-offset-4;
}
.naked {
@apply bg-white text-slate-900;
}
.md {
@apply px-6 py-2;
}
.lg {
@apply px-7 py-4 text-sm md:px-8;
}
.disabled {
@apply cursor-not-allowed opacity-30;
}
コンポーネントは、タイプセーフのタイプスクリプトを使用してコードです.TypeScriptはまた、自己文書化されているコードを書くことに役立ちます.スタイリング用tailwindcss
しかし、対応するコンポーネントのクラスがクリーンであることに注意してください.CSS module
. CSSモジュールは、CSSクラスの名前空間衝突を避けるのに役立ちます.以下はどのようになりますButton
を使用できます.<Button
variant='primary'
size='lg'
href='/blog'
className='uppercase'
>
Read my blog
</Button>
私の再利用可能なコンポーネントのほとんどすべてがこのように符号化されます.これらの小さなコンポーネント
Button
, Text
, Link
and Box
はcomponents/ui/
フォルダを使用してエクスポートindex.ts
そうすることができるようにファイルをimport { Text, Box, Container, Link, Button } from '@components/ui';
ヒーローのセクションのようなセクションはcomponents/sections/
フォルダとそのような共通の要素Navigation
and Footer
中にいるcomponents/common/
フォルダ.ダークモード
このポートフォリオはライトモードとダークモードの両方を持っています.これはテールウインドのダークモードサポートによって簡単になりました.サイトを最初に訪れたとき、あなたのシステムの設定でダークモードが有効になっているかどうかを確認します.暗闇と光のモードを切り替えることができますボタンもあります.私もテーマを切り替えるためのカスタムフックを作成し、私はそれのコードを表示させてください.
useTheme hook
import { useEffect, useState } from 'react';
export const useTheme = () => {
const getTheme = (): 'light' | 'dark' => {
// Check user preference for theme first
if (
window.localStorage.theme === 'dark' ||
(!('theme' in window.localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
return 'dark';
} else {
return 'light';
}
};
const [theme, setTheme] = useState('');
const toggleTheme = () => {
if (theme === 'light') {
setTheme('dark');
window.localStorage.setItem('theme', 'dark');
} else {
setTheme('light');
window.localStorage.setItem('theme', 'light');
}
};
useEffect(() => {
setTheme(getTheme());
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, [theme]);
return { theme, toggleTheme };
};
使用例
import { BiSun, BiMoon } from 'react-icons/bi';
import { useTheme } from 'hooks';
export const Example = () => {
const { theme, toggleTheme } = useTheme();
return (
<Box>
<Button onClick={toggleTheme}>
{theme === 'dark' ? (
<BiSun className='h-4 w-auto' />
) : (
<BiMoon className='h-4 w-auto' />
)}
{theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'}
</Button>
</Box>
);
};
SEO
これは単純なポートフォリオのウェブサイトだったにもかかわらず、私はそれが検索エンジンフレンドリーであることを確認しなければならなかった.私は
Page
いくつかのSEOデータをpropsとして、サイト上のすべてのページを取得するコンポーネントは、親として使用します.ページ.TSX
import { FC } from 'react';
import Head from 'next/head';
interface Props {
title: string;
description: string;
image: string;
canonicalURL?: string;
}
export const Page: FC<Props> = ({
children,
title,
description,
image,
canonicalURL,
}) => {
return (
<>
<Head>
<title>{title}</title>
<meta name='description' content={description} />
<meta
name='keywords'
content='Joseph, Mukorivo, Joseph Mukorivo, software engineer, Harare, Zimbabwe, Harare software developer, zimbabwe developer blog, software development blog, DevOps blog, Cloud Computing blog, React Developer, React Blog'
/>
<meta name='author' content='Joseph Mukorivo' />
<meta name='image' content={image} />
<meta name='og:title' content={title} />
<meta name='og:description' content={description} />
<meta name='og:image' content={image} />
<meta name='og:url' content='https://josemukorivo.com' />
<meta name='og:site_name' content='Joseph Mukorivo' />
<meta name='og:type' content='website' />
<meta name='twitter:card' content='summary_large_image' />
<meta name='twitter:title' content={title} />
<meta name='twitter:alt' content={title} />
<meta name='twitter:description' content={description} />
<meta name='twitter:image' content={image} />
<meta name='theme-color' content='#f43f5e' />
<meta name='twitter:site' content='@josemukorivo' />
<meta name='twitter:creator' content='@josemukorivo' />
{canonicalURL && <link rel='canonical' href={canonicalURL} />}
</Head>
<main>{children}</main>
</>
);
};
例ページ用法
import { About, Hero, LatestBlogs, TechStack } from '@components/sections';
import { Footer, Nav, Page } from '@components/common';
export default function Home({ articles }) {
return (
<Page
title='Joseph Mukorivo | Software Engineer'
description='Joseph Mukorivo is a Software Engineer, Blogger and DevOps Enthusiat based in Harare, Zimbabwe.'
image='https://josemukorivo.com/images/me.jpeg'
>
<Nav className='absolute py-3 md:py-5' />
<Hero />
<About />
<LatestBlogs articles={articles} />
<TechStack />
<Footer />
</Page>
);
}
Google Analytics、Google MyビジネスとSEOのためのGoogle検索コンソールのような他のツールも使用しました.今私の名前の簡単なGoogle検索Joseph Mukorivo
ユーザーに私に関する詳細情報を与えます.私はまた、ソーシャルメディア上で共有するときにサイトがいくつかの良い意見を持っていることを確認するためにいくつかのオープングラフタグを使用しました.
ブログ
私のブログはストレートから来ています、そして、私はNextjsを使っているので、そのようにビルド時間でブログ内容でページを構築します.nextjsの詳細は見つかりますhere
export async function getStaticProps() {
const res = await fetch(
`https://dev.to/api/articles?username=${DEV_TO_USERNAME}&per_page=5`
);
const articles = await res.json();
return {
props: {
articles,
},
revalidate: 60,
};
}
クール機能
私は、ウェブサイトをカスタマイズするためのウィジェットを追加しました.それは、ユーザーが光と暗いモードを切り替えるために使用するものですが、彼らはまた、色相フィルタを適用するか、右から左に読む人々のために有用であるかもしれないテキストの配置を変更するには、ウェブサイトを黒と白に変えるためにそれを使用することができます.他の機能を働かせると、このウィジェットはまだ開発中です.このウィジェットのアイデアは私のものから来ました.
メーリングリスト
私はまた、私はWeb開発といくつかのクラウド技術についていくつかのヒントを共有するメーリングリストを運営している.購読すれば嬉しいです😎. メーリングリストはmailchimpを使用して実行されます.
ホスティング
このポートフォリオはVercel そして、私がGithubの上で主要な支店に押すたびに、それは再建します.
ファイナル・モード・ヒーロー
倉庫
私は他の人々がそれから学ぶことができて、また、改善するのを助けるように、私のポートフォリオをオープンソースしました.あなたは自由にフォークし、レポと常に改善と他のクールな機能とプル要求を提出するために歓迎スター😎.
ここへのリンクはrepository
どうぞ
コードをコピーしないでください、そして、変更なしでそれをホストしてください.あなたが私のもののように正確に見えないようにデザインと他のものを変えるようにしてくださいwww.josemukorivo.com 常に有り難いです.
私はこの記事が何かを助けてくれることを願っています.あなたは私に従うか、私の購読することができますmailing list 私が働いていることに関する若干の情報を得るために.
Reference
この問題について(現代オープンソースポートフォリオの開発👨🏾💻), 我々は、より多くの情報をここで見つけました https://dev.to/josemukorivo/how-i-developed-my-modern-open-source-portfolio-2o92テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol