Skip to content

Commit 3304ef4

Browse files
authored
Merge pull request #340 from ProgrammingLab/copilot/seo-optimization-update
SEO improvements: proper metadata, OGP, sitemap, robots.txt, lang fix
2 parents b767609 + 13cb03f commit 3304ef4

File tree

7 files changed

+186
-86
lines changed

7 files changed

+186
-86
lines changed

src/app/access/access-client.tsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
"use client";
3+
import { useEffect, useRef } from "react";
4+
5+
export default function AccessClient() {
6+
const isOnce = useRef(false);
7+
const map = useRef<any>(null);
8+
const mapRef = useRef<HTMLDivElement>(null);
9+
10+
const toggle = (file: string) => {
11+
if (map.current && mapRef.current) {
12+
window.scrollTo({
13+
top: mapRef.current.offsetTop - 80,
14+
behavior: "smooth",
15+
});
16+
map.current.destroy();
17+
map.current = null;
18+
// mapRef.current.innerHTML = "";
19+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
20+
//@ts-ignore
21+
map.current = new Vivus(
22+
"map",
23+
{
24+
type: "oneByOne",
25+
duration: 200,
26+
file,
27+
},
28+
() => {
29+
mapRef.current?.removeChild(mapRef.current.firstChild!);
30+
},
31+
);
32+
}
33+
};
34+
35+
useEffect(() => {
36+
if (isOnce.current) return;
37+
isOnce.current = true;
38+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
39+
//@ts-ignore
40+
map.current = new Vivus("map", {
41+
type: "oneByOne",
42+
duration: 200,
43+
file: "/map_marked.svg",
44+
});
45+
}, []);
46+
47+
return (
48+
<div className="text-center md:px-40 flex flex-col items-center">
49+
<p className="text-lg font-bold md:text-3xl border-b mb-2 px-4">
50+
ProLab 活動場所への移動
51+
</p>
52+
<p className="md:text-lg">電気電子・制御情報工学科棟(E03)</p>
53+
<p className="mb-4 md:text-lg">
54+
<span className="font-bold">2階</span> 校門側 制御情報実験室(SJ教室)
55+
</p>
56+
<div
57+
id="map"
58+
className="w-80 md:w-auto h-auto md:h-[80vh] grid *:row-start-1 *:col-start-1"
59+
ref={mapRef}
60+
></div>
61+
<Button onClick={() => toggle("/map_marked.svg")}>
62+
SJ教室を確認する
63+
</Button>
64+
<Button onClick={() => toggle("/map_from_ippan.svg")}>
65+
一般棟からの経路を確認する
66+
</Button>
67+
<Button onClick={() => toggle("/map_from_seimon.svg")}>
68+
正門からの経路を確認する
69+
</Button>
70+
</div>
71+
);
72+
}
73+
74+
const Button = (props: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
75+
<button
76+
className="w-full sm:w-60 md:w-90 px-4 py-2 bg-blue-600 text-white rounded hover:brightness-75 transition mt-4"
77+
{...props}
78+
/>
79+
);

src/app/access/page.tsx

Lines changed: 15 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,15 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
"use client";
3-
import { Strong } from "@/components/markup";
4-
import Image from "next/image";
5-
import Link from "next/link";
6-
import { useEffect, useRef } from "react";
7-
8-
export default function Home() {
9-
const isOnce = useRef(false);
10-
const map = useRef<any>(null);
11-
const mapRef = useRef<HTMLDivElement>(null);
12-
13-
const toggle = (file: string) => {
14-
if (map.current && mapRef.current) {
15-
window.scrollTo({
16-
top: mapRef.current.offsetTop - 80,
17-
behavior: "smooth",
18-
});
19-
map.current.destroy();
20-
map.current = null;
21-
// mapRef.current.innerHTML = "";
22-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
23-
//@ts-ignore
24-
map.current = new Vivus(
25-
"map",
26-
{
27-
type: "oneByOne",
28-
duration: 200,
29-
file,
30-
},
31-
() => {
32-
mapRef.current?.removeChild(mapRef.current.firstChild!);
33-
},
34-
);
35-
}
36-
};
37-
38-
useEffect(() => {
39-
if (isOnce.current) return;
40-
isOnce.current = true;
41-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
42-
//@ts-ignore
43-
map.current = new Vivus("map", {
44-
type: "oneByOne",
45-
duration: 200,
46-
file: "/map_marked.svg",
47-
});
48-
}, []);
49-
50-
return (
51-
<div className="text-center md:px-40 flex flex-col items-center">
52-
<p className="text-lg font-bold md:text-3xl border-b mb-2 px-4">
53-
ProLab 活動場所への移動
54-
</p>
55-
<p className="md:text-lg">電気電子・制御情報工学科棟(E03)</p>
56-
<p className="mb-4 md:text-lg">
57-
<span className="font-bold">2階</span> 校門側 制御情報実験室(SJ教室)
58-
</p>
59-
<div
60-
id="map"
61-
className="w-80 md:w-auto h-auto md:h-[80vh] grid *:row-start-1 *:col-start-1"
62-
ref={mapRef}
63-
></div>
64-
<Button onClick={() => toggle("/map_marked.svg")}>
65-
SJ教室を確認する
66-
</Button>
67-
<Button onClick={() => toggle("/map_from_ippan.svg")}>
68-
一般棟からの経路を確認する
69-
</Button>
70-
<Button onClick={() => toggle("/map_from_seimon.svg")}>
71-
正門からの経路を確認する
72-
</Button>
73-
</div>
74-
);
75-
}
76-
77-
const Button = (props: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
78-
<button
79-
className="w-full sm:w-60 md:w-90 px-4 py-2 bg-blue-600 text-white rounded hover:brightness-75 transition mt-4"
80-
{...props}
81-
/>
82-
);
1+
import type { Metadata } from "next";
2+
import AccessClient from "./access-client";
3+
4+
export const metadata: Metadata = {
5+
title: "アクセス",
6+
description:
7+
"久留米高専プログラミングラボ部(ProLab)の活動場所への行き方です。電気電子・制御情報工学科棟(E03)2階 制御情報実験室(SJ教室)で活動しています。",
8+
openGraph: {
9+
url: "https://www.prolab.club/access",
10+
},
11+
};
12+
13+
export default function AccessPage() {
14+
return <AccessClient />;
15+
}

