βœ… Refactor Plan for Markdown Anchor Linking 🧠 1. Understand the Problem [link](#heading) links rely on corresponding HTML elements having id="heading". marked.js by default doesn’t add id attributes to headings unless configured. Your headings might be missing ids or may not match the expected format (e.g., space vs. hyphen mismatch). --- 🧱 2. Refactor Outline πŸ”§ Step 1: Customize Marked Renderer Use a custom Renderer in marked.js to automatically generate slugified ids for headings: import { marked } from "marked"; import slugify from "slugify"; const renderer = new marked.Renderer(); renderer.heading = (text, level) => { const slug = slugify(text, { lower: true, strict: true }); return `${text}`; }; marked.setOptions({ renderer }); > βœ… You can use slugify or write your own slug generator if needed. --- 🧩 Step 2: Normalize Anchor Links in Markdown Ensure links like [My Paragraph](#my-paragraph) are slugified the same way as the ids: Ensure slugify rules match exactly with those used in the heading renderer. If links are auto-generated or user-written, you may want to validate or transform them in your rendering pipeline. --- πŸ§ͺ Step 3: Test Scroll Behavior If scrolling doesn't work as expected, make sure your links are: Properly rendered as ... The target heading exists in the DOM at time of click (no lazy-loading issues). Check for any custom scroll behavior in your layout that may interfere (e.g., smooth scroll or offset handling for sticky headers). --- πŸ’‘ Optional Improvements βž• Add Smooth Scrolling In _app.tsx or layout file: html { scroll-behavior: smooth; } πŸ›‘ Handle Scroll Offset (if using fixed/sticky headers) Add a little scroll offset with a custom scroll handler: useEffect(() => { const handler = (e: any) => { if (e.target.hash) { e.preventDefault(); const id = e.target.hash.slice(1); const element = document.getElementById(id); if (element) { const yOffset = -80; // adjust if you have a sticky header const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset; window.scrollTo({ top: y, behavior: 'smooth' }); } } }; document.querySelectorAll('a[href^="#"]').forEach((el) => el.addEventListener('click', handler) ); return () => { document.querySelectorAll('a[href^="#"]').forEach((el) => el.removeEventListener('click', handler) ); }; }, []); --- πŸ“ 3. Folder/File Structure (Suggested) /lib markdown.ts # marked.js config and renderer /pages /blog/[slug].tsx # uses markdown.ts to render content --- βœ… Summary Checklist Step Task Status 1 Add custom heading renderer in marked.js ⬜ 2 Ensure consistent slugification ⬜ 3 Fix anchor tag rendering in links ⬜ 4 Add smooth scrolling / offset scroll fix ⬜ 5 Test across multiple headings & links ⬜ ---