Skip to content

Commit

Permalink
Next.js 14 (#121)
Browse files Browse the repository at this point in the history
* upgrade dependencies

* wip add contentlayer

* wip update links and head tags

* get next-themes working kinda

* create-react-app for next 14

* idk, remove purgecss?

* fix some invalid HTML

* get projects kinda working

* wip add blog to app

* kinda get projects working

* get blog working

* get projects working

* migrate contact page

* migrate 404

* use built-in to transpile modules

see https://nextjs.org/docs/app/api-reference/next-config-js/transpilePackages

* add tailwind back

* misc cleanup

* fix tailwind content dirs

* add blog post layout

* rm more layouts

* fix projects index

* sort projects by date desc

* tweak project card borders

* pull out project item into its own file since I'll maybe use client at some point

* add music page

* kill last layout

* oops add missing import

* add more metadata

* fix date vs. publishedAt

* fix eslint errors

* fixed some MDX components

* use contentlayer for music

* wip add test page

* use remark-gfm@3 since v4 is still getting rolled out

see remarkjs/remark-gfm#57

* update iframe

* rm gray-matter

* upgrade eslint

* rm @types/react-syntax-highlighter because it was causing issues

see react-syntax-highlighter/react-syntax-highlighter#539

* fix Google Analytics

* fix some loudness wars typescript issues

* first successful `yarn build` 🎉

* fix some stuff around slugs

* i uhhhh alright I guess I'm escaping urls in my paths now

* rm dummy next-14 dir

* get cypress in a runnable state

* kill react-spring / reach

* daaaaang framer motion is cool

* add social links to mobile nav

* use new next ESLint plugin

* clean up dependencies

* run eslint

* fix some blog metadata

* fix more metadata

* use FancyH1 for 404

* fix blog post title heading

* add leading-8 to project and blog post pages

* defer to tailwind typography over custom styles

* fix tailwind content path

* fix some more classnames and typography

* fix project card image heights

* minor tweaks to conform w/ Tailwind typography

* change url

* use [role="dialog"] instead of custom CSS selector

* rm deprecated property

* tell cypress it's ok to continue to NEXT_NOT_FOUND errors

* fix music headings tests

* rm double underline from links

* make github percy quiet

* add sharp

* use custom h1 for project page

* lint

* rm dead code

* fix og:image assertion

* add favicon and apple-icon

* rm unused permalink

* fix project image link in head

* add twitter to metadata

* fix issue where I was only taking a screenshot of every other project

* make dividing line in mobile nav dark theme aware

* wait before taking screenshot of mobile nav

* update browserslist

* mv blog heading into page, not layout
  • Loading branch information
ryanrishi committed Nov 21, 2023
1 parent edf4d5e commit f2284bc
Show file tree
Hide file tree
Showing 82 changed files with 5,108 additions and 3,503 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"next"
"next/core-web-vitals"
],
"plugins": [
"@typescript-eslint",
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
with:
build: yarn build
start: yarn start
quiet: true
command-prefix: percy exec --
env:
PERCY_TOKEN: "${{ secrets.PERCY_TOKEN }}"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ yarn-error.log*
.env.production.local

# Cypress
cypress/downloads
cypress/screenshots
cypress/videos

.contentlayer
41 changes: 41 additions & 0 deletions app/%5Ftest/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { allTests } from 'contentlayer/generated'
import { notFound } from 'next/navigation'
import type { Metadata } from 'next/types'
import { useMDXComponent } from 'next-contentlayer/hooks'

import { FancyH1 } from '@/components/headings'
import mdxComponents from '@/components/mdx-components'

export const generateMetadata = (): Metadata => {
const testPage = allTests[0]

return {
title: testPage.title,
description: testPage.description,
openGraph: {
type: 'article',
title: testPage.title,
description: testPage.description,
images: {
url: testPage.image,
},
tags: testPage.tags,
},
}
}

export default function Test() {
const testPage = allTests[0]
if (!testPage) notFound()

const MDXContent = useMDXComponent(testPage.body.code)

return (
<>
<FancyH1>{testPage.title}</FancyH1>
<div className="prose prose-slate dark:prose-invert">
<MDXContent components={mdxComponents} />
</div>
</>
)
}
File renamed without changes
14 changes: 14 additions & 0 deletions app/blog/[slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Link from 'next/link'

export default function PostLayout({ children }) {
return (
<div className="prose dark:prose-invert max-w-none">
{children}
<div className="flex items-center justify-center my-8">
<Link href="/blog" className="not-prose text-slate-500 hover:text-slate-600 transition">
&larr; Back to Blog
</Link>
</div>
</div>
)
}
54 changes: 54 additions & 0 deletions app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { allPosts } from 'contentlayer/generated'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { useMDXComponent } from 'next-contentlayer/hooks'

import { H1 } from '@/components/headings'
import mdxComponents from '@/components/mdx-components'

dayjs.extend(utc)

export const generateStaticParams = async () => allPosts.map((post) => ({ slug: post.slug }))

export const generateMetadata = ({ params }: { params: { slug: string } }): Metadata => {
const post = allPosts.find((post) => post.slug === decodeURIComponent(params.slug))
if (!post) throw new Error(`Post not found for slug: ${decodeURIComponent(params.slug)}`)

return {
title: post.title,
description: post.description,
openGraph: {
title: post.title,
type: 'article',
publishedTime: post.publishedAt,
authors: 'Ryan Rishi',
url: `https://ryanrishi.com/blog/${decodeURIComponent(params.slug)}`,
images: [
{ url: `https://ryanrishi.com/${post.image}` },
],
tags: post.tags,
},
twitter: {
title: post.title,
images: `https://ryanrishi.com/${post.image}`,
},
}
}

export default function Post({ params }: { params: { slug: string } }) {
const post = allPosts.find((post) => post.slug === params.slug)
if (!post) notFound()

const MDXContent = useMDXComponent(post.body.code)

return (
<>
<H1>{post.title}</H1>
<p className="mb-8 text-slate-500 dark:text-slate-400 transition">{dayjs.utc(post.publishedAt).format('MMMM D, YYYY')}</p>

<MDXContent components={mdxComponents} />
</>
)
}
51 changes: 51 additions & 0 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { allPosts } from 'contentlayer/generated'
import { compareDesc } from 'date-fns'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { Metadata } from 'next'
import Link from 'next/link'

import { FancyH1,H1 } from '@/components/headings'

dayjs.extend(utc)

export const metadata: Metadata = {
title: 'Blog',
openGraph: {
title: 'Blog',
},
twitter: {
title: 'Blog',
},
}

export default function BlogIndex() {
const posts = allPosts.sort((a, b) => compareDesc(new Date(a.publishedAt), new Date(b.publishedAt)))

return (
<>
<FancyH1>Blog</FancyH1>
{posts.map((post, i) => (
<div
className="mb-16 lg:mb-16 xl:mb-32"
data-test-blog-post
key={i}
>
<H1 className="hover:text-slate-900 dark:hover:text-slate-300">
<Link href={`blog/${post.slug}`} legacyBehavior>
{post.title}
</Link>
</H1>
<p className="pb-4 text-slate-700 dark:text-slate-400 transition" data-test-blog-post-date>{dayjs.utc(post.publishedAt).format('MMMM D, YYYY')}</p>

<div className="flex flex-col">
<p className="transition">{post.description}</p>
<Link className="flex justify-end pt-4 italic uppercase font-bold dark:text-slate-100 transition" href={`blog/${post.slug}`}>
Read more &raquo;
</Link>
</div>
</div>
))}
</>
)
}
93 changes: 93 additions & 0 deletions app/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import classNames from 'classnames'
import { Metadata } from 'next/types'

import { FancyH1 } from '@/components/headings'

export const metadata: Metadata = {
title: 'Contact',
openGraph: {
title: 'Contact',
},
twitter: {
title: 'Contact',
},
}

const sharedInputClassNames = 'block w-full border rounded py-3 px-4 mb-3 mt-2 leading-tight appearance-none text-slate-800 bg-slate-100 dark:text-slate-100 dark:bg-slate-700 border-slate-300 hover:border-slate-400 transition'

function Label({ htmlFor, children }) {
return (
<label
className="block uppercase tracking-wide text-slate-600 dark:text-slate-300 text-xs font-bold mb-2"
htmlFor={htmlFor}
>
{children}
</label>
)
}

export default function Contact() {
return (
<div className="container">
<FancyH1>Contact</FancyH1>
<form
className="mx-auto"
action="https://formspree.io/f/mleppawq"
method="POST"
>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<Label htmlFor="grid-full-name">
Your Name
<input
type="text"
id="grid-full-name"
name="name"
className={sharedInputClassNames}
required
/>
</Label>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<Label htmlFor="grid-password">
E-mail
<input
id="email"
type="email"
name="email"
className={sharedInputClassNames}
required
/>
</Label>
</div>
</div>
<div className="flex flex-wrap -mx-3 mb-6">
<div className="w-full px-3">
<Label htmlFor="grid-password">
Message
<textarea
id="message"
name="message"
className={classNames(sharedInputClassNames, "h-48 resize-none")}
required
/>
</Label>
</div>
</div>
<div className="md:flex md:items-center">
<div className="md:w-1/3">
<button
type="submit"
className="shadow bg-teal-700 hover:bg-teal-800 dark:bg-teal-600 dark:hover:bg-teal-700 transition focus:shadow-outline focus:outline-teal-300 dark:focus:outline-teal-800 text-teal-50 dark:text-teal-50 font-semibold py-2 px-4 uppercase italic rounded"
>
Send
</button>
</div>
<div className="md:w-2/3" />
</div>
</form>
</div>
)
}
File renamed without changes.
39 changes: 39 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* keep these bg-* and dark:bg-* in sync with app/layout.tsx */

body {
@apply bg-slate-50;
}

html.dark body {
@apply bg-slate-800;
}

.prose h1::not(.not-prose),
.prose h2::not(.not-prose),
.prose h3::not(.not-prose),
.prose h4::not(.not-prose),
.prose h5::not(.not-prose),
.prose h6::not(.not-prose) {
@apply font-semibold text-slate-800 dark:text-slate-100 mb-2 lg:mb-6 mt-2 lg:mt-8 transition-colors;
}

.prose a {
@apply no-underline;
}

.prose h1 a,
.prose h2 a,
.prose h3 a,
.prose h4 a,
.prose h5 a,
.prose h6 a {
@apply hover:before:content-['#'] hover:before:absolute hover:before:-ml-[1.2ch] hover:before:inline hover:underline;
}

.prose :not(:is(h1, h2, h3, h4, h5, h6)) a:not(.not-prose) {
@apply text-green-800 hover:text-green-900 border-b border-b-green-400 bg-green-200/50 hover:bg-green-200/80 dark:bg-green-800/50 dark:text-green-200 dark:hover:text-green-300 rounded-sm transition-colors;
}

html {
scroll-behavior: smooth;
}

1 comment on commit f2284bc

@vercel
Copy link

@vercel vercel bot commented on f2284bc Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.