Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add four topics, fix lint and link graph, prepare for open source - #28

Merged
tornike14 merged 11 commits into
mainfrom
develop
Aug 15, 2026
Merged

Add four topics, fix lint and link graph, prepare for open source#28
tornike14 merged 11 commits into
mainfrom
develop

Conversation

@tornike14

Copy link
Copy Markdown
Owner

Brings main up to date with 11 commits of work. Until now the public default branch and the live site have both been serving an older version of the project.

Content

Four new topics, taking the total to 28 (17 JavaScript, 11 React):

  • Event Delegation — capture/target/bubble phases, stopPropagation, the one-parent-handler pattern
  • Modules & Imports — module graph construction, live bindings, circular dependency handling
  • Error Boundaries — error propagation, getDerivedStateFromError, nested boundaries, recovery
  • useEffect Lifecycle — render/commit/paint/effect timeline, dependency comparison, cleanup timing

Topic pages were also consolidated: theory now renders beneath the visualization on the topic route instead of at a separate /theory URL.

Fixes

  • ComponentTreeDiagram called setState synchronously inside a layout effect, failing react-hooks/set-state-in-effect and leaving lint red. Height now writes straight to the DOM. Verified in the browser against the previous implementation: identical scale factor and viewport height, one fewer render pass.
  • The reconciliation theory page listed only two related topics, both unrelated JavaScript ones. Replaced with five React topics.
  • Four topics had no inbound links from any theory page. Each now has two.
  • Docs still described the deleted /theory routes and the renamed TheoryArticle, so a contributor following them would have built a route that no longer exists.

Open source readiness

  • README rewritten, plus a homepage screenshot and a badge row
  • CONTRIBUTING.md documenting all eight registries a new topic touches
  • CI running lint, build, and a registry integrity check on every push and PR
  • scripts/check-registries.mjs, which catches registry desync that TypeScript cannot, since each registry is independently valid on its own
  • Issue templates, PR template, SECURITY.md, CODE_OF_CONDUCT.md, .env.example
  • Removed a stray worktree gitlink that made fresh clones report a phantom submodule

Verification

npm run verify passes: lint clean, 28 topics registered across all eight registries, production build green at 68 static pages.

