Skip to content

Commit 5f9fb31

Browse files
committed
refactor: use app router instead of page
1 parent 19e6ce2 commit 5f9fb31

File tree

20 files changed

+317
-470
lines changed

20 files changed

+317
-470
lines changed

src/app/api/version/route.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const GET = async () => {
2+
const res = await fetch("https://api.github.com/repos/usememos/memos/tags", {
3+
headers: {
4+
Accept: "application/vnd.github.v3.star+json",
5+
Authorization: "",
6+
},
7+
});
8+
const data = (await res.json()) as any[];
9+
return Response.json(data[0].name);
10+
};

src/app/blog/[[...slug]]/page.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Markdoc from "@markdoc/markdoc";
2+
import fs from "fs";
3+
import path from "path";
4+
import React from "react";
5+
import AuthorView from "@/components/AuthorView";
6+
import authorList from "@/consts/author";
7+
import { getBlogSlugList } from "@/lib/content";
8+
import { markdoc } from "@/markdoc/markdoc";
9+
10+
const Page = ({ params }: { params: { slug: string[] } }) => {
11+
const content = readBlogContent(params.slug);
12+
const { frontmatter, transformedContent } = markdoc(content);
13+
const author = authorList.find((author) => author.name === frontmatter.author);
14+
15+
return (
16+
<>
17+
<div className="pt-12 w-full mx-auto sm:px-20 prose prose-lg max-w-none prose-a:text-blue-600">
18+
<h1>{frontmatter.title}</h1>
19+
{author && <AuthorView author={author} />}
20+
{Markdoc.renderers.react(transformedContent, React)}
21+
</div>
22+
</>
23+
);
24+
};
25+
26+
export const generateStaticParams = () => {
27+
return [
28+
{ slug: [] },
29+
...[...getBlogSlugList()].map((contentSlug) => {
30+
return { slug: contentSlug };
31+
}),
32+
];
33+
};
34+
35+
const readBlogContent = (contentSlug: string[]) => {
36+
let filePath = path.resolve("./content/blog/index.md");
37+
if (Array.isArray(contentSlug) && contentSlug.length !== 0) {
38+
const indexFilePath = path.resolve(`./content/blog/${contentSlug.join("/")}/index.md`);
39+
if (fs.existsSync(indexFilePath)) {
40+
filePath = indexFilePath;
41+
} else {
42+
filePath = path.resolve(`./content/blog/${contentSlug.join("/")}.md`);
43+
}
44+
}
45+
const content = fs.readFileSync(filePath, "utf8");
46+
return content;
47+
};
48+
49+
export default Page;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Markdoc from "@markdoc/markdoc";
2+
import fs from "fs";
3+
import path from "path";
4+
import React from "react";
5+
import AuthorView from "@/components/AuthorView";
6+
import authorList from "@/consts/author";
7+
import { getChangelogSlugList } from "@/lib/content";
8+
import { markdoc } from "@/markdoc/markdoc";
9+
10+
const Page = ({ params }: { params: { slug: string[] } }) => {
11+
const content = readChangelogContent(params.slug);
12+
const { frontmatter, transformedContent } = markdoc(content);
13+
const author = authorList.find((author) => author.name === frontmatter.author);
14+
15+
return (
16+
<>
17+
<div className="pt-12 w-full mx-auto sm:px-20 prose prose-lg max-w-none prose-a:text-blue-600">
18+
<h1>{frontmatter.title}</h1>
19+
{author && <AuthorView author={author} />}
20+
{Markdoc.renderers.react(transformedContent, React)}
21+
</div>
22+
</>
23+
);
24+
};
25+
26+
export const generateStaticParams = () => {
27+
return [
28+
{ slug: [] },
29+
...[...getChangelogSlugList()].map((contentSlug) => {
30+
return { slug: contentSlug };
31+
}),
32+
];
33+
};
34+
35+
const readChangelogContent = (contentSlug: string[]) => {
36+
let filePath = path.resolve("./content/changelog/index.md");
37+
if (Array.isArray(contentSlug) && contentSlug.length !== 0) {
38+
const indexFilePath = path.resolve(`./content/changelog/${contentSlug.join("/")}/index.md`);
39+
if (fs.existsSync(indexFilePath)) {
40+
filePath = indexFilePath;
41+
} else {
42+
filePath = path.resolve(`./content/changelog/${contentSlug.join("/")}.md`);
43+
}
44+
}
45+
const content = fs.readFileSync(filePath, "utf8");
46+
return content;
47+
};
48+
49+
export default Page;

