Skip to content
This repository has been archived by the owner on May 30, 2024. It is now read-only.

Make everything for your profile easier to customize #63

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
/.pnp
.pnp.js

# Use Yarn!
package-lock.json

# testing
/coverage

Expand Down Expand Up @@ -45,3 +48,7 @@ yarn-error.log*

# Vercel
.vercel

# JetBrains
.idea/
.fleet/
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lts/gallium
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ npm run build
yarn build
```

## ✍ Customize!

Update files in [`src/data`](/src/data) to get started adding your own information.

Types for each are found in [`src/types`](/src/types).
All the profile information can be customized from [`src/data/profile.json`](src/data/profile.json).
Project post correlation are in [`src/data/projects.json`](src/data/projects.json).
Referrals are in [`src/data/referrals.json`](src/data/referrals.json).
Your personal timeline are found in [`src/data/timeline.json`](src/data/timeline.json).

## 📄 License

MIT © [Ben Dixon](https://github.com/nurodev/nuro.dev/blob/main/LICENSE)
20 changes: 20 additions & 0 deletions src/data/profile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "Ben",
"birthday": "1997-08-09",
"role": "developer",
"bio": "software engineer & games developer",
"alias": "nuro",
"social": {
"twitter": "nurodev",
"github": "nurodev"
},
"projectSrcs": [
{
"type": "users",
"slug": "nurodev",
"ignore": []
}
],
"pagesIgnore": [],
"domain": "nuro.dev"
}
6 changes: 5 additions & 1 deletion src/layouts/Blog.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import { useSeoProps } from '~/lib';

import type { ComponentProps, PropsWithChildren } from 'react';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';
const { alias } = profile as unknown as Profile;

interface BlogLayoutProps {
seo?: Partial<ComponentProps<typeof NextSeo>>;
}

export function BlogLayout({ children, seo }: PropsWithChildren<BlogLayoutProps>): JSX.Element {
const seoProps = useSeoProps({
title: 'nuro ─ blog',
title: `${alias} ─ blog`,
...seo,
});

Expand Down
6 changes: 5 additions & 1 deletion src/layouts/Error.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { useSeoProps } from '~/lib';

import type { WithChildren, WithProps } from '~/types';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';
const { alias } = profile as unknown as Profile;

interface DefaultLayoutProps extends WithChildren {
seo?: Partial<WithProps<typeof NextSeo>>;
}

export function ErrorLayout({ children, seo }: DefaultLayoutProps): JSX.Element {
const seoProps = useSeoProps({
title: 'nuro ─ Whoops!',
title: `${alias} ─ Whoops!`,
...seo,
});

Expand Down
17 changes: 11 additions & 6 deletions src/lib/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import { NavigationItemType, Theme } from '~/types';

import type { NavigationItem, NavigationItems } from '~/types';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';

const { social, pagesIgnore } = profile as unknown as Profile;

const staticMenuItems: Array<Array<NavigationItem>> = [
[
{
Expand Down Expand Up @@ -39,23 +44,23 @@ const staticMenuItems: Array<Array<NavigationItem>> = [
text: 'Referrals',
href: '/referrals',
},
],
].filter(e => !pagesIgnore.includes(e.href)),
[
{
social.twitter && {
type: NavigationItemType.LINK,
icon: 'feather:twitter',
text: 'Twitter',
href: 'https://twitter.com/nurodev',
href: `https://twitter.com/${social.twitter}`,
external: true,
},
{
social.github && {
type: NavigationItemType.LINK,
icon: 'feather:github',
text: 'GitHub',
href: 'https://github.com/nurodev',
href: `https://github.com/${social.github}`,
external: true,
},
],
].filter(e => e),
];

