Skip to content

Commit 6e02cae

Browse files
authored
🚀 | Merge pull request #3 from Syobosetsu-Proj/feat/blog
✨️ | Feat: simple blog
2 parents 001f06f + c6f5c27 commit 6e02cae

10 files changed

Lines changed: 2253 additions & 45 deletions

File tree

package-lock.json

Lines changed: 1901 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,26 @@
99
"lint": "eslint"
1010
},
1111
"dependencies": {
12+
"gray-matter": "^4.0.3",
1213
"next": "16.0.0",
1314
"react": "19.2.0",
14-
"react-dom": "19.2.0"
15+
"react-dom": "19.2.0",
16+
"react-markdown": "^10.1.0",
17+
"rehype-raw": "^7.0.0",
18+
"remark-gfm": "^4.0.1"
1519
},
1620
"devDependencies": {
1721
"@tailwindcss/postcss": "^4",
22+
"@tailwindcss/typography": "^0.5.19",
1823
"@types/node": "^20",
1924
"@types/react": "^19",
2025
"@types/react-dom": "^19",
2126
"autoprefixer": "^10.4.21",
2227
"eslint": "^9",
2328
"eslint-config-next": "16.0.0",
2429
"postcss": "^8.5.6",
30+
"remark": "^15.0.1",
31+
"remark-html": "^16.0.1",
2532
"tailwindcss": "^4.1.16",
2633
"typescript": "^5"
2734
}

posts/251029_BornBlog.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
title: "ブログができました。"
3+
date: "2025-10-29"
4+
description: "簡易的なブログができちゃいましたよ。どうしよう"
5+
---
6+
# 🎉 | やったぜ
7+
8+
紆余曲折の結果、なんとかブログ(笑)を完成させました。
9+
多分ほぼ使わない。
10+
まあ、あっても困らんでしょう理論。
11+
12+
---
13+
14+
以下、テスト
15+
16+
# レベル1の見出し
17+
18+
## レベル2の見出し
19+
20+
### レベル3の見出し
21+
22+
#### レベル4の見出し
23+
24+
##### レベル5の見出し
25+
26+
###### レベル6の見出し
27+
28+
> "このテキストは、HTMLのblockquote要素に囲まれます。
29+
> blockquote要素はreflowableです。テキストを好きなように
30+
> 改行することができます。改行したとしても、変換後はひとつの
31+
> blockquote要素として扱われます。"
32+
33+
* 順序無しリストのアイテム
34+
* サブアイテムはタブもしくは4つのスペースでインデントする
35+
* 順序無しリストの別のアイテム
36+
37+
1. 順序付きリストのアイテム
38+
1. サブアイテムはタブもしくは4つのスペースでインデントする
39+
2. 順序付きリストの別のアイテム
40+
41+
これは段落です。文中に `コードテキスト`を含みます。
42+
43+
```text
44+
This is CodeBlock Line 1.
45+
This is CodeBlock Line 2.
46+
This is CodeBlock Line 3.
47+
```
48+
49+
[リンクのテキスト](リンクのアドレス "リンクのタイトル")
50+
51+
*強調*(斜体として表現されることが多い)
52+
**強い強調**(太字として表現されることが多い)

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { getAllPosts, getPostBySlug } from "@/lib/posts";
2+
import { remark } from "remark";
3+
import html from "remark-html";
4+
import Link from "next/link";
5+
import { notFound } from 'next/navigation';
6+
7+
type Props = {
8+
params: Promise<{ slug: string }>;
9+
};
10+
11+
export async function generateStaticParams() {
12+
const posts = getAllPosts();
13+
return posts.map((post) => ({ slug: post.slug }));
14+
}
15+
16+
export default async function PostPage({ params }: Props) {
17+
const { slug } = await params;
18+
19+
try {
20+
const post = getPostBySlug(slug);
21+
const processedContent = await remark().use(html).process(post.content);
22+
const contentHtml = processedContent.toString();
23+
24+
return (
25+
<div className="min-h-screen text-neutral-100 py-20 px-6">
26+
<article className="max-w-5xl mx-auto bg-neutral-900/80 border border-neutral-800 backdrop-blur-md rounded-2xl shadow-md overflow-hidden p-10">
27+
<header className="border-b border-neutral-800 pb-6 mb-10">
28+
<p className="text-sm text-green-400 tracking-wide uppercase">
29+
{new Date(post.meta.date).toLocaleDateString("ja-JP", {
30+
year: "numeric",
31+
month: "long",
32+
day: "numeric",
33+
})}
34+
</p>
35+
<h1 className="mt-3 text-3xl font-bold text-white">{post.meta.title}</h1>
36+
{post.meta.description && (
37+
<p className="mt-3 text-neutral-400 text-sm leading-relaxed">
38+
{post.meta.description}
39+
</p>
40+
)}
41+
</header>
42+
43+
<div
44+
className="prose prose-invert lg:prose-xl max-w-none"
45+
dangerouslySetInnerHTML={{ __html: contentHtml }}
46+
/>
47+
48+
<footer className="border-t border-neutral-800 pt-6 mt-10">
49+
<Link href="/blog" className="mt-6 text-sm font-bold text-green-400 tracking-wide uppercase">
50+
→ Back
51+
</Link>
52+
</footer>
53+
</article>
54+
</div>
55+
);
56+
} catch (error) {
57+
console.error(`Failed to load post ${slug}:`, error);
58+
notFound();
59+
}
60+
}