src/app/docs/[[...slug]]/page.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Markdoc from "@markdoc/markdoc";
2+
import fs from "fs";
3+
import path from "path";
4+
import React from "react";
5+
import AuthorView from "@/components/AuthorView";
6+
import authorList from "@/consts/author";
7+
import { getDocsSlugList } from "@/lib/content";
8+
import { markdoc } from "@/markdoc/markdoc";
9+
10+
const Page = ({ params }: { params: { slug: string[] } }) => {
11+
const content = readDocsContent(params.slug);
12+
const { frontmatter, transformedContent } = markdoc(content);
13+
const author = authorList.find((author) => author.name === frontmatter.author);
14+
15+
return (
16+
<>
17+
<div className="pt-12 w-full mx-auto sm:px-20 prose prose-lg max-w-none prose-a:text-blue-600">
18+
<h1>{frontmatter.title}</h1>
19+
{author && <AuthorView author={author} />}
20+
{Markdoc.renderers.react(transformedContent, React)}
21+
</div>
22+
</>
23+
);
24+
};
25+
26+
export const generateStaticParams = () => {
27+
return [
28+
{ slug: [] },
29+
...[...getDocsSlugList()].map((contentSlug) => {
30+
return { slug: contentSlug };
31+
}),
32+
];
33+
};
34+
35+
const readDocsContent = (contentSlug: string[]) => {
36+
let filePath = path.resolve("./content/docs/index.md");
37+
if (Array.isArray(contentSlug) && contentSlug.length !== 0) {
38+
const indexFilePath = path.resolve(`./content/docs/${contentSlug.join("/")}/index.md`);
39+
if (fs.existsSync(indexFilePath)) {
40+
filePath = indexFilePath;
41+
} else {
42+
filePath = path.resolve(`./content/docs/${contentSlug.join("/")}.md`);
43+
}
44+
}
45+
const content = fs.readFileSync(filePath, "utf8");
46+
return content;
47+
};
48+
49+
export default Page;

src/app/feature/[slug]/page.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Link from "next/link";
2+
import DemoPlaceholder from "@/components/DemoPlaceholder";
3+
import FeatureMatrix, { FEATURE_LIST, FeatureItem } from "@/components/FeatureMatrix";
4+
import LatestVersion from "@/components/LatestVersion";
5+
6+
const Page = ({ params }: { params: { slug: string } }) => {
7+
const feature = FEATURE_LIST.find((feature) => feature.slug === params.slug) as FeatureItem;
8+
9+
return (
10+
<>
11+
<div className="mt-6 sm:mt-12 w-full flex flex-col justify-start items-center">
12+
<LatestVersion />
13+
</div>
14+
<div className="w-full flex flex-col justify-center items-center sm:px-16">
15+
<feature.icon strokeWidth="1" className="h-14 mt-4 mb-2 sm:h-20 w-auto text-gray-500" />
16+
<h2 className="w-full text-center text-2xl sm:text-4xl font-bold mt-4 mb-4">{feature.title}</h2>
17+
<h3 className="w-full text-base sm:text-lg text-gray-500 text-center mb-2">{feature.description}</h3>
18+
</div>
19+
<div className="w-full flex flex-row justify-center items-center space-x-2 py-4">
20+
<Link target="_blank" href="https://github.com/usememos/memos">
21+
<img alt="GitHub stars" src="https://img.shields.io/github/stars/usememos/memos?logo=github" />
22+
</Link>
23+
<Link target="_blank" href="https://hub.docker.com/r/neosmemo/memos">
24+
<img alt="Docker" src="https://img.shields.io/docker/pulls/neosmemo/memos.svg?logo=docker" />
25+
</Link>
26+
<Link target="_blank" href="https://discord.gg/tfPJa4UmAv">
27+
<img alt="Discord" src="https://img.shields.io/badge/discord-chat-5865f2?logo=discord" />
28+
</Link>
29+
</div>
30+
<DemoPlaceholder />
31+
<FeatureMatrix />
32+
</>
33+
);
34+
};
35+
36+
export const generateStaticParams = () => {
37+
return FEATURE_LIST.map((feature) => {
38+
return {
39+
slug: feature.slug,
40+
};
41+
});
42+
};
43+
44+
export default Page;