export function useNavigation(): {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export async function getPost(slug: string): Promise<Post> {
const source = await serialize(content, {
scope: data,
mdxOptions: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
rehypePlugins: [[RehypeAutolinkHeadings, {}]],
remarkPlugins: [RemarkCodeTitles, RemarkEmoji, RemarkPrism, RemarkSlug],
},
Expand Down
44 changes: 28 additions & 16 deletions src/lib/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,11 @@ import emojiRegex from 'emoji-regex';
import { log } from 'next-axiom';

import type { GitHubRepos, Project, ProjectPost } from '~/types';
import { projectSrcs } from '~/data/profile.json';
import { ProjectSrc } from '~/types/profile';

/**
* Fetch Projects
*
* Make a GET request to the GitHub API to gather all repositories
* under my `nurodev` username & then filter them down to only
* include those that contain the `portfolio` topic
*
* @TODO Switch to v3 API using GraphQL to save over-fetching
*/
export async function fetchProjects(): Promise<Array<Project> | null> {
const response = await fetch('https://api.github.com/users/nurodev/repos', {
const fetchRepos = async ({ slug, type, ignore }: ProjectSrc): Promise<GitHubRepos> => {
const response = await fetch(`https://api.github.com/${type}/${slug}/repos`, {
headers: {
...(process.env.GITHUB_PAT && {
authorization: `token ${process.env.GITHUB_PAT}`,
Expand All @@ -34,19 +27,40 @@ export async function fetchProjects(): Promise<Array<Project> | null> {
return null;
}

const json = (await response.json()) as GitHubRepos;
const repos = await response.json() as GitHubRepos;

return repos.filter((repo) => {
return !ignore.includes(repo.name);
});
}

/**
* Fetch Projects
*
* Make a GET request to the GitHub API to gather all repositories
* under my `nurodev` username & then filter them down to only
* include those that contain the `portfolio` topic
*
* @TODO Switch to v3 API using GraphQL to save over-fetching
*/
export async function fetchProjects(): Promise<Array<Project> | null> {
const projects = [];
for (const source of projectSrcs as Array<ProjectSrc>) {
projects.push(...(await fetchRepos(source)));
}

const { default: rawProjectPosts } = await import('~/data/projects.json');
const projectPosts = rawProjectPosts as Array<ProjectPost>;

const projects: Array<Project> = json
return projects
.map((repo) => {
if (!repo.topics.includes('portfolio')) return null;

if (repo.archived) return null;
if (repo.fork) return null;

// Strip the emoji suffix from the repo description
const trimmedDescription = repo.description.split(' ');
const trimmedDescription = (repo.description || '').split(' ');
trimmedDescription.shift();
const description = trimmedDescription.join(' ');

Expand Down Expand Up @@ -74,6 +88,4 @@ export async function fetchProjects(): Promise<Array<Project> | null> {
} as Project;
})
.filter((project) => project !== null);

return projects;
}
22 changes: 13 additions & 9 deletions src/lib/seo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,41 @@ import { useRouter } from 'next/router';

import type { ComponentProps } from 'react';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';
const { alias, name, role, domain, social } = profile as unknown as Profile;

export function useSeoProps(
props: Partial<ComponentProps<typeof NextSeo>> = {},
): Partial<ComponentProps<typeof NextSeo>> {
const router = useRouter();

const title = 'nurodeveloper';
const description = "Hey 👋 I'm Ben, a developer";
const title = `${alias}${role}`;
const description = `Hey 👋 I'm ${name}, a ${role}`;

return {
title,
description,
canonical: `https://nuro.dev/${router.asPath}`,
canonical: `https://${domain}/${router.asPath}`,
openGraph: {
title,
description,
site_name: 'nuro',
url: `https://nuro.dev/${router.asPath}`,
site_name: alias,
url: `https://${domain}/${router.asPath}`,
type: 'website',
images: [
{
url: 'https://nuro.dev/banner.png',
url: `https://${domain}/banner.png`,
alt: description,
width: 1280,
height: 720,
},
],
},
twitter: {
twitter: social.twitter && {
cardType: 'summary_large_image',
handle: '@nurodev',
site: '@nurodev',
handle: `@${social.twitter}`,
site: `@${social.twitter}`,
},
...props,
};
Expand Down
6 changes: 5 additions & 1 deletion src/pages/blog/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import type { GetStaticPaths, GetStaticProps } from 'next';
import type { ParsedUrlQuery } from 'querystring';
import type { Post } from '~/types';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';
const { alias } = profile as unknown as Profile;

interface PathProps extends ParsedUrlQuery {
slug: string;
}
Expand Down Expand Up @@ -48,7 +52,7 @@ export default function BlogPost({ post }: BlogPostProps): JSX.Element {
<>
<Layout.Blog
seo={{
title: `${post.frontmatter.title} ─ blog ─ nuro`,
title: `${post.frontmatter.title} ─ blog ─ ${alias}`,
description: post.frontmatter.description ?? undefined,
openGraph: {
title: post.frontmatter.title,
Expand Down
6 changes: 5 additions & 1 deletion src/pages/blog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import type { GetStaticProps } from 'next';

import type { FrontMatter } from '~/types';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';
const { alias } = profile as unknown as Profile;

interface BlogProps {
serialisedFrontmatters: string;
}
Expand All @@ -28,7 +32,7 @@ export default function BlogPage({ serialisedFrontmatters }: BlogProps): JSX.Ele
const latestPost = frontmatters.shift();

return (
<Layout.Default seo={{ title: 'nuro ─ blog' }}>
<Layout.Default seo={{ title: `${alias} ─ blog` }}>
<div className="mt-8 sm:mt-16 mb-20 mx-0 sm:mx-6 lg:mb-28 lg:mx-8">
<div className="relative max-w-6xl mx-auto">
<Blog.Latest frontmatter={latestPost} />
Expand Down
19 changes: 12 additions & 7 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import { Layout } from '~/layouts';
import type { EventProps } from '~/components/Event.component';
import type { NavigationItem } from '~/types';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';

const { birthday: bday, role, name, bio, pagesIgnore, social } = profile as unknown as Profile;

const Event = dynamic<EventProps>(
() => import('~/components/Event.component').then(({ Event }) => Event),
{
Expand All @@ -29,23 +34,23 @@ const ACTIONS: Array<NavigationItem> = [
icon: <Icon className="mr-3" icon="feather:copy" />,
text: 'Projects',
},
{
social.github && {
type: NavigationItemType.LINK,
external: true,
href: 'https://github.com/nurodev',
href: `https://github.com/${social.github}`,
icon: <Icon className="mr-3" icon="feather:github" />,
text: 'GitHub',
},
];
].filter(e => e && !pagesIgnore.includes(e.href));

export default function HomePage(): JSX.Element {
const today = new Date();
const birthday = new Date('1997-08-09');
const birthday = new Date(bday);
const age = differenceInYears(today, birthday);
const isBirthday =
today.getDate() === birthday.getDate() && today.getMonth() === birthday.getMonth();

const description = `I am a ${age} year old software engineer & games developer`;
const description = `I am a ${age} year old ${bio}`;

return (
<Layout.Default>
Expand All @@ -60,8 +65,8 @@ export default function HomePage(): JSX.Element {
}}
className="text-gray-500 dark:text-white text-5xl sm:text-6xl md:text-6xl lg:text-8xl tracking-tight font-extrabold">
Hey <span className="inline-block origin-70 hover:(animate-wave)">👋</span>{' '}
I&apos;m Ben, <br className="hidden sm:block" />a{' '}
<Pill.Standard className="mt-4">developer</Pill.Standard>
I&apos;m {name}, <br className="hidden sm:block" />a{' '}
<Pill.Standard className="mt-4">{role}</Pill.Standard>
</Animate>

<Animate
Expand Down
6 changes: 5 additions & 1 deletion src/pages/projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import type { GetStaticProps } from 'next';

import type { ListAction, Project } from '~/types';

import profile from '~/data/profile.json';
import type { Profile } from '~/types/profile';
const { alias } = profile as unknown as Profile;

interface ProjectProps {
stringifiedProjects: string;
}
Expand All @@ -26,7 +30,7 @@ export default function ProjectsPage({ stringifiedProjects }: ProjectProps): JSX
const projects = JSON.parse(stringifiedProjects) as Array<Project>;

return (
<Layout.Default seo={{ title: 'nuro ─ projects' }}>
<Layout.Default seo={{ title: `${alias} ─ projects` }}>
<div className="my-24 mx-2 sm:mx-6 lg:mb-28 lg:mx-8">
<div className="relative max-w-xl mx-auto">
<List.Container>
Expand Down
Loading