src/app/blog/page.tsx

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,41 @@
11
import Link from "next/link";
2+
import Image from "next/image";
3+
import { getAllPosts } from "@/lib/posts";
4+
5+
export default async function BlogPage() {
6+
const posts = getAllPosts();
27

3-
export default function BlogPage() {
48
return (
5-
<div className="items-centerrelative min-h-screen flex items-center justify-center overflow-hidden bg-neutral-950">
6-
<h1>Preparing...</h1>
9+
<div className="text-neutral-100 py-20 px-6">
10+
<div className="max-w-3xl mx-auto">
11+
12+
<ul className="mt-12 space-y-6">
13+
{posts.map((post) => (
14+
<li key={post.slug}>
15+
<Link
16+
href={`/blog/${post.slug}`}
17+
className="block p-4 border border-neutral-800 rounded-xl bg-neutral-900/80 backdrop-blur-md hover:border-green-500/50 hover:text-green-400 transition-all duration-300"
18+
>
19+
<div className="flex justify-between items-center">
20+
<h2 className="text-xl font-semibold">{post.meta.title}</h2>
21+
<span className="text-sm text-green-400">
22+
{new Date(post.meta.date).toLocaleDateString("ja-JP", {
23+
year: "numeric",
24+
month: "short",
25+
day: "numeric",
26+
})}
27+
</span>
28+
</div>
29+
{post.meta.description && (
30+
<p className="mt-2 text-neutral-400 text-sm line-clamp-2">
31+
{post.meta.description}
32+
</p>
33+
)}
34+
</Link>
35+
</li>
36+
))}
37+
</ul>
38+
</div>
739
</div>
840
);
9-
}
41+
}

src/app/globals.css

Lines changed: 143 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,149 @@ body {
2525
font-family: Arial, Helvetica, sans-serif;
2626
}
2727

