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
7 changes: 7 additions & 0 deletions .github/workflows/content-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,10 @@ jobs:

- name: Lint image references (non-blocking)
run: pnpm lint:images || echo "[warn] image lint found issues (non-blocking)"

# Block PR if newly added/modified MDX is missing a proper description.
# Old files are grandfathered via lib/seo-description.ts (Layer 1 fallback);
# this check only fires on changed files in the PR (uses GITHUB_BASE_REF diff).
# leetcode/ and _translated.md are exempt — see scripts/check-frontmatter-description.mjs
- name: Check MDX frontmatter description
run: pnpm check:frontmatter
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,6 @@ AGENTS.md

.npmrc
/.env.*

# scripts/generate-descriptions.mjs 的 dry-run / apply 报表(产物,不进 git)
scripts/.descriptions-report.json
8 changes: 7 additions & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,11 @@ pnpm test || exit 1
pnpm check:pnpm-version || true
pnpm check:lockfile || true

# 5) 其余按 lint-staged 处理(如 Prettier)
# 5) 校验新增/修改的 docs MDX 必须有 description(>= 60 字符)
# Bing 2026-05 报告 118 个页面 description 太短,老内容由 lib/seo-description.ts
# 代码层兜底,但新增/修改必须手写,避免再积累低质量 SEO 内容。
# leetcode/ 和 _translated 自动豁免,详见 scripts/check-frontmatter-description.mjs
pnpm check:frontmatter || exit 1

