Skip to content

Commit 0363f15

Browse files
committed
✨ Initial commit
0 parents  commit 0363f15

37 files changed

+11003
-0
lines changed

.eslintrc.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = {
2+
env: {
3+
browser: true,
4+
es2021: true,
5+
node: true
6+
},
7+
extends: [
8+
'plugin:react/recommended',
9+
'standard'
10+
],
11+
parserOptions: {
12+
ecmaFeatures: {
13+
jsx: true
14+
},
15+
ecmaVersion: 12,
16+
sourceType: 'module'
17+
},
18+
plugins: [
19+
'react'
20+
],
21+
rules: {
22+
},
23+
globals: {
24+
React: true
25+
}
26+
}

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
*.pem
21+
22+
# debug
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
27+
# local env files
28+
.env.local
29+
.env.development.local
30+
.env.test.local
31+
.env.production.local
32+
33+
# vercel
34+
.vercel

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
```
12+
13+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14+
15+
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
16+
17+
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
18+
19+
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
20+
21+
## Learn More
22+
23+
To learn more about Next.js, take a look at the following resources:
24+
25+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27+
28+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29+
30+
## Deploy on Vercel
31+
32+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33+
34+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

blog.config.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const BLOG = {
2+
title: 'CRAIGARY',
3+
description: 'This gonna be an awesome website.',
4+
author: 'Craig Hart',
5+
6+
link: 'https://craigary.net',
7+
lang: 'en-US',
8+
path: '', // leave this empty unless you want to deploy Nobelium in a folder
9+
since: 2015, // if leave this empty, current year will be used.
10+
postsPerPage: 7,
11+
showAbout: true, // WIP
12+
showArchive: true, // WIP
13+
socialLink: 'https://twitter.com/craigaryhart',
14+
notionApiEndPoint: process.env.NOTION_API_ENDPOINT,
15+
notionPageId: process.env.NOTION_PAGE_ID
16+
}
17+
18+
export default BLOG

components/BlogPost.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Link from 'next/link'
2+
import BLOG from '@/blog.config'
3+
import formatDate from '@/lib/formatDate'
4+
5+
const BlogPost = ({ post }) => {
6+
return (
7+
<article key={post.id} className="mb-6 md:mb-8">
8+
<header className="flex flex-col justify-between md:flex-row ">
9+
<Link href={`${BLOG.path}/${post.slug}`}>
10+
<h2 className="font-sans text-lg md:text-xl font-medium mb-2 cursor-pointer">
11+
<a>{post.title}</a>
12+
</h2>
13+
</Link>
14+
<time className="flex-shrink-0 text-gray-600">{formatDate(post.date, BLOG.lang)}</time>
15+
</header>
16+
<main>
17+
<p className="hidden md:block text-gray-700 leading-7">{post.summary}</p>
18+
</main>
19+
</article>
20+
)
21+
}
22+
23+
export default BlogPost

components/Container.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Header from '@/components/Header'
2+
import Footer from '@/components/Footer'
3+
import BLOG from '@/blog.config'
4+
import Head from 'next/head'
5+
import PropTypes from 'prop-types'
6+
7+
const Container = ({ children, layout, ...customMeta }) => {
8+
const meta = {
9+
title: BLOG.title,
10+
type: 'website',
11+
...customMeta
12+
}
13+
return (
14+
<div>
15+
<Head>
16+
{/* Add more Meta Info */}
17+
<title>{meta.title}</title>
18+
<meta name="robots" content="follow, index" />
19+
<meta content={meta.summary} name="description" />
20+
</Head>
21+
<div className="wrapper">
22+
<Header navBarTitle={layout === 'blog' ? meta.title : null} />
23+
<main className="m-auto max-w-3xl px-4 font-sans flex-grow w-full">
24+
{children}
25+
</main>
26+
<Footer />
27+
</div>
28+
</div>
29+
)
30+
}
31+
32+
Container.propTypes = {
33+
children: PropTypes.node
34+
}
35+
36+
export default Container

components/Footer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import BLOG from '@/blog.config'
2+
const Footer = () => {
3+
const d = new Date()
4+
const y = d.getFullYear()
5+
return (
6+
<div className="mt-6 flex-shrink-0 m-auto max-w-3xl px-4 font-sans w-full text-gray-600">
7+
<hr />
8+
<div className="my-4 text-sm">
9+
<p>Built with ♥ and ⚛ Next.js. Proudly deployed on ▲Vercel.</p>
10+
<p>©{BLOG.since ? `${BLOG.since} - ${y}` : y} {BLOG.author}</p>
11+
</div>
12+
</div>
13+
)
14+
}
15+
16+
export default Footer

components/Header.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useEffect, useRef } from 'react'
2+
import Link from 'next/link'
3+
import Image from 'next/image'
4+
import BLOG from '@/blog.config'
5+
6+
const NavBar = () => {
7+
const links = [
8+
{ id: 1, name: 'Blog', to: BLOG.path || '/' },
9+
{ id: 2, name: 'RSS', to: '/feed' },
10+
{ id: 3, name: 'Search', to: '/search' }
11+
]
12+
return (
13+
<div>
14+
<ul className="flex flex-row font-sans">
15+
{links.map(link => (
16+
<li key={link.id} className="block ml-4">
17+
<Link href={link.to}>
18+
<a>{link.name}</a>
19+
</Link>
20+
</li>
21+
))}
22+
</ul>
23+
</div>
24+
)
25+
}
26+
27+
const Header = ({ navBarTitle }) => {
28+
const navRef = useRef(null)
29+
const sentinalRef = useRef(null)
30+
const handler = ([entry]) => {
31+
if (navRef && navRef.current) {
32+
if (!entry.isIntersecting && entry !== undefined) {
33+
navRef.current.classList.add('sticky-nav-full')
34+
} else {
35+
navRef.current.classList.remove('sticky-nav-full')
36+
}
37+
}
38+
}
39+
useEffect(() => {
40+
const obvserver = new window.IntersectionObserver(handler)
41+
obvserver.observe(sentinalRef.current)
42+
// Don't touch this, I have no idea how it works XD
43+
// return () => {
44+
// if (sentinalRef.current) obvserver.unobserve(sentinalRef.current)
45+
// }
46+
}, [sentinalRef])
47+
return (
48+
<>
49+
<div className="observer-element h-4 md:h-12" ref={sentinalRef}></div>
50+
<div
51+
className="sticky-nav m-auto max-w-3xl w-full h-6 flex flex-row justify-between items-center mb-1 md:mb-8 px-4 py-8 bg-opacity-60"
52+
id="sticky-nav"
53+
ref={navRef}
54+
>
55+
<div className="flex">
56+
<Link href="/">
57+
<div className="h-6">
58+
<Image src="/logo.svg" width={24} height={24} alt="Craigary" />
59+
</div>
60+
</Link>
61+
{navBarTitle
62+
? (
63+
<p className="ml-2 italic header-name font-medium">{navBarTitle}</p>
64+
)
65+
: (
66+
<p className="ml-2 italic header-name font-medium">
67+
{BLOG.title},{' '}
68+
<span className="font-normal">{BLOG.description}</span>
69+
</p>
70+
)}
71+
</div>
72+
<NavBar />
73+
</div>
74+
</>
75+
)
76+
}
77+
78+
export default Header

components/Pagination.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Link from 'next/link'
2+
import BLOG from '@/blog.config'
3+
4+
const Pagination = ({ totalPages, page }) => {
5+
const currentPage = +page
6+
return (
7+
<div className="flex justify-between">
8+
<Link href={ currentPage - 1 === 1 ? `${BLOG.path || '/'}` : `/page/${currentPage - 1}`}>
9+
<p className={currentPage === 1 ? 'invisible' : 'block'}>
10+
<a rel="prev">← Prev</a>
11+
</p>
12+
</Link>
13+
<Link href={`/page/${currentPage + 1}`}>
14+
<p className={currentPage === totalPages ? 'invisible' : 'block'}>
15+
<a rel="next">Next →</a>
16+
</p>
17+
</Link>
18+
</div>
19+
)
20+
}
21+
22+
export default Pagination

components/Tags.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { useState } from 'react'
2+
3+
const Tags = ({ tags, handleTagClick, selectedTag }) => {
4+
// const colorPalette = ['yellow-400', 'blue-400', 'purple-400', 'pink s-400']
5+
// const color = colorPalette[Math.floor(Math.random() * colorPalette.length)]
6+
// const ClassToReturn = `border-${color} text-${color} bg-${color}`
7+
if (!tags) return null
8+
return (
9+
<ul className="flex max-w-full overflow-x-auto">
10+
{Object.keys(tags).map(key => (
11+
<li
12+
key={key}
13+
onClick={() => handleTagClick(key)}
14+
className={`mr-2 px-2 py-1 my-3 cursor-pointer rounded-full border-2 bg-opacity-0 border-blue-400 text-blue-400 bg-blue-400 whitespace-nowrap ${key === selectedTag ? 'bg-opacity-30' : ''}`}
15+
>
16+
{`${key} (${tags[key]})`}
17+
</li>
18+
))}
19+
</ul>
20+
)
21+
}
22+
23+
export default Tags

jsconfig.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"paths": {
5+
"@/*": ["./*"],
6+
"@/components/*": ["components/*"],
7+
"@/data/*": ["data/*"],
8+
"@/layouts/*": ["layouts/*"],
9+
"@/lib/*": ["lib/*"],
10+
"@/styles/*": ["styles/*"]
11+
}
12+
}
13+
}

layouts/blog.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Image from 'next/image'
2+
import Container from '@/components/Container'
3+
import { useRouter } from 'next/router'
4+
import { NotionRenderer } from 'react-notion'
5+
import BLOG from '@/blog.config'
6+
import formatDate from '@/lib/formatDate'
7+
8+
const BlogLayout = ({ children, blocks, frontMatter }) => {
9+
const router = useRouter()
10+
return (
11+
<Container
12+
layout="blog"
13+
title={frontMatter.title}
14+
description={frontMatter.summary}
15+
// date={new Date(frontMatter.publishedAt).toISOString()}
16+
type="article"
17+
>
18+
<article>
19+
<h1 className="font-sans font-bold text-3xl">{frontMatter.title}</h1>
20+
<nav className="flex mt-4 mb-2 items-center text-gray-600">
21+
<div className="flex">
22+
<a href={BLOG.socialLink} className="flex">
23+
<Image
24+
alt={BLOG.author}
25+
width={24}
26+
height={24}
27+
src="/avatar.svg"
28+
className="rounded-full"
29+
/>
30+
<p className="hidden md:ml-2 md:block">{BLOG.author}</p>
31+
</a>
32+
<span className="hidden md:inline">&nbsp;/&nbsp;</span>
33+
</div>
34+
<div className="ml-2 md:ml-0">
35+
{formatDate(frontMatter.date, BLOG.lang)}
36+
</div>
37+
{frontMatter.tags.length && (
38+
<div className="tag flex ml-2">
39+
{frontMatter.tags.map(tag => <p key={tag} className="mr-1 cursor-pointer" onClick={() => router.push(`/tag/${encodeURIComponent(tag)}`)}>#{tag}</p>)}
40+
</div>
41+
)}
42+
</nav>
43+
{children}
44+
<NotionRenderer blockMap={blocks}/>
45+
<p onClick={() => router.back()} className="mt-2">
46+
← Back
47+
</p>
48+
</article>
49+
</Container>
50+
)
51+
}
52+
53+
export default BlogLayout

0 commit comments

Comments
 (0)