28-
@tailwind base;
29-
@tailwind components;
30-
@tailwind utilities;
28+
@layer base {
29+
.prose {
30+
color: #f7fafc;
31+
}
32+
33+
/* 見出し */
34+
.prose h1 {
35+
font-size: 2rem;
36+
line-height: 2.5rem;
37+
font-weight: 700;
38+
padding: 10px 0;
39+
}
40+
41+
.prose h2 {
42+
font-size: 1.75rem;
43+
line-height: 2.25rem;
44+
font-weight: 700;
45+
padding: 10px 0;
46+
}
47+
48+
.prose h3 {
49+
font-size: 1.5rem;
50+
line-height: 2rem;
51+
font-weight: 700;
52+
padding: 10px 0;
53+
}
54+
55+
.prose h4 {
56+
font-size: 1.25rem;
57+
line-height: 1.75rem;
58+
font-weight: 700;
59+
padding: 8px 0;
60+
}
61+
62+
.prose h5 {
63+
font-size: 1.125rem;
64+
line-height: 1.5rem;
65+
font-weight: 700;
66+
padding: 6px 0;
67+
}
68+
69+
.prose h6 {
70+
font-size: 1rem;
71+
line-height: 1.25rem;
72+
font-weight: 700;
73+
padding: 4px 0;
74+
}
75+
76+
/* 段落 */
77+
.prose p {
78+
font-size: 1rem;
79+
line-height: 1.6rem;
80+
padding-bottom: 10px;
81+
}
82+
83+
/* 水平線 */
84+
.prose hr {
85+
border-color: #4a5568;
86+
margin: 30px 0;
87+
}
88+
89+
/* リスト */
90+
.prose ul {
91+
list-style-type: disc;
92+
padding-left: 1.5rem;
93+
margin-bottom: 1rem;
94+
}
95+
96+
.prose ol {
97+
list-style-type: decimal;
98+
padding-left: 1.5rem;
99+
margin-bottom: 1rem;
100+
}
101+
102+
.prose li {
103+
margin-bottom: 0.5rem;
104+
}
105+
106+
/* リンク */
107+
.prose a {
108+
color: #63b3ed;
109+
text-decoration: underline;
110+
}
111+
112+
.prose a:hover {
113+
color: #4299e1;
114+
}
115+
116+
/* 引用 */
117+
.prose blockquote {
118+
border-left: 4px solid #4a5568;
119+
padding-left: 1rem;
120+
color: #a0aec0;
121+
font-style: italic;
122+
margin: 1rem 0;
123+
}
124+
125+
/* コードインライン */
126+
.prose code {
127+
background-color: #252525;
128+
padding: 2px 6px;
129+
border-radius: 4px;
130+
font-size: 0.95rem;
131+
font-family: "Fira Code", monospace;
132+
}
133+
134+
.prose pre {
135+
background-color: #252525;
136+
padding: 1rem;
137+
border-radius: 8px;
138+
overflow-x: auto;
139+
font-size: 0.95rem;
140+
font-family: "Fira Code", monospace;
141+
line-height: 1.5rem;
142+
white-space: pre-wrap;
143+
}
144+
145+
/* 画像 */
146+
.prose img {
147+
max-width: 100%;
148+
border-radius: 8px;
149+
margin: 1rem 0;
150+
}
151+
152+
/* テーブル */
153+
.prose table {
154+
width: 100%;
155+
border-collapse: collapse;
156+
margin-bottom: 1rem;
157+
}
158+
159+
.prose th,
160+
.prose td {
161+
border: 1px solid #4a5568;
162+
padding: 0.5rem;
163+
text-align: left;
164+
}
165+
166+
.prose th {
167+
background-color: #2d3748;
168+
}
169+
}
170+
31171

32172
@layer utilities {
33173
.fade-in {

src/app/layout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ export default function RootLayout({
2727
<body
2828
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
2929
>
30-
{children}
30+
<div className="min-h-screen bg-[url('/bk1.png')] bg-cover bg-center bg-fixed bg-neutral-950">
31+
{children}
32+
</div>
3133
</body>
3234
</html>
3335
);

src/app/page.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Image from "next/image";
1+
import Link from "next/link";
22

33
async function getOrgData() {
44
const res = await fetch(`https://api.github.com/orgs/Syobosetsu-Proj`, {
@@ -32,31 +32,23 @@ export function GithubButton(sublink: string) {
3232

3333
export function BookButton(link: string, text: string) {
3434
return (
35-
<a
35+
<Link
3636
href={link}
3737
rel="noopener noreferrer"
3838
className="mt-10 py-1.5 px-4 inline-flex items-center justify-center gap-2 transition-colors bg-green-800 active:bg-green-950 font-medium border-green-900 text-white rounded-lg hover:bg-green-900 disabled:opacity-50"
3939
>
4040
<img src="/icons/book.svg" alt="GitHub" className="w-5 h-5 filter invert" />
4141

4242
<span>{text}</span>
43-
</a>
43+
</Link>
4444
);
4545
}
4646

4747
export default async function Home() {
4848
const org = await getOrgData();
4949

5050
return (
51-
<div className="relative min-h-screen flex items-center justify-center overflow-hidden bg-neutral-950 fade-in">
52-
<Image
53-
src="/bk1.png"
54-
alt="Space background"
55-
fill
56-
unoptimized
57-
className="object-cover"
58-
/>
59-
51+
<div className="relative min-h-screen flex items-center justify-center overflow-hidden fade-in">
6052
<section className="fade-in">
6153
<div className="relative z-10 container mx-auto px-4 py-16">
6254
<div className="flex w-full flex-col items-center justify-center rounded-lg p-8">

0 commit comments

Comments
 (0)