Skip to content

Drop unused MDX deps and inline use-scramble#74

Merged
lwwmanning merged 1 commit into
mainfrom
claude/strange-payne-74561c
May 13, 2026
Merged

Drop unused MDX deps and inline use-scramble#74
lwwmanning merged 1 commit into
mainfrom
claude/strange-payne-74561c

Conversation

@lwwmanning
Copy link
Copy Markdown
Contributor

Summary

First-principles audit of the runtime dependency list. Four packages dropped, one decorative hook inlined.

Package Why it's removable
react-markdown Zero imports anywhere. The blog pipeline is Velite/MDX → MDXRenderer.tsx, which evaluates compiled JSX. react-markdown plays no role.
@next/mdx Not wired into next.config.mjs (no withMDX() wrapper). No .mdx files under app/ for Next to route. Velite handles MDX compilation entirely.
@mdx-js/react Zero direct imports. Typically a peer of @next/mdx's React provider system, which isn't used here. velite depends on @mdx-js/mdx (the compiler), not @mdx-js/react (the runtime).
use-scramble Used in one component (src/components/link/index.tsx). Replaced with a ~50-line requestAnimationFrame loop. Behavior parity preserved: left-to-right reveal, 4-char scramble window, fires on hover/touch, whitespace passes through unscrambled.

Peer-dependency verification: nothing else in the tree requires these four as peers. velite installs cleanly.

One non-obvious gotcha in the scramble inlining

The original use-scramble setup bound the animation to onMouseOver. That doesn't survive a hand-rolled implementation: mouseover re-fires every time the element's textContent mutates (because the new text node is a "different child" under the cursor), which would restart the animation in an infinite loop. Switched to onMouseEnter (single fire per real entry) plus an if (frameRef.current !== null) return in-flight guard. New regression test in tests/smoke.spec.ts asserts the animation actually settles, so the failure mode can't sneak back in.

What's not in this PR

  • mdast-util-to-hast override stays. With react-markdown gone there are now two transitive paths (shiki/rehype-pretty-code, velite/@mdx-js/mdx) instead of three, but both still resolve to a pre-fix version without the override. CLAUDE.md rationale updated accordingly.
  • GHSA-w5hq-g745-h8pq audit-ignore stays. It's blocked by @lhci/cli's transitive uuid@8.3.2, which this PR doesn't touch.

Test plan

  • bun installRemoved: 4, lockfile clean (-14 lines)
  • bun pm ls --all | grep -E "react-markdown|@mdx-js/react|@next/mdx|use-scramble" returns nothing
  • bun pm ls --all | grep mdast-util-to-hast shows only >=13.2.1 (override still effective)
  • bun audit --ignore=GHSA-w5hq-g745-h8pq --ignore=GHSA-52f5-9888-hmc6 clean
  • bun run check clean
  • bun run build succeeds (all 18 static pages generated)
  • bun run typecheck clean
  • bun run verify — 17/17 (sitemap, robots, RSS x3, OG, canonicals, theme parity, /api/subscribe, internal links)
  • bun run test:e2e — 18/18 (desktop + mobile), including new footer › custom Link scramble settles back to original on hover regression test

First-principles audit of the runtime dep list. Four packages removed:

- react-markdown: zero imports anywhere in the codebase. Velite/MDX is
  the actual blog pipeline; this was dead weight.
- @next/mdx: not wired into next.config.mjs (no withMDX() wrapper) and
  no .mdx routes under app/. Velite compiles MDX to JSX code that
  MDXRenderer.tsx evaluates against react/jsx-runtime.
- @mdx-js/react: zero direct imports. Typically a peer of @next/mdx's
  React provider system, which isn't used here. velite depends on
  @mdx-js/mdx (the compiler), not @mdx-js/react (the runtime).
- use-scramble: used in exactly one component (custom Link wrapper).
  Inlined as a ~50-line rAF loop with an in-flight guard and a
  callback ref. Behavior parity preserved: left-to-right reveal,
  4-char scramble window, fires on hover/touch, whitespace passes
  through unscrambled. Switched from onMouseOver to onMouseEnter
  because mouseOver re-fires every time textContent mutates (browsers
  emit it on child-node changes), which would restart the animation
  in an infinite loop.

The mdast-util-to-hast override stays — its two remaining transitive
paths (shiki/rehype-pretty-code and velite/@mdx-js/mdx) still resolve
to a pre-fix version without the override. CLAUDE.md updated to drop
the now-removed react-markdown path from the rationale.

bun audit, lint, typecheck, build, verify (17/17), and Playwright
(18/18 including a new footer-scramble regression test that guards
against the mouseover-textContent-refire loop) all pass.

Signed-off-by: Will Manning <will@willmanning.io>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vortex Ready Ready Preview, Comment May 13, 2026 6:01pm

Request Review

@github-actions
Copy link
Copy Markdown

🔦 Lighthouse audit

URL Perf A11y Best practices SEO Report
/ 🟢 100 🟢 100 🟢 96 🟢 100 report
/blog 🟢 100 🟢 100 🟢 96 🟢 100 report
/blog/btrblocks-compressor 🟢 100 🟢 96 🟢 96 🟢 100 report

Run 25817136267 · 2026-05-13 18:03 UTC

@lwwmanning lwwmanning merged commit 22f9c52 into main May 13, 2026
10 checks passed
@lwwmanning lwwmanning deleted the claude/strange-payne-74561c branch May 13, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant