Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"dependencies": {
"@radix-ui/react-dialog": "^1.1.15",
"@supabase/supabase-js": "^2.80.0",
"@vercel/analytics": "^1.6.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"framer-motion": "^12.23.24",
Expand Down
34 changes: 34 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@ export default function CategoryWidget({ category }: Props) {

return (
<section className="flex flex-col gap-3 md:flex-row">
{/* 왼쪽: 숫자 위젯 4개 */}
<div className="grid flex-1 grid-cols-2 gap-3 md:grid-cols-4">
<StatWidget
label="Total Posts"
value={String(stats.totalPosts)}
caption="전체 누적"
/>
<StatWidget
label="New This Month"
label="This Month"
value={`+${stats.newThisMonth}`}
caption="이번 달 업데이트"
/>
Expand All @@ -52,7 +51,6 @@ export default function CategoryWidget({ category }: Props) {
/>
</div>

{/* 오른쪽: Monthly Mission */}
<div className="md:w-[260px] ">
<MissionWidget
current={stats.newThisMonth}
Expand Down
2 changes: 2 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Metadata } from "next";
import { ThemeProvider } from "next-themes";
import localFont from "next/font/local";
import "./globals.css";
import { Analytics } from "@vercel/analytics/react";

export const metadata: Metadata = {
title: "B-log",
Expand Down Expand Up @@ -44,6 +45,7 @@ export default function RootLayout({
>
{children}
</ThemeProvider>
<Analytics />
Comment on lines 46 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

<Analytics /> 배치 위치 확인 필요.

현재 <Analytics />ThemeProvider 바깥에 위치해 있습니다. 기능상 문제는 없지만, 일반적으로 컴포넌트 계층 구조의 일관성을 위해 ThemeProvider 내부에 배치하는 것이 더 자연스럽습니다.

다만, Vercel Analytics는 테마 컨텍스트가 필요 없으므로 현재 위치도 정상 동작합니다.

♻️ (선택사항) ThemeProvider 내부로 이동
         <ThemeProvider
           attribute="class"
           defaultTheme="system"
           enableSystem={true}
           storageKey="theme"
         >
           {children}
+          <Analytics />
         </ThemeProvider>
-        <Analytics />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{children}
</ThemeProvider>
<Analytics />
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem={true}
storageKey="theme"
>
{children}
<Analytics />
</ThemeProvider>
🤖 Prompt for AI Agents
In `@src/app/layout.tsx` around lines 46 - 48, The <Analytics /> component is
currently rendered outside the ThemeProvider which breaks component hierarchy
consistency; move the <Analytics /> JSX so it is rendered inside the
ThemeProvider (e.g., after {children} but before closing ThemeProvider) to keep
component structure consistent while leaving functionality unchanged; update the
render in layout.tsx so ThemeProvider wraps children and <Analytics /> together.

</body>
</html>
);
Expand Down
9 changes: 3 additions & 6 deletions src/lib/posts/stats.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { VelitePost } from "./source";
import { getAllPosts } from "./queries";
import { CategoryKey } from "@/config/categories";
import { SERIES_META_BY_CATEGORY } from "@/lib/posts/registry/series.registry";

export interface CategoryStatsParams {
category: CategoryKey;
Expand Down Expand Up @@ -67,12 +68,8 @@ export function getCategoryStats(params: CategoryStatsParams): CategoryStats {
const thisYYYYMM = toYYYYMM(now);
const newThisMonth = catPosts.filter((p) => p.date.startsWith(thisYYYYMM)).length;

const seriesSet = new Set(
catPosts
.map((p) => p.series?.trim())
.filter((s): s is string => Boolean(s))
);
const seriesCount = seriesSet.size;
const seriesMeta = SERIES_META_BY_CATEGORY[category] ?? [];
const seriesCount = seriesMeta.length;
Comment on lines +71 to +72
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "*.ts" -o -name "*.tsx" | grep -E "(registry|series)" | head -20

Repository: swallowedB/b-log

Length of output: 490


🏁 Script executed:

# SERIES_META_BY_CATEGORY 정의 찾기
rg "SERIES_META_BY_CATEGORY" --type ts -B 2 -A 5

Repository: swallowedB/b-log

Length of output: 2900


🏁 Script executed:

# stats.ts의 해당 부분 확인
cat -n src/lib/posts/stats.ts | sed -n '60,85p'

Repository: swallowedB/b-log

Length of output: 961


🏁 Script executed:

# 레지스트리 전체 내용 확인
cat -n src/lib/posts/registry/series.registry.ts

Repository: swallowedB/b-log

Length of output: 1750


🏁 Script executed:

# 포스트 구조에서 series 필드 확인
rg "series" src/lib/posts/source.ts -B 2 -A 2

Repository: swallowedB/b-log

Length of output: 42


🏁 Script executed:

# 실제 포스트 파일에서 series id 사용 확인 (샘플 포스트 찾기)
fd "\.mdx?$" --max-results 10 | head -1 | xargs head -30

Repository: swallowedB/b-log

Length of output: 1121


🏁 Script executed:

# velite 설정이나 포스트 스키마 확인
rg "series" src/lib/posts -B 2 -A 2 --type ts | head -40

Repository: swallowedB/b-log

Length of output: 2005


🏁 Script executed:

# 포스트 저장 위치 찾기
fd -t f -e md -e mdx | head -5

Repository: swallowedB/b-log

Length of output: 107


🏁 Script executed:

# 포스트 메타데이터 스키마 확인 (velite)
rg "schema\|collection" velite.config -A 5 -B 2 2>/dev/null || rg "export.*Post" src/lib/posts -A 10 | head -50

Repository: swallowedB/b-log

Length of output: 2676


🏁 Script executed:

# VelitePost 타입 정의 확인
rg "VelitePost\|posts:\|collection" -A 15 | grep -A 15 "posts\|VelitePost" | head -60

Repository: swallowedB/b-log

Length of output: 42


🏁 Script executed:

# velite.config 파일 찾기
fd "velite" -name "*.config.*" -o -name "velite.ts" -o -name "velite.js"

Repository: swallowedB/b-log

Length of output: 290


🏁 Script executed:

# 실제 포스트 파일 확인 (frontmatter에 series 있는지)
cat content/posts/INSIGHT/velite-test.mdx | head -30

Repository: swallowedB/b-log

Length of output: 700


🏁 Script executed:

# getSeriesByIdAndCategory 함수 확인 - 대소문자 처리 확인
rg "getSeriesBy\|seriesId" src/lib/posts -B 3 -A 8 | head -60

Repository: swallowedB/b-log

Length of output: 42


🏁 Script executed:

# 모든 포스트에서 사용된 series 값 추출 (대소문자 확인)
rg "^series:" content/posts -h | sort | uniq -c

Repository: swallowedB/b-log

Length of output: 10375


🏁 Script executed:

# 레지스트리의 모든 series id 확인
rg "id:" src/lib/posts/registry/series.registry.ts | grep -o '"[^"]*"' | sort | uniq

Repository: swallowedB/b-log

Length of output: 119


🏁 Script executed:

# posts 폴더의 모든 .mdx 파일에서 series 필드 확인
find content/posts -name "*.mdx" -exec grep -h "^series:" {} \; | sort | uniq -c

Repository: swallowedB/b-log

Length of output: 84


🏁 Script executed:

# 쿼리에서 series 필터링 로직 확인
rg "filterByS\|filterSeries\|series.*filter" src/lib/posts -B 2 -A 8

Repository: swallowedB/b-log

Length of output: 42


🏁 Script executed:

# queries.ts에서 시리즈 필터링 로직 전체 확인
cat -n src/lib/posts/queries.ts | sed -n '1,150p'

Repository: swallowedB/b-log

Length of output: 2483


🏁 Script executed:

# 포스트 소스 정의 및 시리즈 필드 정규화 확인
cat src/lib/posts/source.ts

Repository: swallowedB/b-log

Length of output: 181


🏁 Script executed:

# velite config 또는 post schema 확인
fd -type f \( -name "*.config.ts" -o -name "*.config.js" \) | xargs grep -l "posts\|velite" 2>/dev/null

Repository: swallowedB/b-log

Length of output: 232


🏁 Script executed:

# 시리즈 관련 모든 대소문자 처리 확인
rg "toLowerCase\|toUpperCase\|series" src/lib/posts -i -B 2 -A 2 | grep -A 5 -B 5 "series"

Repository: swallowedB/b-log

Length of output: 42


🏁 Script executed:

# velite 설정 파일 찾기
find . -name "velite.config.*" -o -name "velite.ts"

Repository: swallowedB/b-log

Length of output: 78


🏁 Script executed:

# 포스트 schema 정의 확인 (# site prefix 찾기)
rg "#site" src -B 3 -A 3 | head -40

Repository: swallowedB/b-log

Length of output: 277


🏁 Script executed:

# 포스트 필드 검사 (series 포함)
rg "series\|category\|draft" src/lib/posts/source.ts -B 1 -A 1

Repository: swallowedB/b-log

Length of output: 42


🏁 Script executed:

# velite.config.ts 파일 확인
cat velite.config.ts

Repository: swallowedB/b-log

Length of output: 2005


🏁 Script executed:

# 모든 포스트 파일에서 series 필드값 추출 (확인)
find content/posts -name "*.mdx" -exec grep -h "^series:" {} \;

Repository: swallowedB/b-log

Length of output: 76


시리즈 ID 대소문자 불일치로 인한 조회 실패 발생

현재 코드에서 발견된 문제들:

  1. 레지스트리 등록 누락 시 카운트 제외 (의도된 동작): seriesCount = SERIES_META_BY_CATEGORY[category].length는 레지스트리 기반 카운트이므로, 포스트에 있지만 레지스트리에 미등록된 시리즈는 집계되지 않습니다. 이것이 의도된 설계라면 명확히 문서화하면 좋겠습니다.

  2. 긴급: 시리즈 ID 매칭 실패: velite.config.ts에서 series 필드를 capitalizeFirst() 변환하므로 포스트는 "Nextjs"(대문자)가 되지만, 레지스트리는 id: "nextjs"(소문자)로 정의되어 있습니다. 결과적으로 getSeriesMeta()s.id === seriesId 비교가 실패하며, series 기반 포스트 필터링 및 조회가 정상 작동하지 않습니다.

레지스트리의 모든 시리즈 ID를 capitalizeFirst() 형식으로 통일하거나, 조회 시 toLowerCase()를 적용하여 대소문자를 정규화해야 합니다.

🤖 Prompt for AI Agents
In `@src/lib/posts/stats.ts` around lines 71 - 72, The series lookup is failing
due to case mismatch between registry IDs and post-config transformed IDs:
normalize casing during lookup instead of relying on registry changes; update
getSeriesMeta (and any code referencing SERIES_META_BY_CATEGORY or the s.id ===
seriesId comparison) to compare a normalized form (e.g., convert both s.id and
seriesId to toLowerCase() or apply a shared normalize function) so seriesCount
and series-based filtering use the same canonical casing as capitalizeFirst in
velite.config.ts.


const recentCount = catPosts.filter((p) =>
isWithinLastNDays(p.date, now, activityWindowDays)
Expand Down
Loading