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

feat: Migrate into Next.js App Router #353

Merged
merged 15 commits into from
Oct 25, 2023
20 changes: 20 additions & 0 deletions src/app/blog/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { BlogInfo, BlogInfos, getAllBlogInfos, getBlogFromId } from "../../lib/blog-fetch";
Fixed Show fixed Hide fixed
import { Metadata } from "next";
import { Post } from "./post";

export async function generateMetadata({ params }: { params: BlogInfo }): Promise<Metadata> {
const { title } = await getBlogFromId(params.id);
return { title };
shun-shobon marked this conversation as resolved.
Show resolved Hide resolved
}

export async function generateStaticParams(): Promise<BlogInfos> {
return getAllBlogInfos();
}

export default async function Page({ params }: { params?: BlogInfo }) {
if (params == null) {
throw new Error("invalid params");
}
const post = await getBlogFromId(params.id);
return <Post post={post} />;
}
34 changes: 7 additions & 27 deletions src/pages/blog/[id].tsx → src/app/blog/[id]/post.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Blog, BlogInfo, getAllBlogInfos, getBlogFromId } from "../../lib/blog-fetch";
"use client";
Dismissed Show dismissed Hide dismissed

import { Container, Heading, Link, Text, VStack } from "@chakra-ui/react";
import type { GetStaticPaths, GetStaticProps, NextPage } from "next";
import { Blog } from "../../lib/blog-fetch";
import { DateString } from "../../components/date";
import { Layout } from "../../components/layout";
import MarkdownIt from "markdown-it";
import MarkdownItFootnote from "markdown-it-footnote";
import MarkdownItFrontMatter from "markdown-it-front-matter";
Expand All @@ -17,11 +17,11 @@
.use(MarkdownItFrontMatter)
.use(MarkdownItFootnote);

type BlogPostPageProps = {
export type BlogPostPageProps = {
post: Blog;
};

const BlogPostPage: NextPage<BlogPostPageProps> = ({ post }) => {
export const Post = ({ post }: BlogPostPageProps) => {
const prevNext = (
<PrevNextLink
prevLinkHref={post.prevId !== "" ? post.prevId : null}
Expand All @@ -30,7 +30,7 @@
);
const bodyHtml = md.render(emojify`${post.content}`);
return (
<Layout pageName={`限界開発鯖 - ブログ - ${post.title}`}>
<>
<VStack>
<Heading m={8} textAlign="center">
{post.title}
Expand All @@ -48,26 +48,6 @@
<div dangerouslySetInnerHTML={{ __html: bodyHtml }} />
</Container>
{prevNext}
</Layout>
</>
);
};

export const getStaticProps: GetStaticProps<BlogPostPageProps, BlogInfo> = async ({ params }) => {
if (params == null) {
throw new Error("invalid params");
}
console.dir(params);
const post = await getBlogFromId(params.id);
return {
props: {
post,
},
};
};

export const getStaticPaths: GetStaticPaths<BlogInfo> = async () => {
const paths = await getAllBlogInfos();
return { paths, fallback: false };
};

export default BlogPostPage;
40 changes: 16 additions & 24 deletions src/pages/blog.tsx → src/app/blog/blog.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
Dismissed Show dismissed Hide dismissed
import {
Avatar,
Button,
Expand All @@ -9,17 +10,20 @@
Spacer,
VStack,
} from "@chakra-ui/react";
import type { GetStaticProps, NextPage } from "next";
import { Metadata, getSortedBlogMetadata } from "../lib/blog-fetch";
import { DateString } from "../components/date";
import { Layout } from "../components/layout";
import { Metadata } from "../lib/blog-fetch";
import NextLink from "next/link";
import { Title } from "../components/title";
import { Metadata as NextMetadata } from "next";
import type { NextPage } from "next";

export const metadata: NextMetadata = {
title: "限界開発鯖 - ブログ",
};

const BlogCard = ({ id, title, date, author, authorId }: Metadata): JSX.Element => (
<HStack borderColor="shadowed" borderRightWidth="1px" borderBottomWidth="2px">
<NextLink href={`/blog/${id}`} passHref>
<Avatar as="a" flex="0 0 sm" name={title} />
<Avatar flex="0 0 sm" name={title} />
</NextLink>
<VStack alignItems="self-start" flex="1 1" p={2} spacing="0.5">
<NextLink href={`/blog/${id}`} passHref>
Expand All @@ -32,29 +36,17 @@
<DateString dateString={date} />
<Spacer />
<NextLink href={`/blog/${id}`} passHref>
<Button as="a" size="sm">
記事を読む &rarr;
</Button>
<Button size="sm">記事を読む &rarr;</Button>
</NextLink>
shun-shobon marked this conversation as resolved.
Show resolved Hide resolved
</Flex>
</VStack>
</HStack>
);

const BlogPage: NextPage<{ blogs: Metadata[] }> = ({ blogs }) => (
<Layout pageName="限界開発鯖 - ブログ">
<Title>ブログ</Title>
<SimpleGrid gap={4} columns={1}>
{blogs.map((blog) => (
<BlogCard key={blog.id} {...blog} />
))}
</SimpleGrid>
</Layout>
export const Blog: NextPage<{ blogs: Metadata[] }> = ({ blogs }) => (
<SimpleGrid gap={4} columns={1}>
{blogs.map((blog) => (
<BlogCard key={blog.id} {...blog} />
))}
</SimpleGrid>
);

export const getStaticProps: GetStaticProps = async () => {
const blogs = await getSortedBlogMetadata();
return { props: { blogs } };
};

export default BlogPage;
7 changes: 7 additions & 0 deletions src/app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Blog } from "./blog";
import { getSortedBlogMetadata } from "../lib/blog-fetch";

export default async function Page() {
const blogs = await getSortedBlogMetadata();
return <Blog blogs={blogs} />;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { DateString } from "./date";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<DateString dateString="2021-01-01" />);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Footer } from "./footer";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<Footer />);
Expand Down
2 changes: 2 additions & 0 deletions src/components/footer.tsx → src/app/components/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";
Dismissed Show dismissed Hide dismissed