…ect Lifecycle topics
Four new topics, two JavaScript and two React, each with a step-by-step
visualization and a full theory page.
- Event Delegation (beginner): capture/target/bubble phases, stopPropagation,
and the one-parent-handler delegation pattern
- Modules & Imports (intermediate): module graph construction, live bindings,
and circular dependency handling
- Error Boundaries (intermediate): error propagation up the tree,
getDerivedStateFromError, nested boundaries, and recovery
- useEffect Lifecycle (beginner): render/commit/paint/effect timeline,
dependency comparison, and cleanup timing
Registered across all eight registries: topic registry, routes, visualization
components, theory content, theory registry, keyword and description maps, and
the selector toolbar set.
ComponentTreeDiagram called setState synchronously inside a layout effect,
which fails the react-hooks/set-state-in-effect rule and left the repo with a
red lint run. Measuring already happens in a layout effect, so the height now
writes straight to the DOM node instead of routing through state. Verified in
the browser: identical scale factor and viewport height to the previous
implementation, with one fewer render pass per measurement.
The reconciliation theory page listed only two related topics, both of them
JavaScript topics unrelated to reconciliation. Replaced with five React topics.
Four topics had no inbound links from any theory page, leaving them dead ends
for readers and for search. Each now has two, added by swapping out the
weakest link where a list was already at the five-entry maximum.
The code and the authoring docs were already in good shape. What was missing
was everything a contributor needs before they can make their first change.
- README rewritten. It listed 7 JavaScript routes and described React as
"coming soon" while 28 topics and 11 React visualizations were shipping.
- CONTRIBUTING.md added. Adding a topic touches eight registries, and missing
one produces a page that half works, so each is listed with its file path.
- CI workflow runs lint, build, and a registry integrity check on every push
and pull request.
- scripts/check-registries.mjs verifies that every topic is registered in all
eight places, that relatedTopicIds hold 3 to 5 valid non-self IDs, that no
topic is left without inbound links, that ExampleSelector topics appear in
the toolbar set, and that no em dash reaches user-facing content. TypeScript
cannot catch these because each registry is independently valid on its own.
- Issue templates for bugs, content corrections, and topic requests, plus a
pull request template carrying the eight-registry checklist.
- SECURITY.md and CODE_OF_CONDUCT.md added.
- .env.example documents the three NEXT_PUBLIC_ variables, which matters for
forks since two of them default to the maintainer's own links.
- package.json gains description, license, repository, engines, and the
check:registries and verify scripts.
Also removes a stray worktree directory that was committed by accident as a
gitlink with no .gitmodules entry, which made fresh clones report a phantom
submodule. Local editor and tooling state is now ignored.
The Analytics and Speed Insights scripts are served from
va.vercel-scripts.com in development, which script-src blocked, so
neither one loaded locally. Add the host to script-src.
connect-src is unchanged: beacons always post same-origin under
/_vercel, and development sends none at all.
Google indexed only 28 of 60 known URLs (14 "crawled, currently not
indexed"), and the split between /topic and /topic/theory was splitting
signals across two thin URLs per concept. GSC showed Google picking
inconsistently between the pair: heap-stack ranked the theory page,
execution-context ranked the visualization page.
Merge theory content into the visualization page, one URL per topic:
- Render theory sections below the visualization via TopicTheorySections
- 308 redirect /javascript/:topic/theory and /react/:topic/theory to the
topic page via next.config redirects
- Delete the [topic]/theory routes and TheoryArticle
- Section headings now carry concept keywords ("What is X in JavaScript?"
instead of "What it is")
- Related topics link to topic pages instead of theory pages
Replace the homepage soft redirect with real content:
- / served 200 with a meta refresh, which Google classified as a
redirect, wasting the strongest URL on the domain
- New HomeLandingPage targets the "javascript visualizer" query cluster
and links all 28 topics
- Add / to the sitemap, drop the removed theory routes
Metadata and structured data:
- Topic titles lead with the concept: "X in JavaScript, Visualized"
- Topic descriptions use the richer theory copy
- Render topic.description as visible text (it was metadata-only)
- Drop FAQPage schema, which has earned no rich results since Google
restricted FAQ results in 2023
- Add Person author to TechArticle
- Category descriptions derive their topic counts from the registry
Deepen heap-stack theory, the closest near-miss to page one at position
16.1 with 318 impressions.
All 31 sitemap URLs now have one h1, a correct self-canonical, a meta
description, and over 300 words. Average page weight went from roughly
150 words to 787.
Link audit found two holes that page-level SEO work does not fix:
- No page linked to the homepage. The sidebar logo pointed at the
active category route, so the new landing page had zero inbound
internal links and was reachable only from the sitemap.
- The JavaScript and React halves of the site were disconnected. The
category switcher is a button with onClick, not a link, and the
sidebar only renders the active category, so /javascript/closures
had 18 internal links and none of them reached React.
Point the sidebar logo at / and add a crawlable link to the opposite
category in the sidebar footer.
Every page now links to the homepage and to both category hubs.
.claude/worktrees holds full checkouts of the repo, including their own
.next build output. ESLint walked into them and reported 2293 problems
from code that is not part of this working tree, so `npm run lint`
failed whenever a worktree existed on disk.
The directory is already gitignored. Ignore it in ESLint too.
Theory now renders on the topic page instead of a separate /theory route, but
the docs still described the old structure. A contributor following them would
have created a route that no longer exists.
- README and CONTRIBUTING no longer promise a page at <route>/theory
- theory-authoring.md points at TopicTheorySections rather than the deleted
TheoryArticle, and drops the claim that a theory URL is statically generated
- topic-authoring.md removes the deleted [topic]/theory entries from its tree
- seo.md corrects the sitemap description, since theory content now shares its
topic's URL and needs no separate entry
The project is entirely visual, and the README described it in prose with no
image. Anyone landing on the repo had to clone and run it to see what it does.
Captured from a production build rather than the dev server, so the Next.js
dev indicator does not appear. Stored as JPEG at 1600px wide, which is 448KB
against 1.25MB for the equivalent PNG with no visible quality loss on the dark
gradients. The image links through to the live site.
A naked visualizejs.com link sitting between two paragraphs gave the most
important link in the project the least visual weight.
Seven badges on a single line: live site, CI status, topic count, Next.js,
React, TypeScript, and license. CI and license read their values live from the
repository rather than being hardcoded.
Two details that matter for how this renders:
- All badges go on one markdown line. GitHub turns single newlines into line
breaks, so one badge per line stacks them vertically down the page.
- The badges sit above the screenshot rather than below it. The screenshot is
1600x1000, tall enough to push anything under it past the fold.
The CI badge tracks develop, since main does not carry the workflow yet and
renders "no status" there. Point it at main once develop is merged.
The workflow now lives on main, so the badge tracks the default branch instead
of develop.
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
visualizejsReadyReadyPreviewAug 15, 2026 9:56pm

@tornike14
tornike14 merged commit 080fc7c into mainAug 15, 2026
6 checks passed
Sign up for freeto 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

@tornike14