Skip to content

Commit 7ef1291

Browse files
authored
Merge pull request #83 from S0L-V/feat/seo
[FEAT] SEO 최적화 — 메타 태그 + OG 이미지 + sitemap
2 parents 699b28e + bebe5a0 commit 7ef1291

12 files changed

Lines changed: 309 additions & 26 deletions

File tree

index.html

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
<!doctype html>
2-
<html lang="en">
2+
<html lang="ko">
33
<head>
44
<meta charset="UTF-8" />
5+
<meta
6+
name="description"
7+
content="실시간 모의투자 트레이딩 시스템. 실시간 거래, 타임머신 투자, AI 시장 브리핑을 제공합니다."
8+
/>
9+
<meta property="og:type" content="website" />
10+
<meta property="og:title" content="WeFin — 과거에서 배우고, 현재에 투자하는 모의투자" />
11+
<meta
12+
property="og:description"
13+
content="실시간 모의투자 트레이딩 시스템. 실시간 거래, 타임머신 투자, AI 시장 브리핑을 제공합니다."
14+
/>
15+
<meta property="og:url" content="https://www.wefin.ai.kr" />
16+
<meta property="og:image" content="https://www.wefin.ai.kr/og-image.png" />
17+
<meta name="twitter:card" content="summary_large_image" />
518
<script>
619
window.global = window
720
;(function () {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"lucide-react": "^1.6.0",
3636
"react": "^19.2.4",
3737
"react-dom": "^19.2.4",
38+
"react-helmet-async": "^3.0.0",
3839
"react-router-dom": "^7.13.2",
3940
"recharts": "^3.8.1",
4041
"sockjs-client": "^1.6.1",

pnpm-lock.yaml

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

public/og-image.png

685 KB
Loading

public/og-image.svg

Lines changed: 121 additions & 0 deletions
Loading

public/robots.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
User-agent: *
2+
Allow: /
3+
Disallow: /account/
4+
Disallow: /settings/
5+
Disallow: /admin/
6+
Disallow: /chat/
7+
Disallow: /payment/
8+
9+
Sitemap: https://www.wefin.ai.kr/sitemap.xml

public/sitemap.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3+
<url>
4+
<loc>https://www.wefin.ai.kr/</loc>
5+
<changefreq>daily</changefreq>
6+
<priority>1.0</priority>
7+
</url>
8+
<url>
9+
<loc>https://www.wefin.ai.kr/stocks</loc>
10+
<changefreq>daily</changefreq>
11+
<priority>0.9</priority>
12+
</url>
13+
<url>
14+
<loc>https://www.wefin.ai.kr/history</loc>
15+
<changefreq>weekly</changefreq>
16+
<priority>0.8</priority>
17+
</url>
18+
<url>
19+
<loc>https://www.wefin.ai.kr/about</loc>
20+
<changefreq>monthly</changefreq>
21+
<priority>0.5</priority>
22+
</url>
23+
<url>
24+
<loc>https://www.wefin.ai.kr/terms</loc>
25+
<changefreq>monthly</changefreq>
26+
<priority>0.3</priority>
27+
</url>
28+
<url>
29+
<loc>https://www.wefin.ai.kr/privacy</loc>
30+
<changefreq>monthly</changefreq>
31+
<priority>0.3</priority>
32+
</url>
33+
</urlset>

src/app/providers/app-providers.tsx

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
22
import type { PropsWithChildren } from 'react'
3+
import { HelmetProvider } from 'react-helmet-async'
34
import { Toaster } from 'sonner'
45

56
import ErrorBoundary from './error-boundary'
@@ -17,31 +18,33 @@ const queryClient = new QueryClient({
1718
function AppProviders({ children }: PropsWithChildren) {
1819
return (
1920
<ErrorBoundary>
20-
<QueryClientProvider client={queryClient}>
21-
{children}
22-
<Toaster
23-
position="top-center"
24-
style={{ zIndex: 9999 }}
25-
toastOptions={{
26-
style: {
27-
borderRadius: '16px',
28-
padding: '12px 20px',
29-
fontSize: '14px',
30-
fontWeight: 600,
31-
background: 'var(--surface)',
32-
color: 'var(--text)',
33-
boxShadow: '0 8px 32px -8px rgba(0,0,0,0.2)',
34-
border: '1px solid var(--line)'
35-
},
36-
classNames: {
37-
success: '!bg-wefin-mint !text-white !border-wefin-mint-deep/30',
38-
error: '!bg-wefin-red !text-white !border-wefin-red/30',
39-
warning: '!bg-wefin-amber !text-white !border-wefin-amber/30'
40-
}
41-
}}
42-
offset={20}
43-
/>
44-
</QueryClientProvider>
21+
<HelmetProvider>
22+
<QueryClientProvider client={queryClient}>
23+
{children}
24+
<Toaster
25+
position="top-center"
26+
style={{ zIndex: 9999 }}
27+
toastOptions={{
28+
style: {
29+
borderRadius: '16px',
30+
padding: '12px 20px',
31+
fontSize: '14px',
32+
fontWeight: 600,
33+
background: 'var(--surface)',
34+
color: 'var(--text)',
35+
boxShadow: '0 8px 32px -8px rgba(0,0,0,0.2)',
36+
border: '1px solid var(--line)'
37+
},
38+
classNames: {
39+
success: '!bg-wefin-mint !text-white !border-wefin-mint-deep/30',
40+
error: '!bg-wefin-red !text-white !border-wefin-red/30',
41+
warning: '!bg-wefin-amber !text-white !border-wefin-amber/30'
42+
}
43+
}}
44+
offset={20}
45+
/>
46+
</QueryClientProvider>
47+
</HelmetProvider>
4548
</ErrorBoundary>
4649
)
4750
}

src/features/news-feed/ui/cluster-detail-content.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { useParams } from 'react-router-dom'
22

3+
import SeoHead from '@/shared/ui/seo-head'
4+
35
import { useClusterDetailQuery } from '../model/use-cluster-detail-query'
46
import { useMarkClusterRead } from '../model/use-mark-cluster-read'
57
import ClusterDetailFooter from './cluster-detail-footer'
@@ -55,6 +57,12 @@ export default function ClusterDetailContent() {
5557

5658
return (
5759
<div className="overflow-hidden rounded-2xl bg-wefin-surface p-4 sm:rounded-3xl sm:p-8">
60+
<SeoHead
61+
title={cluster.title}
62+
description={cluster.summary}
63+
path={`/news/${clusterId}`}
64+
type="article"
65+
/>
5866
<ClusterDetailHeader cluster={cluster} />
5967
<ClusterDetailSections sections={cluster.sections} articleContent={cluster.articleContent} />
6068
<ClusterDetailFooter cluster={cluster} />

0 commit comments

Comments
 (0)