Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SEKAI{V2_Migration} #50

Merged
merged 9 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
# visit https://giscus.app to get your Giscus ids
NEXT_PUBLIC_GISCUS_REPO=
NEXT_PUBLIC_GISCUS_REPOSITORY_ID=
NEXT_PUBLIC_GISCUS_CATEGORY=
NEXT_PUBLIC_GISCUS_CATEGORY_ID=
NEXT_PUBLIC_UTTERANCES_REPO=
NEXT_PUBLIC_DISQUS_SHORTNAME=


MAILCHIMP_API_KEY=
MAILCHIMP_API_SERVER=
MAILCHIMP_AUDIENCE_ID=

BUTTONDOWN_API_URL=https://api.buttondown.email/v1/
BUTTONDOWN_API_KEY=

CONVERTKIT_API_URL=https://api.convertkit.com/v3/
CONVERTKIT_API_KEY=
// curl https://api.convertkit.com/v3/forms?api_key=<your_public_api_key> to get your form ID
# curl https://api.convertkit.com/v3/forms?api_key=<your_public_api_key> to get your form ID
CONVERTKIT_FORM_ID=

KLAVIYO_API_KEY=
KLAVIYO_LIST_ID=
KLAVIYO_LIST_ID=

REVUE_API_KEY=

EMAILOCTOPUS_API_KEY=
EMAILOCTOPUS_LIST_ID=
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
.eslintrc.js
9 changes: 6 additions & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ module.exports = {
'next',
'next/core-web-vitals',
],
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
},
rules: {
'prettier/prettier': 'error',
'prettier/prettier': 'warn',
'react/react-in-jsx-scope': 'off',
'@next/next/no-img-element': 'off',
'jsx-a11y/anchor-is-valid': [
'error',
{
Expand All @@ -30,7 +33,7 @@ module.exports = {
},
],
'react/prop-types': 0,
'no-unused-vars': 0,
'@typescript-eslint/no-unused-vars': 0,
'react/no-unescaped-entities': 0,
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-var-requires': 'off',
Expand Down
4 changes: 2 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## Source: https://github.com/alexkaratarakis/gitattributes
## Modified * text=auto to * text eol=lf to force LF endings.
## Modified * text=auto to * text=auto eol=lf eol=lf to force LF endings.

## GITATTRIBUTES FOR WEB PROJECTS
#
Expand All @@ -16,7 +16,7 @@
## Force LF line endings automatically for files detected as
## text and leave all files detected as binary untouched.
## This will handle all files NOT defined below.
* text eol=lf
* text=auto eol=lf

# Source code
*.bash text eol=lf
Expand Down
12 changes: 11 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
/node_modules
/.pnp
.pnp.js
/.yarn/*
!/.yarn/releases
!/.yarn/plugins
!/.yarn/sdks

# testing
/coverage
Expand All @@ -13,14 +17,17 @@
/out/
public/sitemap.xml
.vercel
.next

# production
/build
*.xml

# rss feed
/public/feed.xml

# search
/public/search.json

# misc
.DS_Store

Expand All @@ -35,3 +42,6 @@ yarn-error.log*
.env.development.local
.env.test.local
.env.production.local

# Contentlayer
.contentlayer
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.mdx
1 change: 0 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
MIT License

Copyright (c) 2021 Timothy Lin
Copyright (c) 2021 Eana Hufwe

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
391 changes: 387 additions & 4 deletions README.md

Large diffs are not rendered by default.

143 changes: 143 additions & 0 deletions app/blog/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import 'css/prism.css'
import 'katex/dist/katex.css'

import PageTitle from '@/components/PageTitle'
import { components } from '@/components/MDXComponents'
import { MDXLayoutRenderer } from 'pliny/mdx-components'
import {
sortPosts,
coreContent,
allCoreContent,
} from 'pliny/utils/contentlayer'
import { allBlogs, allAuthors } from 'contentlayer/generated'
import type { Authors, Blog } from 'contentlayer/generated'
import PostSimple from '@/layouts/PostSimple'
import PostLayout from '@/layouts/PostLayout'
import PostBanner from '@/layouts/PostBanner'
import { Metadata } from 'next'
import siteMetadata from '@/data/siteMetadata'

const defaultLayout = 'PostLayout'
const layouts = {
PostSimple,
PostLayout,
PostBanner,
}

export async function generateMetadata({
params,
}: {
params: { slug: string[] }
}): Promise<Metadata | undefined> {
const slug = decodeURI(params.slug.join('/'))
const post = allBlogs.find((p) => p.slug === slug)
const authorList = post?.authors || ['default']
const authorDetails = authorList.map((author) => {
const authorResults = allAuthors.find((p) => p.slug === author)
return coreContent(authorResults as Authors)
})
if (!post) {
return
}

const publishedAt = new Date(post.date).toISOString()
const modifiedAt = new Date(post.lastmod || post.date).toISOString()
const authors = authorDetails.map((author) => author.name)
let imageList = [siteMetadata.socialBanner]
if (post.images) {
imageList = typeof post.images === 'string' ? [post.images] : post.images
}
const ogImages = imageList.map((img) => {
return {
url: img.includes('http') ? img : siteMetadata.siteUrl + img,
}
})

return {
title: post.title,
description: post.summary,
openGraph: {
title: post.title,
description: post.summary,
siteName: siteMetadata.title,
locale: 'en_US',
type: 'article',
publishedTime: publishedAt,
modifiedTime: modifiedAt,
url: './',
images: ogImages,
authors: authors.length > 0 ? authors : [siteMetadata.author],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.summary,
images: imageList,
},
}
}

export const generateStaticParams = async () => {
const paths = allBlogs.map((p) => ({ slug: p.slug.split('/') }))

return paths
}

export default async function Page({ params }: { params: { slug: string[] } }) {
const slug = decodeURI(params.slug.join('/'))
// Filter out drafts in production
const sortedCoreContents = allCoreContent(sortPosts(allBlogs))
const postIndex = sortedCoreContents.findIndex((p) => p.slug === slug)
if (postIndex === -1) {
return (
<div className="mt-24 text-center">
<PageTitle>
Under Construction{' '}
<span role="img" aria-label="roadwork sign">
🚧
</span>
</PageTitle>
</div>
)
}

const prev = sortedCoreContents[postIndex + 1]
const next = sortedCoreContents[postIndex - 1]
const post = allBlogs.find((p) => p.slug === slug) as Blog
const authorList = post?.authors || ['default']
const authorDetails = authorList.map((author) => {
const authorResults = allAuthors.find((p) => p.slug === author)
return coreContent(authorResults as Authors)
})
const mainContent = coreContent(post)
const jsonLd = post.structuredData
jsonLd['author'] = authorDetails.map((author) => {
return {
'@type': 'Person',
name: author.name,
}
})

const Layout = layouts[post.layout || defaultLayout]

return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<Layout
content={mainContent}
authorDetails={authorDetails}
next={next}
prev={prev}
>
<MDXLayoutRenderer
code={post.body.code}
components={components}
toc={post.toc}
/>
</Layout>
</>
)
}
30 changes: 30 additions & 0 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import ListLayout from '@/layouts/ListLayout'
import { allCoreContent, sortPosts } from 'pliny/utils/contentlayer'
import { allBlogs } from 'contentlayer/generated'
import { genPageMetadata } from 'app/seo'

const POSTS_PER_PAGE = 5

export const metadata = genPageMetadata({ title: 'Blog' })

export default function BlogPage() {
const posts = allCoreContent(sortPosts(allBlogs))
const pageNumber = 1
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber
)
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
}

return (
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
)
}
36 changes: 36 additions & 0 deletions app/blog/page/[page]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import ListLayout from '@/layouts/ListLayout'
import { allCoreContent, sortPosts } from 'pliny/utils/contentlayer'
import { allBlogs } from 'contentlayer/generated'

const POSTS_PER_PAGE = 5

export const generateStaticParams = async () => {
const totalPages = Math.ceil(allBlogs.length / POSTS_PER_PAGE)
const paths = Array.from({ length: totalPages }, (_, i) => ({
page: (i + 1).toString(),
}))

return paths
}

export default function Page({ params }: { params: { page: string } }) {
const posts = allCoreContent(sortPosts(allBlogs))
const pageNumber = parseInt(params.page as string)
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber
)
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
}

return (
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
)
}
49 changes: 49 additions & 0 deletions app/contests/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import ContestCard from '@/components/ContestCard'
import { DataTable } from '@/components/ui/data-table'
import { columns } from '@/layouts/ContestsColumns'
import contestsData from '@/data/contestsData'
import { genPageMetadata } from 'app/seo'
import { groupBy } from 'lodash'
import { Fragment } from 'react'

export const metadata = genPageMetadata({ title: 'Contests' })

export default function Contests() {
return (
<>
<div className="divide-y divide-border">
<div className="space-y-2 pb-8 pt-6 md:space-y-5">
<h1 className="text-3xl font-semibold leading-9 tracking-tight text-foreground sm:text-4xl sm:leading-10 md:text-6xl md:leading-14">
Contests
</h1>
<p className="text-lg leading-7 text-muted-foreground">
CTFs we have participated in.
</p>
</div>
<div className="container hidden py-12 md:block">
<DataTable
data={contestsData.filter((d) => d.place <= 25)}
columns={columns}
/>
</div>
<div className="container block py-12 md:hidden">
{Object.entries(groupBy(contestsData, 'year'))
.sort((a, b) => b[0].localeCompare(a[0]))
.map(([year, contests]) => (
<Fragment key={year}>
<h2 className="mb-6 mt-12 text-2xl font-bold first:mt-0 sm:text-3xl md:text-4xl">
{year}
</h2>
<div className="-m-4 flex flex-wrap place-items-stretch">
{/* @ts-ignore */}
jktrn marked this conversation as resolved.
Show resolved Hide resolved
{contests.map((d) => (
<ContestCard {...d} key={d.name} />
))}
</div>
</Fragment>
))}
</div>
</div>
</>
)
}