src/app/layout.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Analytics } from "@vercel/analytics/react";
2+
import React from "react";
3+
import Footer from "@/components/Footer";
4+
import Header from "@/components/Header";
5+
import "@/styles/global.css";
6+
7+
const RootLayout = ({ children }: { children: React.ReactNode }) => {
8+
return (
9+
<html className="w-full h-full">
10+
<head>
11+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover" />
12+
<title>memos - Easily capture and share your great thoughts</title>
13+
<link rel="icon" href="/logo.ico" />
14+
<meta
15+
name="description"
16+
content="A privacy-first, lightweight note-taking service. Easily capture and share your great thoughts."
17+
key="desc"
18+
/>
19+
<meta name="og:title" property="og:title" content="memos - lightweight, self-hosted memo hub. Open Source and Free forever" />
20+
<meta
21+
name="og:description"
22+
content="A privacy-first, lightweight note-taking service. Easily capture and share your great thoughts."
23+
/>
24+
<meta name="og:type" property="og:type" content="website" />
25+
<meta name="twitter:card" content="summary" />
26+
<meta name="og:url" property="og:url" content="https://usememos.com" />
27+
</head>
28+
<body className="flex flex-col w-full h-full">
29+
<div className="relative w-full min-h-screen flex flex-col">
30+
<Header />
31+
32+
<main className="relative shrink-0 grow basis-auto mx-auto pt-6 pb-16 px-4 w-full max-w-6xl flex flex-col justify-start items-center">
33+
{children}
34+
</main>
35+
<Footer />
36+
</div>
37+
<Analytics />
38+
<script async src="https://analytics.eu.umami.is/script.js" data-website-id="b6e36293-961b-43eb-af79-d7da00f27707"></script>
39+
</body>
40+
</html>
41+
);
42+
};
43+
44+
export default RootLayout;

src/app/page.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Link from "next/link";
2+
import DemoPlaceholder from "@/components/DemoPlaceholder";
3+
import FeatureMatrix from "@/components/FeatureMatrix";
4+
import LatestVersion from "@/components/LatestVersion";
5+
import SlashBanner from "@/components/SlashBanner";
6+
7+
const Page = () => {
8+
return (
9+
<>
10+
<div className="mt-6 sm:mt-12 w-full flex flex-col justify-start items-center">
11+
<LatestVersion />
12+
</div>
13+
<div className="w-full flex flex-col justify-center items-center sm:px-16">
14+
<h2 className="w-full max-w-3xl text-center text-4xl sm:text-6xl font-medium sm:font-bold mt-4 mb-6">
15+
A privacy-first, lightweight note-taking service
16+
</h2>
17+
<h3 className="w-full text-base sm:text-lg text-gray-500 text-center mb-2">Easily capture and share your great thoughts.</h3>
18+
</div>
19+
<div className="w-full flex flex-row justify-center items-center space-x-2 py-4">
20+
<Link target="_blank" href="https://github.com/usememos/memos">
21+
<img alt="GitHub stars" src="https://img.shields.io/github/stars/usememos/memos?logo=github" />
22+
</Link>
23+
<Link target="_blank" href="https://hub.docker.com/r/neosmemo/memos">
24+
<img alt="Docker" src="https://img.shields.io/docker/pulls/neosmemo/memos.svg?logo=docker" />
25+
</Link>
26+
<Link target="_blank" href="https://discord.gg/tfPJa4UmAv">
27+
<img alt="Discord" src="https://img.shields.io/badge/discord-chat-5865f2?logo=discord" />
28+
</Link>
29+
</div>
30+
<DemoPlaceholder />
31+
<div className="w-full flex flex-row justify-center items-center">
32+
<SlashBanner />
33+
</div>
34+
<FeatureMatrix />
35+
</>
36+
);
37+
};
38+
39+
export default Page;

src/components/AuthorView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Link from "next/link";
2-
import { Author } from "../consts/author";
2+
import { Author } from "@/consts/author";
33
import Icon from "./Icon";
44

55
interface Props {

src/components/LatestVersion.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"use client";
2+
13
import axios from "axios";
24
import Link from "next/link";
35
import { useEffect, useState } from "react";

src/markdoc/heading.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { nodes } from "@markdoc/markdoc";
22

3-
function generateID(children: any, attributes: any) {
3+
const generateID = (children: any, attributes: any) => {
44
if (attributes.id && typeof attributes.id === "string") {
55
return attributes.id;
66
}
@@ -11,7 +11,7 @@ function generateID(children: any, attributes: any) {
1111
.replace(/\./g, "")
1212
.replace(/\s+/g, "-")
1313
.toLowerCase();
14-
}
14+
};
1515

1616
const header = {
1717
...nodes.heading,

0 commit comments

Comments
 (0)