src/app/contact/page.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
import type { Metadata } from "next";
2+
3+
export const metadata: Metadata = {
4+
title: "コンタクト",
5+
description: "久留米高専プログラミングラボ部(ProLab)へのお問い合わせはこちら。",
6+
openGraph: {
7+
url: "https://www.prolab.club/contact",
8+
},
9+
};
10+
111
export default function Contact() {
212
return (
313
<div className="h-[80vh] bg-linear-to-br from-slate-900 via-purple-900 to-slate-900 flex flex-col items-center justify-center px-4">

src/app/layout.tsx

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,38 @@ const geistMono = Geist_Mono({
1414
subsets: ["latin"],
1515
});
1616

17+
const siteUrl = "https://www.prolab.club";
18+
1719
export const metadata: Metadata = {
18-
title: "Create Next App",
19-
description: "Generated by create next app",
20+
metadataBase: new URL(siteUrl),
21+
title: {
22+
default: "久留米高専 プログラミングラボ部",
23+
template: "%s | 久留米高専 プログラミングラボ部",
24+
},
25+
description:
26+
"久留米高専プログラミングラボ部(ProLab)の公式サイトです。プログラミングに興味を持つ学生が集まり、アプリ・ゲーム・アルゴリズムを制作しています。",
27+
openGraph: {
28+
type: "website",
29+
locale: "ja_JP",
30+
url: siteUrl,
31+
siteName: "久留米高専 プログラミングラボ部",
32+
title: "久留米高専 プログラミングラボ部",
33+
description:
34+
"久留米高専プログラミングラボ部(ProLab)の公式サイトです。プログラミングに興味を持つ学生が集まり、アプリ・ゲーム・アルゴリズムを制作しています。",
35+
images: [
36+
{
37+
url: "/logo.png",
38+
alt: "久留米高専 プログラミングラボ部",
39+
},
40+
],
41+
},
42+
twitter: {
43+
card: "summary",
44+
title: "久留米高専 プログラミングラボ部",
45+
description:
46+
"久留米高専プログラミングラボ部(ProLab)の公式サイトです。プログラミングに興味を持つ学生が集まり、アプリ・ゲーム・アルゴリズムを制作しています。",
47+
images: ["/logo.png"],
48+
},
2049
};
2150

2251
export default function RootLayout({
@@ -25,9 +54,9 @@ export default function RootLayout({
2554
children: React.ReactNode;
2655
}>) {
2756
return (
28-
<html lang="en" suppressHydrationWarning>
57+
<html lang="ja" suppressHydrationWarning>
2958
<head>
30-
<link rel="icon" href="/logo.png" type="image/svg+xml"></link>
59+
<link rel="icon" href="/logo.png" type="image/png"></link>
3160
</head>
3261
<body
3362
className={`${geistSans.variable} ${geistMono.variable} antialiased`}

src/app/page.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1+
import type { Metadata } from "next";
12
import { Strong } from "@/components/markup";
23
import Image from "next/image";
34
import Link from "next/link";
45

6+
export const metadata: Metadata = {
7+
title: "久留米高専 プログラミングラボ部",
8+
description:
9+
"久留米高専プログラミングラボ部(ProLab)の公式サイトです。プログラミングに興味を持つ学生が集まり、アプリ・ゲーム・アルゴリズムを制作しています。毎週月〜木曜日 16:30〜 電気電子・制御情報工学科棟2階 SJ教室にて活動中。",
10+
openGraph: {
11+
url: "https://www.prolab.club",
12+
},
13+
};
14+
515
export default function Home() {
616
return (
717
<div className="text-center md:px-40 px-2">

src/app/robots.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { MetadataRoute } from "next";
2+
3+
const siteUrl = "https://www.prolab.club";
4+
5+
export default function robots(): MetadataRoute.Robots {
6+
return {
7+
rules: {
8+
userAgent: "*",
9+
allow: "/",
10+
},
11+
sitemap: `${siteUrl}/sitemap.xml`,
12+
};
13+
}

src/app/sitemap.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { MetadataRoute } from "next";
2+
3+
const siteUrl = "https://www.prolab.club";
4+
5+
export default function sitemap(): MetadataRoute.Sitemap {
6+
return [
7+
{
8+
url: siteUrl,
9+
lastModified: new Date(),
10+
changeFrequency: "monthly",
11+
priority: 1,
12+
},
13+
{
14+
url: `${siteUrl}/access`,
15+
lastModified: new Date(),
16+
changeFrequency: "monthly",
17+
priority: 0.8,
18+
},
19+
{
20+
url: `${siteUrl}/contact`,
21+
lastModified: new Date(),
22+
changeFrequency: "monthly",
23+
priority: 0.6,
24+
},
25+
];
26+
}

0 commit comments

Comments
 (0)