import { Box, Link } from "@chakra-ui/react";

import NextLink from "next/link";
Expand Down
66 changes: 66 additions & 0 deletions src/app/components/google-analytics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use client";
Dismissed Show dismissed Hide dismissed

import { usePathname, useSearchParams } from "next/navigation";
import Script from "next/script";
import { useEffect } from "react";

export const GOOGLE_ANALYTICS_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID ?? "";

const notifyShowingPage = (url: string): void => {
(
window as unknown as { gtag(event: "config", id: string, options: { page_path: string }): void }
).gtag("config", GOOGLE_ANALYTICS_ID, {
page_path: url,
});
};

type Event = {
action: string;
category: string;
label: string;
value?: string;
};

const event = ({ action, category, label, value }: Event): void => {
Fixed Show fixed Hide fixed
(
window as unknown as {
gtag(
event: "event",
id: string,
options: { event_category: string; event_label: string; value?: string },
): void;
}
).gtag("event", action, {
event_category: category,
event_label: label,
value: value,
});
};

export const GoogleAnalytics = () => {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
notifyShowingPage(`${pathname}?${searchParams}`);
}, [pathname, searchParams]);
return (
<>
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${GOOGLE_ANALYTICS_ID}`}
/>
<Script strategy="afterInteractive" id="send-ga">
{`
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "${GOOGLE_ANALYTICS_ID}", {
page_path: window.location.pathname,
});
`}
</Script>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Header } from "./header";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<Header />);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Navigation } from "./navigation";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";
Dismissed Show dismissed Hide dismissed

import {
Button,
Container,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { PrevNextLink } from "./prev-next-link";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders both prev and next correctly", () => {
const tree = render(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Questions } from "./questions";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<Questions />);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { SNSLink } from "./sns-link";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders twitter link correctly", () => {
const tree = render(<SNSLink type="twitter" url="https://twitter.com/MikurXina" />);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Subtitle, Title } from "./title";
import { expect, it } from "vitest";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders title correctly", () => {
const tree = render(<Title>Epic Title</Title>);
Expand Down
File renamed without changes.
6 changes: 6 additions & 0 deletions src/app/fonts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Roboto } from "next/font/google";

export const roboto = Roboto({
weight: "400",
subsets: ["latin"],
});
Loading
Loading