Implemented comprehensive Schema.org structured data across the blog to improve SEO and enable rich snippets in search results.
Changes:
- Created JSON-LD helper component for safe schema rendering
- Added BlogPosting schema to blog posts with:
* Article metadata (headline, description, image, dates)
* Author and publisher information
* Keywords and article sections from tags
- Added BreadcrumbList schema to blog posts for navigation
- Added WebSite and Organization schemas to root layout
* Site-wide identity and branding
* Search action for site search functionality
- Added CollectionPage schema to homepage
* Blog collection metadata
- Added WebPage schema to static pages
* Page metadata with dates and images
Benefits:
- Rich snippets in Google/Bing search results
- Better content understanding by search engines
- Article cards with images, dates, authors in SERPs
- Breadcrumb navigation in search results
- Improved SEO ranking signals
All schemas validated against Schema.org specifications and include proper Chinese language support.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: Table of Contents displayed headings from previously viewed
articles when navigating between posts via client-side routing.
Root cause: PostToc component's useEffect with empty dependency array
only ran once on mount, so it retained stale heading data when React
reused the component instance during navigation.
Solution: Add contentKey prop flow:
- Blog/page routes pass slug to PostLayout
- PostLayout passes contentKey as key prop to PostToc instances
- React remounts PostToc when key changes, rebuilding TOC correctly
Files changed:
- components/post-layout.tsx: Add contentKey prop and key forwarding
- app/blog/[slug]/page.tsx: Pass slug as contentKey
- app/pages/[slug]/page.tsx: Pass slug as contentKey
- Upgraded Next.js to v16, React to v19
- Migrated from contentlayer to contentlayer2
- Migrated to Turbopack by decoupling Contentlayer from webpack
- Updated all page components to handle async params (Next.js 15+ breaking change)
- Changed package.json to type: module and renamed config files to .cjs
- Updated README with current tech stack and article creation instructions
- Fixed tag encoding issue (removed double encoding)
- All security vulnerabilities resolved (npm audit: 0 vulnerabilities)