I Built 2 Browser Puzzle Games from Scratch This Week ๐ฎ
As part of my ongoing project โ 7x.games โ I'm building 150+ original,
SEO-optimized browser games. This week I shipped two puzzle games:
- ๐งช Color Sort Puzzle โ pour colored liquids between test tubes to sort them by color
- ๐งฑ Block Blast โ place Tetris-style blocks on an 8ร8 grid, clear rows & columns
No game engines. No canvas libraries. Just React, and CSS.
Here's what I learned building both.
๐งช Color Sort Puzzle
The mechanic seems trivial but the solver logic is not.
The key challenge was level validation โ generating a solvable puzzle
every time. I built a backtracking solver that simulates valid pour sequences
before presenting a level to the player.
// A pour is valid only if:
// - Source tube is not empty
// - Target tube is not full
// - Top color of source matches top color of target (or target is empty)
const isValidPour = (from, to) => {
if (from.length === 0) return false
if (to.length === TUBE_SIZE) return false
if (to.length > 0 && to[to.length - 1] !== from[from.length - 1]) return false
return true
}
Other interesting bits:
- Undo stack with full state snapshots
- Auto-win detection after each pour
- 50+ difficulty-scaled levels generated algorithmically
๐งฑ Block Blast
This one was trickier on the interaction side.
Drag-and-Drop with Proximity Snapping
Standard drag-and-drop maps your cursor to the grid. But on a crowded board,
being 1px off means you miss the gap entirely.
I implemented a 3ร3 proximity search โ the game scans a neighborhood
around your finger and snaps to the closest valid placement:
for (let dr = -1; dr <= 1; dr++) {
for (let dc = -1; dc <= 1; dc++) {
const r = baseRow + dr
const c = baseCol + dc
if (canPlaceBlock(grid, shape, r, c)) {
const dist = Math.sqrt(dr * dr + dc * dc)
if (dist < minDistance) {
minDistance = dist
bestPos = { row: r, col: c }
}
}
}
}
This made the game feel 10x more playable on mobile immediately.
Web Audio Sound Effects โ Zero Dependencies
Instead of loading audio files, I synthesized all sounds via the Web Audio API:
const playSound = (type) => {
const ctx = new AudioContext()
const osc = ctx.createOscillator()
const gain = ctx.createGain()
osc.connect(gain)
gain.connect(ctx.destination)
if (type === 'clear') {
osc.type = 'triangle'
osc.frequency.setValueAtTime(523.25, ctx.currentTime) // C5
osc.frequency.linearRampToValueAtTime(1046.50, ctx.currentTime + 0.3) // C6
gain.gain.setValueAtTime(0.2, ctx.currentTime)
gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + 0.3)
osc.start()
osc.stop(ctx.currentTime + 0.3)
}
}
Three sounds (place, clear, game over) โ 0 bytes of audio assets.
Mobile Scroll Freeze During Drag
The tricky part: you want the page to scroll normally, but freeze the moment
the user grabs a block.
React's synthetic touch events are passive by default, so preventDefault
doesn't work inside them. The fix: register a non-passive listener on
mount using a ref that updates synchronously:
const isDraggingRef = useRef(false)
useEffect(() => {
const blockScroll = (e) => {
if (isDraggingRef.current && e.cancelable) e.preventDefault()
}
// { passive: false } is KEY โ allows preventDefault to work
window.addEventListener('touchmove', blockScroll, { passive: false })
return () => window.removeEventListener('touchmove', blockScroll)
}, [])
// Then on touchStart of a block:
isDraggingRef.current = true // synchronous โ no state lag
Using useState here would fail because the state update is async โ
the browser already starts scrolling before React re-renders.
SEO Integration
Both games are pre-rendered static pages in Next.js with:
- Full
metadataobject + OpenGraph tags inlayout.js -
VideoGame+FAQPageJSON-LD structured data vianext/script - Registered in
sitemap.xmlautomatically via the games registry - Long-form strategy articles on each game page for topical authority
What's Next
I'm continuing to build original games for 7x.games โ the goal is 150+
fully SEO-optimized, original browser games. Each game is a standalone
Next.js static page with its own schema, metadata, and content strategy.
๐ Play both games:
- Color Sort โ https://7x.games/games/color-sort
- Block Blast โ https://7x.games/games/block-blast
๐ Follow the build: https://www.instagram.com/buntynamberdar
Drop a โค๏ธ if you found the non-passive touch trick useful โ took me longer than I'd like to admit to figure that one out! ๐
United States
NORTH AMERICA
Related News
What Does "Building in Public" Actually Mean in 2026?
19h ago
The Agentic Headless Backend: What Vibe Coders Still Need After the UI Is Done
19h ago
Why Iโm Still Learning to Code Even With AI
21h ago
I gave Claude a persistent memory for $0/month using Cloudflare
1d ago
NYT: 'Meta's Embrace of AI Is Making Its Employees Miserable'
1d ago