Understand algorithms by watching them run — step-by-step animated visualizations for every major LeetCode problem, with multiple approaches and code in your language of choice.
CodeVisualizer is an open-source platform where you can see how algorithms work, not just read about them. Every problem comes with:
- Animated step-by-step visualization — play, pause, step through, and control speed
- Multiple approaches — Brute Force → Optimal, with clear tradeoffs
- Code in every major language — Python, TypeScript, Java, C++, Go
- Plain English explanation — intuition first, complexity second
Built with Next.js 15 App Router, deployed globally on Cloudflare Pages.
| # | Problem | Difficulty | Tags |
|---|---|---|---|
| 1 | Two Sum | Easy | Array, Hash Map |
| 704 | Binary Search | Easy | Binary Search |
| 21 | Merge Two Sorted Lists | Easy | Linked List |
| 102 | Binary Tree Level Order | Medium | BFS, Tree |
| 15 | 3Sum | Medium | Two Pointers |
| ... | more added regularly |
Don't see your problem? Request it or contribute it yourself.
| Layer | Choice | Why |
|---|---|---|
| Framework | Next.js 15 App Router | Static export, fast routing |
| Animations | Framer Motion | Smooth, controllable step animations |
| Code highlighting | Shiki | Build-time, zero client JS |
| Styling | Tailwind CSS | Contributor-friendly utility classes |
| Prose | MDX | Rich explanations with embedded components |
| Search | Fuse.js | Fuzzy client-side search, no backend |
| Package manager | Bun | Fast installs |
| Deployment | Cloudflare Pages (OpenNext) | Global edge, free tier |
- Bun v1.0+
- Node.js 20+
# Clone the repo
git clone https://github.com/SH20RAJ/codevisualiser.git
cd codevisualiser
# Install dependencies
bun install
# Start dev server
bun run devOpen http://localhost:3000 to see it.
To test exactly how it'll behave on Cloudflare Pages before deploying:
bun run previewbun run deployThis builds the app with OpenNext and deploys to your Cloudflare Pages project via Wrangler.
codevisualiser/
├── src/
│ └── app/
│ ├── page.tsx ← Homepage
│ ├── problems/
│ │ ├── page.tsx ← Problem list + filters
│ │ └── [slug]/page.tsx ← Problem detail (viz + code)
│ └── tags/[tag]/page.tsx ← Problems by topic
│
├── components/
│ ├── ui/ ← CodeBlock, Tabs, Badges, StepController
│ ├── visualizations/ ← One folder per problem
│ │ ├── _base/ ← Reusable primitives (ArrayViz, TreeViz…)
│ │ ├── two-sum/index.tsx
│ │ └── binary-search/index.tsx
│ └── layouts/
│
├── data/
│ ├── problems/ ← Typed TS file per problem
│ │ ├── two-sum.ts
│ │ └── binary-search.ts
│ ├── index.ts ← Problem registry
│ ├── schema.ts ← TypeScript interfaces
│ └── categories.ts
│
├── content/
│ └── problems/ ← MDX explanation per problem
│ ├── two-sum.mdx
│ └── binary-search.mdx
│
├── next.config.ts
├── open-next.config.ts
└── wrangler.jsonc
Contributions are the heart of this project. Adding a new problem is intentionally straightforward — you only need to touch 3 files.
Step 1 — Data file (data/problems/[slug].ts)
Define the problem metadata, all approaches, and code snippets for every language:
import type { Problem } from '../schema'
const problem: Problem = {
id: 1,
slug: 'two-sum',
title: 'Two Sum',
difficulty: 'Easy',
tags: ['Array', 'Hash Table'],
leetcodeUrl: 'https://leetcode.com/problems/two-sum/',
approaches: [
{
name: 'Brute Force',
timeComplexity: 'O(n²)',
spaceComplexity: 'O(1)',
intuition: 'Check every pair of numbers until you find ones that sum to target.',
codes: [
{
language: 'python',
code: `def twoSum(nums, target):
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]`,
},
// add more languages...
],
},
{
name: 'Hash Map',
timeComplexity: 'O(n)',
spaceComplexity: 'O(n)',
intuition: 'Store each number\'s index in a map; for each number check if its complement already exists.',
codes: [ /* ... */ ],
},
],
visualizationComponent: 'TwoSumViz',
hasVisualization: true,
}
export default problemStep 2 — Visualization component (components/visualizations/[slug]/index.tsx)
Use the base primitives and the useVizStepper hook — you only need to implement buildSteps():
import { ArrayViz, HashMapViz } from '../_base'
import { useVizStepper } from '@/lib/useVizStepper'
import StepController from '@/components/ui/StepController'
export function TwoSumViz() {
const steps = buildSteps([2, 7, 11, 15], 9)
const { step, controls } = useVizStepper(steps)
return (
<div className="space-y-4">
<ArrayViz array={step.array} highlights={step.highlights} />
<HashMapViz map={step.hashMap} />
<p className="text-sm text-muted">{step.description}</p>
<StepController {...controls} total={steps.length} />
</div>
)
}
function buildSteps(nums: number[], target: number) {
// Return an array of step snapshots that the stepper will play through
// Each step: { array, highlights, hashMap, description }
}Step 3 — Explanation prose (content/problems/[slug].mdx)
Write the explanation in MDX. You can use standard markdown plus any component from components/ui/:
## Intuition
The naive approach checks every pair — that's O(n²). But we only need to check each number once if we store what we've already seen.
## The Hash Map insight
For each number `x`, we need `target - x`. If we store every number we've visited in a hash map...
<Callout type="tip">
The key insight: instead of looking forward for the complement, look backward — it might already be in the map.
</Callout>Step 4 — Register it in data/index.ts:
import twoSum from './problems/two-sum'
export const problems = [
twoSum,
// your new problem here
]That's it. Open a PR and it's live.
- Keep visualizations accessible — every animation must have a step-through mode (no auto-play-only)
- Code snippets should be idiomatic for each language, not just translated from Python
- Explanations should start with intuition, not with code
- If a problem has multiple valid approaches, include all of them
- Test locally with
bun run previewbefore submitting
See CONTRIBUTING.md for the full guide including PR checklist and code style.
Open an issue using the Problem Request template. Include the LeetCode problem number, link, and why a visualization would be especially helpful for it.
MIT — see LICENSE for details.
Built by @SH20RAJ. If this helped you crack an interview or finally understand binary search, consider starring the repo.