Skip to content

Commit

Permalink
Revert "Update to latest dependencies. (leerob#624)" (leerob#625)
Browse files Browse the repository at this point in the history
This reverts commit 713a90c.
  • Loading branch information
leerob authored Jun 12, 2023
1 parent 713a90c commit e3ee434
Show file tree
Hide file tree
Showing 27 changed files with 1,401 additions and 1,349 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
- **Styling**: [Tailwind CSS](https://tailwindcss.com)
- **Analytics**: [Vercel Analytics](https://vercel.com/analytics)

## TODO

In early 2023, I refactored my site to use the new `app/` directory in Next.js 13. I went ahead and shipped it, but there are still a few things I want to do:

- [ ] Global `404` page coming soon
- [ ] Move redirects to end of routing stack (not in `next.config.js`)
- [ ] Use new support for API routes in `app` (not ready yet)
- [ ] Improved scroll position support in `app/` (not implemented yet)

You can learn more about the `app/` directory [here](https://nextjs.org/docs/app).

## Running Locally

This application requires Node.js v16.13+.
Expand Down
2 changes: 1 addition & 1 deletion app/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
YoutubeIcon,
ArrowIcon,
TwitterIcon,
} from 'app/components/icons';
} from 'components/icons';

export const metadata: Metadata = {
title: 'About',
Expand Down
47 changes: 0 additions & 47 deletions app/actions.ts

This file was deleted.

20 changes: 11 additions & 9 deletions app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { Mdx } from 'app/components/mdx';
import { Mdx } from 'components/mdx';
import { allBlogs } from 'contentlayer/generated';
import { getTweets } from 'lib/twitter';
import Balancer from 'react-wrap-balancer';
import ViewCounter from '../view-counter';
import { getViewsCount } from 'lib/metrics';

export async function generateStaticParams() {
return allBlogs.map((post) => ({
slug: post.slug,
}));
}

export async function generateMetadata({
params,
Expand All @@ -24,7 +29,7 @@ export async function generateMetadata({
} = post;
const ogImage = image
? `https://leerob.io${image}`
: `https://leerob.io/og?title=${title}`;
: `https://leerob.io/api/og?title=${title}`;

return {
title,
Expand Down Expand Up @@ -57,14 +62,11 @@ export default async function Blog({ params }) {
notFound();
}

const [allViews, tweets] = await Promise.all([
getViewsCount(),
getTweets(post.tweetIds),
]);
const tweets = await getTweets(post.tweetIds);

return (
<section>
<script type="application/ld+json" suppressHydrationWarning>
<script type="application/ld+json">
{JSON.stringify(post.structuredData)}
</script>
<h1 className="font-bold text-3xl font-serif max-w-[650px]">
Expand All @@ -75,7 +77,7 @@ export default async function Blog({ params }) {
{post.publishedAt}
</div>
<div className="h-[0.2em] bg-neutral-50 dark:bg-neutral-800 mx-2" />
<ViewCounter allViews={allViews} slug={post.slug} trackView />
<ViewCounter slug={post.slug} trackView />
</div>
<Mdx code={post.body.code} tweets={tweets} />
</section>
Expand Down
9 changes: 1 addition & 8 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ import type { Metadata } from 'next';
import Link from 'next/link';
import { allBlogs } from 'contentlayer/generated';
import ViewCounter from './view-counter';
import { getViewsCount } from 'lib/metrics';

export const metadata: Metadata = {
title: 'Blog',
description: 'Read my thoughts on software development, design, and more.',
};

export default async function BlogPage() {
const allViews = await getViewsCount();

return (
<section>
<h1 className="font-bold text-3xl font-serif mb-5">Blog</h1>
Expand All @@ -30,11 +27,7 @@ export default async function BlogPage() {
>
<div className="w-full flex flex-col">
<p>{post.title}</p>
<ViewCounter
allViews={allViews}
slug={post.slug}
trackView={false}
/>
<ViewCounter slug={post.slug} trackView={false} />
</div>
</Link>
))}
Expand Down
38 changes: 26 additions & 12 deletions app/blog/view-counter.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
'use client';

import { useEffect } from 'react';
import { increment } from 'app/actions';
import useSWR from 'swr';

type PostView = {
slug: string;
count: string;
};

async function fetcher<JSON = any>(
input: RequestInfo,
init?: RequestInit
): Promise<JSON> {
const res = await fetch(input, init);
return res.json();
}

export default function ViewCounter({
slug,
allViews,
trackView,
}: {
slug: string;
allViews: {
slug: string;
count: number;
}[];
trackView?: boolean;
trackView: boolean;
}) {
const viewsForSlug = allViews && allViews.find((view) => view.slug === slug);
const number = new Number(viewsForSlug?.count || 0);
const { data } = useSWR<PostView[]>('/api/views', fetcher);
const viewsForSlug = data && data.find((view) => view.slug === slug);
const views = new Number(viewsForSlug?.count || 0);

useEffect(() => {
const registerView = () =>
fetch(`/api/views/${slug}`, {
method: 'POST',
});

if (trackView) {
increment(slug);
registerView();
}
}, []);
}, [slug]);

return (
<p className="font-mono text-sm text-neutral-500 tracking-tighter">
{`${number.toLocaleString()} views`}
{data ? `${views.toLocaleString()} views` : '​'}
</p>
);
}
2 changes: 1 addition & 1 deletion app/guestbook/buttons.tsx → app/guestbook/actions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { GitHubIcon } from 'app/components/icons';
import { GitHubIcon } from 'components/icons';
import { signIn, signOut } from 'next-auth/react';

export function SignOut() {
Expand Down
51 changes: 38 additions & 13 deletions app/guestbook/form.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
'use client';

import { useRef } from 'react';
import { saveGuestbookEntry } from '../actions';
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
import { useRouter } from 'next/navigation';
import { useState, useTransition } from 'react';

export default function Form() {
const formRef = useRef<HTMLFormElement>(null);
const { pending } = useFormStatus();
const router = useRouter();
const [isPending, startTransition] = useTransition();
const [isFetching, setIsFetching] = useState(false);
const isMutating = isFetching || isPending;

async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setIsFetching(true);

const form = e.currentTarget;
const input = form.elements.namedItem('entry') as HTMLInputElement;

const res = await fetch('/api/guestbook', {
body: JSON.stringify({
body: input.value,
}),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
});

input.value = '';
const { error } = await res.json();

setIsFetching(false);
startTransition(() => {
// Refresh the current route and fetch new data from the server without
// losing client-side browser or React state.
router.refresh();
});
}

return (
<form
style={{ opacity: !pending ? 1 : 0.7 }}
style={{ opacity: !isMutating ? 1 : 0.7 }}
className="relative max-w-[500px] text-sm"
ref={formRef}
action={async (formData) => {
await saveGuestbookEntry(formData);
formRef.current?.reset();
}}
onSubmit={onSubmit}
>
<input
aria-label="Your message"
placeholder="Your message..."
disabled={pending}
disabled={isPending}
name="entry"
type="text"
required
className="pl-4 pr-32 py-2 mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full border-neutral-300 rounded-md bg-gray-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100"
/>
<button
className="flex items-center justify-center absolute right-1 top-1 px-2 py-1 font-medium h-7 bg-neutral-200 dark:bg-neutral-700 text-neutral-900 dark:text-neutral-100 rounded w-16"
disabled={pending}
disabled={isMutating}
type="submit"
>
Sign
Expand Down
4 changes: 2 additions & 2 deletions app/guestbook/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Metadata } from 'next';
import { queryBuilder } from 'lib/planetscale';
import { SignIn, SignOut } from './actions';
import { getServerSession } from 'next-auth/next';
import { authOptions } from 'pages/api/auth/[...nextauth]';
import { queryBuilder } from 'lib/planetscale';
import { SignIn, SignOut } from './buttons';
import Form from './form';

async function getGuestbook() {
Expand Down
12 changes: 11 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import './global.css';
import clsx from 'clsx';
import type { Metadata } from 'next';
import localFont from 'next/font/local';
import Sidebar from './components/sidebar';
import Sidebar from '../components/sidebar';
import { Analytics } from '@vercel/analytics/react';

const kaisei = localFont({
Expand All @@ -23,6 +23,13 @@ export const metadata: Metadata = {
description: 'Developer, writer, and creator.',
url: 'https://leerob.io',
siteName: 'Lee Robinson',
images: [
{
url: 'https://leerob.io/og.jpg',
width: 1920,
height: 1080,
},
],
locale: 'en-US',
type: 'website',
},
Expand All @@ -41,6 +48,9 @@ export const metadata: Metadata = {
title: 'Lee Robinson',
card: 'summary_large_image',
},
icons: {
shortcut: '/favicon.ico',
},
verification: {
google: 'eZSdmzAXlLkKhNJzfgwDqWORghxnJ8qR9_CHdAh5-xw',
yandex: '14d2e73487fa6c71',
Expand Down
3 changes: 1 addition & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import {
GitHubIcon,
TwitterIcon,
ViewsIcon,
} from 'app/components/icons';
} from 'components/icons';
import { name, about, bio, avatar } from 'lib/info';

export const revalidate = 60;
export const dynamic = 'force-dynamic';

export default async function HomePage() {
let starCount, views, tweetCount;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion contentlayer.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const computedFields = {
description: doc.summary,
image: doc.image
? `https://leerob.io${doc.image}`
: `https://leerob.io/og?title=${doc.title}`,
: `https://leerob.io/api/og?title=${doc.title}`,
url: `https://leerob.io/blog/${doc._raw.flattenedPath}`,
author: {
'@type': 'Person',
Expand Down
7 changes: 1 addition & 6 deletions lib/metrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { queryBuilder } from 'lib/planetscale';
import { cache } from 'react';

export const getBlogViews = cache(async () => {
if (!process.env.DATABASE_URL) {
if (!process.env.TWITTER_API_TOKEN) {
return 0;
}

Expand All @@ -17,10 +17,6 @@ export const getBlogViews = cache(async () => {
return data.reduce((acc, curr) => acc + Number(curr.count), 0);
});

export const getViewsCount = cache(async () => {
return queryBuilder.selectFrom('views').select(['slug', 'count']).execute();
});

export async function getTweetCount() {
if (!process.env.TWITTER_API_TOKEN) {
return 0;
Expand All @@ -29,7 +25,6 @@ export async function getTweetCount() {
const response = await fetch(
`https://api.twitter.com/2/users/by/username/leeerob?user.fields=public_metrics`,
{
cache: 'force-cache',
headers: {
Authorization: `Bearer ${process.env.TWITTER_API_TOKEN}`,
},
Expand Down
Loading

0 comments on commit e3ee434

Please sign in to comment.