If you grew up in India (or navigated any high-stakes school system), you know this nightmare:
You finish 10th or 12th grade. Everyone tells you there are only three paths: Engineering, Medical, or Commerce.
When you search online for alternative routes, diploma options, or entrance exams, you get hit with:
- 5,000-word SEO blogs written solely for ad revenue.
- Pushy coaching institute lead-generation forms.
- Zero clarity on prerequisites, durations, or lateral entry routes.
I wanted to fix this with a single visual premise: Education and careers are trees, not essays.
So I built PathTree — a free, lightweight, zoomable canvas that maps out degrees, competitive exams, vocational tracks, and backup branches interactively.
Here is the tech breakdown, the design decisions, and the hardest D3 layout bugs I had to solve.
The Tech Stack
I deliberately avoided heavy frameworks (React/Next.js) for this project:
- Engine: Custom Vanilla JavaScript (ES6+)
-
Graph & Hierarchy Layout: D3.js (
d3-org-chart+d3-flextree+d3-zoom) - Styling: Tailwind CSS + Vanilla CSS custom properties (for instant light/dark theme switching)
- Performance Target: Sub-second First Contentful Paint (FCP) and smooth 60fps panning across hundreds of nodes.
3 Technical Challenges I Faced
1. The "Violent Jump" Problem on Branch Expansion
In standard tree visualizers, when a node with ~25 children (like B.Tech / B.E.) expands:
- The layout engine (
d3-flextree) recalculates node coordinates relative to the root(0, 0). - The default chart engine calls an auto-center
.fit()to frame all the newly spawned children.
The result? The entire tree violently jumped across the screen, throwing the user off their focal point.
The Fix:
I implemented an anchor stabilization system that runs during the layout phase:
- Capture the exact screen viewport coordinates
(x, y)of the clicked card right before expansion viagetBoundingClientRect(). - Disable the default auto-center behavior (
setActiveNodeCentered(false)). - Immediately counter-adjust D3's zoom transform by the exact coordinate difference
(-dx, -dy)across subsequent animation frames:
const currentTransform = d3.zoomTransform(svg.node());
const adjusted = d3.zoomIdentity
.translate(currentTransform.x - dx, currentTransform.y - dy)
.scale(currentTransform.k);
svg.call(chart.zoomBehavior().transform, adjusted);
Now, clicking + on any node pins that exact card to the screen while its children bloom out organically.
2. Information Overload: Multi-Level Sibling Grouping
Displaying 300+ career paths simultaneously creates massive cognitive clutter.
To solve this, I built a Group Current Level feature:
- When looking at a specific branch (e.g., Computer Science), users can right-click and group all other sibling branches into a compact
[ 15 other paths ]summary capsule. - Users can now collapse multiple sibling clusters independently across different parent levels without disrupting the overall pathway structure.
3. Lateral Entry & Multi-Parent Traversal
Education isn't a strict acyclic tree. A student can reach a B.Tech degree through:
- 12th PCM → JEE Main / CET → B.Tech Year 1
- 10th → 3-Year Polytechnic Diploma → Lateral Entry into B.Tech Year 2
To represent these dual entry points without tangling the visual hierarchy into a messy spaghetti graph, I designed custom node badges that render alternative parents dynamically and link back to their originating pathways.
Try it Out
The project is live, responsive, and completely free to use:
🔗 Live App: https://pathtree.in
🌲 Education Tree: https://pathtree.in/education
🎨 Skills & Vocations: https://pathtree.in/skills
What I'd Love Feedback On:
- UX & Gestures: How does the canvas panning, zooming, and context menu feel on your machine/trackpad?
- Missing Nodes: What lesser-known degrees, state exams, or vocational routes do you think are missing?
- Architecture: Would you have handled multi-parent relationships differently in D3?
Drop your thoughts and critiques in the comments below!
Top comments (0)