# 6) 其余按 lint-staged 处理(如 Prettier)
pnpm exec lint-staged
34 changes: 30 additions & 4 deletions app/[locale]/docs/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { source } from "@/lib/source";
import { safeJsonLdString } from "@/lib/json-ld";
import { SITE_URL } from "@/lib/site-url";
import { ensureSeoDescription } from "@/lib/seo-description";
import { DocsPage, DocsBody } from "fumadocs-ui/page";
import { notFound } from "next/navigation";
import type { Metadata } from "next";
Expand Down Expand Up @@ -65,12 +66,23 @@ export default async function DocPage({ params }: Param) {
? `${SITE_URL}/${locale}/docs/${slugPath}`
: `${SITE_URL}/${locale}/docs`;

// JSON-LD description 同步走兜底:避免结构化数据里出现空字符串,否则
// Google Rich Results 测试会 warning。与 generateMetadata 里的逻辑一致。
const sectionPathForJsonLd =
(slug ?? []).length > 1 ? (slug ?? []).slice(0, -1) : [];
const articleDescription = ensureSeoDescription({
description: page.data.description,
title: page.data.title,
sectionPath: sectionPathForJsonLd,
locale,
});

// TechArticle: 让 docs 在 Google 搜索结果上更可能展示为技术文章卡片
const articleJsonLd = {
"@context": "https://schema.org",
"@type": "TechArticle",
headline: page.data.title,
description: page.data.description,
description: articleDescription,
url: docUrl,
inLanguage: locale === "en" ? "en-US" : "zh-CN",
publisher: {
Expand Down Expand Up @@ -190,21 +202,35 @@ export async function generateMetadata({ params }: Param): Promise<Metadata> {
"",
);

// SEO description 兜底:page.data.description 可能为 undefined/空/极短
// (96 个 leetcode 题解完全没 description,67 个空,35 个 < 20 字符)。
// 用 ensureSeoDescription 拼 title + 面包屑 + 站点 tagline 补到 80+ 字符,
// 让 Bing/Google 拿到完整摘要而不是从正文随便抓一段。
// sectionPath 取 slug 除末段外的所有段(末段是当前页本身,已在 title 里)。
const slugArr = slug ?? [];
const sectionPath = slugArr.length > 1 ? slugArr.slice(0, -1) : [];
const safeDescription = ensureSeoDescription({
description: page.data.description,
title: page.data.title,
sectionPath,
locale,
});

return {
title: page.data.title,
description: page.data.description,
description: safeDescription,
alternates: { canonical, languages: langs },
openGraph: {
type: "article",
title: page.data.title,
description: page.data.description,
description: safeDescription,
url: canonical,
locale: locale === "en" ? "en_US" : "zh_CN",
},
twitter: {
card: "summary_large_image",
title: page.data.title,
description: page.data.description,
description: safeDescription,
},
};
}
15 changes: 11 additions & 4 deletions app/[locale]/docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hasLocale } from "next-intl";
import { notFound } from "next/navigation";
import { SectionIndex } from "@/app/components/docs/SectionIndex";
import { routing } from "@/i18n/routing";
import { ensureSeoDescription } from "@/lib/seo-description";

/**
* /[locale]/docs 根路由的 landing。Header 的 "文档 / Docs" 链接指到 /docs,
Expand Down Expand Up @@ -49,11 +50,17 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
if (!hasLocale(routing.locales, locale)) notFound();
setRequestLocale(locale);

// 走统一兜底:原文本只 ~60 字符,被 Bing 判定为太短。ensureSeoDescription
// 会自动补足到 80+ 字符,并保持中英分别的 tagline。
return {
title: locale === "en" ? "Docs" : "文档",
description:
locale === "en"
? "Involution Hell community knowledge base — AI, CS, jobs, community shares."
: "Involution Hell 社区知识库 — AI、计算机基础、求职、群友分享等分区总览。",
description: ensureSeoDescription({
description:
locale === "en"
? "Involution Hell community knowledge base — AI, CS, jobs, community shares."
: "Involution Hell 社区知识库 — AI、计算机基础、求职、群友分享等分区总览。",
title: locale === "en" ? "Docs" : "文档",
locale,
}),
};
}
21 changes: 19 additions & 2 deletions app/[locale]/events/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Footer } from "@/app/components/Footer";
import type { EventDetailResponse, EventView } from "../types";
import { InterestButton } from "./InterestButton";
import { sanitizeExternalUrl, sanitizeMediaUrl } from "@/lib/url-safety";
import { ensureSeoDescription } from "@/lib/seo-description";

/**
* /events/[id] 详情页。SSR 拉 /api/events/{id}。
Expand Down Expand Up @@ -57,10 +58,26 @@ interface Param {
export async function generateMetadata({ params }: Param): Promise<Metadata> {
const { id } = await params;
const data = await fetchDetail(id);
if (!data) return { title: `活动 #${id} · Involution Hell` };
if (!data) {
// 没拿到 event 也兜底 description(404 前的过渡态)
return {
title: `活动 #${id} · Involution Hell`,
description: ensureSeoDescription({
title: `活动 #${id}`,
sectionPath: ["events"],
locale: "zh",
}),
};
}
// event.description 由用户/管理员录入,长度不可控;走兜底防短。
return {
title: `${data.event.title} · Involution Hell`,
description: data.event.description || "Involution Hell 社群活动详情。",
description: ensureSeoDescription({
description: data.event.description,
title: data.event.title,
sectionPath: ["events"],
locale: "zh",
}),
};
}

Expand Down
10 changes: 9 additions & 1 deletion app/[locale]/feed/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ import { FeedAuthWrapper } from "@/app/[locale]/feed/components/FeedAuthWrapper"
import type { SharedLinkView, CategorySlug } from "@/app/[locale]/feed/types";
import type { ApiResponse } from "@/app/[locale]/feed/types";
import Link from "next/link";
import { ensureSeoDescription } from "@/lib/seo-description";

export const revalidate = 120;

// 原 description 只有 24 字符(远低于 Bing 推荐的 150-160),统一走 ensureSeoDescription
// 兜底到 80+ 字符。社区分享墙是公开 SEO 页,搜索摘要质量直接影响 CTR。
export const metadata: Metadata = {
title: "社区分享墙 · Involution Hell",
description: "群友精选好文,随手转发,沉淀有价值的信息流。",
description: ensureSeoDescription({
description: "群友精选好文,随手转发,沉淀有价值的信息流。",
title: "社区分享墙",
sectionPath: ["feed"],
locale: "zh",
}),
Comment on lines +26 to +35
};

/**
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/events/coffee-chat.en.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Senior Tech-Industry Engineer Coffee Chat Recap
description: ""
description: "Senior backend engineer shares Australian programmer job search strategies, big company career planning, and platform resources for early-career tech professionals."
date: "2025-11-01"
tags:
- career
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/events/coffee-chat.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 资深科技大厂程序员Coffee Chat回顾
description: ""
description: "资深科技大厂程序员Coffee Chat回顾:澳洲程序员求职与职业规划分享会,聚焦大公司作为职业跳板的核心策略与SRE入门路径,详解K8s自动化项目优先于安全背景的实战建议。适合CS/AI求职者、海外程序员及准备回国发展的技术从业者阅读。"
date: "2025-11-01"
tags:
- career
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/events/event-takeway.en.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Career Events Recap Hub
description: Career Events Recap Introduction Page
description: "Explore career event takeaways on involutionhell.com: interview tips, resume optimization, and role-specific growth insights for job seekers."
date: "2025-10-26"
tags:
- intro
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/events/event-takeway.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 求职活动回放站
description: Career Events Recap Introduction Page
description: "求职活动回放站系统整理社区往期活动精华,涵盖Coffee Chat问答、面试实录与技巧总结、岗位经验分享等核心内容。适合正在求职或准备转行的CS/AI学生与职场新人,通过真实案例拆解与成长路径参考,帮助高效复用社区沉淀的面试与职业发展干货。"
date: "2025-10-26"
tags:
- intro
Expand Down
19 changes: 19 additions & 0 deletions content/docs/career/index.en.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: Career
description: "Involution Hell tech docs — Career section. A one-stop resource hub for the entire CS/AI job search journey: LeetCode grinding strategies, behavioral interview (BQ) and online assessment (OA) tips, plus highlights from community events like Coffee Chat and Mock Interview."
date: "2026-04-18"
docId: crr0001index2026041800000001
lang: en
translatedFrom: zh
translatedAt: 2026-05-11T00:00:00Z
translatorAgent: claude-sonnet-4-6
---

import { SectionIndex } from "@/app/components/docs/SectionIndex";

One-stop content for the job search journey:

- **Interview Prep**: LeetCode grinding, BQ, OA, and Video Interview techniques
- **Events**: Recaps of community events — Coffee Chat, Mock Interview, Career Journey, and more

<SectionIndex root="career" />
2 changes: 1 addition & 1 deletion content/docs/career/index.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Career
description: 求职准备、面试经验、社群活动——从刷题到拿 offer 的全流程。
description: "内卷地狱技术文档站 Career 页面汇总求职全流程资源:涵盖 LeetCode 刷题策略、BQ 行为面试与 OA 在线评估技巧,以及 Coffee Chat、Mock Interview 等社群活动精华。适合正在准备 CS/AI 岗位面试、寻求系统化求职攻略的在校生与转行者。"
date: "2026-04-18"
docId: crr0001index2026041800000001
---
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/interview-prep/bq.en.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Behavioral Interview
description: First page
description: "Master behavioral interviews with 10 universal angles—prepare one story per angle for collaboration, conflict, and client service. For CS/AI job seekers."
date: "2025-09-11"
tags:
- intro
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/interview-prep/bq.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 行为面
description: First page
description: "行为面十题万能思路覆盖合作沟通、领导组织、学习成长与挑战应对四大类,详解Teamwork、Conflict、Leadership、Planning、Multitasking、Learn new skills、Motivation、Challenge、Failure等关键技术点,适合求职面试者、CS/AI从业者及准备行为面(BQ)的候选人阅读。"
date: "2025-09-11"
tags:
- intro
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/interview-prep/interview-tips.en.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Conquering Every Interview Stage | OA Coding Grind, HireVue Score Tricks, and Group Interview Tactics"
description: ""
description: "Master OA coding, HireVue scoring, and group interviews with proven tactics for international students and job seekers facing tough tech interview stages."
date: "2025-09-19"
tags:
- interview-preparation
Expand Down
2 changes: 1 addition & 1 deletion content/docs/career/interview-prep/interview-tips.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "面试阶段逐关击破 | OA刷题血泪史 + VI分数偷看技巧 + 群面套路合集"
description: ""
description: "澳洲IT求职面试全流程攻略:OA刷题血泪史(HackerRank/CodeSignal/SHL平台拆解)、VI视频面评分偷看技巧、群面套路合集。适合在澳留学生、CS/AI求职者、想提升面试通过率的新手。"
date: "2025-09-19"
tags:
- interview-preparation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1004. Max Consecutive Ones III"
description: "LeetCode 1004. Max Consecutive Ones III — sliding window with at most k zeros flipped, using two pointers to track the longest subarray; for intermediate learners."
date: "2022.12.07-01:15"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: 1004.Maximum continuity1Number III Maximum continuity1Number III
description: "LeetCode 1004. 最大连续1的个数 III 题解 — 滑动窗口与双指针解法,核心技巧在于维护窗口内最多翻转 K 个 0,通过动态调整左右指针实现最长连续 1 子数组。适合准备算法面试、刷题进阶的 CS 求职者与 AI 学习者。"
date: "2022.12.07-01:15"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "121. Best Time to Buy and Sell Stock"
description: "LeetCode 121. Best Time to Buy and Sell Stock — DP approach tracking min price and max profit in one pass, O(n) time and O(1) space, for coding interview prep."
date: "2024.01.01 0:00"
tags:
- Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1234. Replace the Substring for Balanced String — Daily Problem"
description: 'LeetCode 1234. Replace the Substring for Balanced String — two-pointer sliding window approach to find minimal substring where outside characters exceed n/4, using frequency counting and the "at most m" trick for O(n) solution. For intermediate algorithm learners.'
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: 1234. Replace the sub -string to get a balanced string One question daily
description: "LeetCode 1234. 替换子串得到平衡字符串 题解 — 使用同向双指针(滑动窗口)维护待替换子串,核心技巧是检查窗口外各字符出现次数是否均不超过 n/4,从而找到最小替换长度。适合备战面试、刷滑动窗口与字符串平衡类题目的算法学习者。"
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1333. Filter Restaurants by Vegan-Friendly, Price, and Distance"
description: "LeetCode 1333. Filter Restaurants by Vegan-Friendly, Price, and Distance — Sort and filter restaurants using list comprehension with lambda for multi-key sorting by rating then ID, for Python developers."
date: "2024.01.01 0:00"
tags:
- Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "142. Linked List Cycle II"
description: "LeetCode 142. Linked List Cycle II — Two-pointer technique to detect cycle entrance using Floyd’s algorithm; find first meeting point, then reset one pointer to head and move both one step until they meet. For developers preparing for coding interviews."
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: 142.Ring linkedII.md
description: "LeetCode 142. 环形链表 II 题解 — 使用快慢双指针检测链表环入口,核心技巧是相遇后重置慢指针到头节点、同步步进直至再次相遇。适合准备算法面试、刷链表题型的 CS 求职者与 LeetCode 学习者阅读。"
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "146. LRU Cache"
description: "LeetCode 146. LRU Cache — Simulates LRU with a dictionary for O(1) get/put; no linked list needed. For developers learning caching strategies."
date: "2024.01.01 0:00"
tags:
- Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1545. Find Kth Bit in Nth Binary String"
description: "LeetCode 1545. Find Kth Bit in Nth Binary String — recursive approach using string length rules and bit inversion to locate the kth bit without building the full string, for intermediate algorithm learners."
date: "2026.03.04 00:46"
tags:
- Leetcode
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1653. Minimum Deletions to Make String Balanced"
description: "LeetCode 1653. Minimum Deletions to Make String Balanced — DP and stack-free counting with two passes, tracking 'a' and 'b' counts to minimize deletions for CS learners."
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: 1653. The minimum number of times to balance the string balance.md
description: "LeetCode 1653. 使字符串平衡的最少删除次数题解 — 通过动态规划与状态机思想,将字符映射为数值((c - 'a') * 2 - 1)消除分支预测失败,提升执行效率。详解如何用一次遍历与最小前缀/后缀计数,计算删除最少字符使字符串中所有 a 在 b 之后。适合备战面试、追求高性能解法的 LeetCode 刷题者与算法竞赛选手。"
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1664. Ways to Make a Fair Array — Daily Problem"
description: "LeetCode 1664. Ways to Make a Fair Array — Use prefix/suffix sums to track even/odd index parity shifts after deletion, for O(n) solution. Ideal for intermediate coders learning DP optimization."
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: 1664. Number of schemes to generate balance numbers One question daily
description: "LeetCode 1664. 生成平衡数组的方案数 题解 — 使用动态规划与奇偶性分析,核心技巧是预处理前缀奇偶和与后缀奇偶和,在枚举删除每个元素时 O(1) 判断剩余数组奇偶下标和是否相等。适合准备算法面试、刷 LeetCode 中等题的求职者和 CS 学生。"
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "1825. Find MK Average"
description: "LeetCode 1825. Find MK Average — Maintain three multisets for smallest k, middle, and largest k elements; track middle sum for O(1) average queries. Ideal for engineers mastering data structure design."
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: 1825. Seek out MK average value
description: "LeetCode 1825. 求出 MK 平均值 题解 — 使用三个 multiset 维护滑动窗口中的最小值、中间值和最大值集合,通过平衡插入与删除操作保持 lower 和 upper 各含 k 个元素,并实时维护 middle 的元素和以 O(log n) 计算剔除首尾 k 个后的平均值。适合准备系统设计面试或需要掌握有序集合与滑动窗口技巧的算法学习者。"
date: "2024.01.01 0:00"
tags:
- - Python
Expand Down
Loading
Loading