diff --git a/.env b/.env
new file mode 100644
index 0000000..dfc11f3
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+BLOG_ENDPOINT=https://raw.githubusercontents.com/lumither/blog-posts/master
+; use mirror
diff --git a/app/blog/BlogPostCard.tsx b/app/blog/BlogPostCard.tsx
new file mode 100644
index 0000000..393a7ea
--- /dev/null
+++ b/app/blog/BlogPostCard.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import Link from 'next/link';
+import { Card, CardBody, CardHeader } from '@nextui-org/card';
+import { Divider } from '@nextui-org/react';
+
+type Props = {
+ post: JSON
+}
+
+function BlogPostCard({ post }: Props) {
+ const name = (post as any)['name'];
+ const { title, desc } = (post as any)['meta'] as { title: string, desc: string };
+ return (
+
+
+ {/*todo: to be update*/ }
+ {/*
*/}
+
+
+ { title }
+
+
+
+ { desc }
+
+
+ {/**/}
+
+ );
+
+}
+
+export default BlogPostCard;
diff --git a/app/blog/fetch_posts.ts b/app/blog/fetch_posts.ts
new file mode 100644
index 0000000..af53549
--- /dev/null
+++ b/app/blog/fetch_posts.ts
@@ -0,0 +1,19 @@
+import { Result } from '@/app/public/type/Result';
+
+export default async function fetch_posts(url: string): Promise> {
+ const response = await fetch(`${ url }/posts/idx.json`);
+ if (!response.ok) {
+ return {
+ ok: false,
+ error: new Error(response.statusText)
+ };
+ }
+ const res = await response.json();
+ const posts = res['idx'].filter((posts: { type: string }) => posts.type === 'md');
+ return {
+ ok: true,
+ value: posts
+ };
+}
+
+
diff --git a/app/blog/layout.tsx b/app/blog/layout.tsx
new file mode 100644
index 0000000..7600370
--- /dev/null
+++ b/app/blog/layout.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+
+function Layout({
+ children
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+ { children }
+
+ );
+}
+
+export default Layout;
diff --git a/app/blog/page.tsx b/app/blog/page.tsx
index 0f4291a..a9962fa 100644
--- a/app/blog/page.tsx
+++ b/app/blog/page.tsx
@@ -1,8 +1,27 @@
import React from 'react';
+import fetch_posts from '@/app/blog/fetch_posts';
+import BlogPostCard from '@/app/blog/BlogPostCard';
+
+async function Blog() {
+
+ const res = await fetch_posts(process.env.BLOG_ENDPOINT!);
+ if (!res.ok) {
+ console.log(res.error);
+ return;
+ }
+ const posts = res.value;
+ // console.log(posts);
-function Blog() {
return (
-
+
+ // blog list
+
+ { posts.map((post, key) => (
+ -
+
+
)
+ ) }
+
);
}
diff --git a/app/public/type/Result.ts b/app/public/type/Result.ts
new file mode 100644
index 0000000..e9c21ba
--- /dev/null
+++ b/app/public/type/Result.ts
@@ -0,0 +1,7 @@
+export type Result = {
+ ok: true;
+ value: T;
+} | {
+ ok: false;
+ error: E;
+};
diff --git a/tsconfig.json b/tsconfig.json
index e7ff90f..a69d60e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -4,6 +4,7 @@
"allowJs": true,
"skipLibCheck": true,
"strict": true,
+ "target": "ESNext",
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",