@tom_doerr: Builds a sun-bleached Mediterranean island in the browser by placing 75+ painterly assets on a 14x14 isometric grid. ht…
Summary
A browser-based creative tool for building sun-bleached Mediterranean islands using an isometric grid with 75+ painterly assets, available as an open-source project on GitHub.
View Cached Full Text
Cached at: 08/26/26, 09:50 AM
Builds a sun-bleached Mediterranean island in the browser by placing 75+ painterly assets on a 14x14 isometric grid. https://github.com/boona13/mykonos-island-voxels…
boona13/mykonos-island-voxels
Source: https://github.com/boona13/mykonos-island-voxels
Mykonos Island Voxels
A browser-based isometric island builder with the soft, sun-bleached Mediterranean look of Mykonos: cobalt-blue domes on whitewashed walls, bougainvillea spilling over stone, olive trees, windmills, narrow cobble paths, and a sea you can carve with a click.
It’s a small, self-contained creative toy — drop blocks on a 14×14 grid and a tiny village builds itself in front of you. There’s no goal, no resource grind, no scoring; just the puzzle-piece pleasure of arranging things until they look right.
🌐 Play it: https://mykonos-island-voxels.netlify.app

Features
- Click-to-build isometric grid. Pick an asset from the right-side palette, click a cell, and it pops in with an elastic placement animation.
- One-click “Fill with grass” to carpet the island and start arranging in seconds.
- 75+ painterly assets organised into terrain, nature, props, water, and buildings — chapels, windmills, two-story villas, cypress, olive trees, agave, wells, lanterns, fences, bridges, and more.
- Touch-first mobile UI. Tap to place, long-press to erase, drag to brush, two-finger pinch and pan. Layout adapts from desktop down to small phones with safe-area insets for the iPhone notch.
- High-fidelity asset pipeline. Source PNGs are pre-rendered at 6× display resolution at load time, baked into high-DPI cached layers, then composited per frame so the canvas stays crisp at every zoom on every screen density.
- Auto-save. Your island is persisted to
localStorageand re-loaded on the next visit. - Tasteful sound design. Distinct placement sounds for water, stone, wood, small vegetation, large vegetation, and UI clicks, with debounced overlap so brush-painting doesn’t flood the bus.
- Pure ES modules. No bundler, no transpiler, no
node_modules— openindex.htmland it runs.
Controls
Mouse + keyboard
| Input | Action |
|---|---|
| Click | Place selected asset |
| Drag | Brush-place across cells |
| Right click | Erase tile |
| Right drag | Brush-erase |
| Shift + drag | Pan camera |
| Scroll wheel | Zoom |
H / V | Flip the placement preview |
E | Toggle erase mode |
G | Toggle grid overlay |
1–5 | Switch palette categories |
S / R | Save / reset |
Touch
| Gesture | Action |
|---|---|
| Tap | Place selected asset |
| Drag | Brush-place across cells |
| Long-press (~420 ms) | Erase the tile under your finger |
| Two-finger pinch | Zoom |
| Two-finger drag | Pan camera |
Run it locally
The project is plain HTML / CSS / ES modules — there’s no build step
required to develop on it. Because browsers refuse to load ES modules
from file:// URLs, you do need to serve it over HTTP. Pick whichever
of these is easiest:
# any one of these from the project root:
python3 -m http.server 8000
npx serve .
npx http-server -c-1 .
Then open http://localhost:8000.
Deploy
The site is deployed to Netlify. The included netlify.toml and
netlify-build.mjs produce a clean dist/ folder containing only the
runtime files (no design references, no .DS_Store, no .webp
duplicates) and ship the right cache headers (immutable for assets,
must-revalidate for HTML/CSS/JS).
netlify deploy --prod
Project layout
.
├── index.html # entry point
├── styles.css # the entire UI (no framework)
├── src/
│ ├── main.js # boot, asset loading, starter scene
│ ├── config.js # grid size, tile dims, palette, debug flags
│ ├── core/
│ │ ├── Game.js # game state + tool dispatch
│ │ ├── Camera.js # pan / zoom / change notifications
│ │ ├── Renderer.js # layered canvas caching + animations
│ │ └── InputManager.js # mouse + touch + keyboard
│ ├── grid/
│ │ ├── IsoGrid.js # screen ↔ cell math
│ │ └── TileMap.js # terrain + objects, occupancy index
│ ├── building/
│ │ └── PlacementSystem.js
│ ├── assets/
│ │ ├── assetManifest.js # the 75+ asset definitions
│ │ ├── assetLoader.js # PNG → display canvas + shadow canvas
│ │ ├── imageToAsset.js # silhouette extraction, anchor inference
│ │ └── voxelRenderer.js # procedural fallback when PNGs missing
│ ├── ui/
│ │ ├── UIManager.js
│ │ ├── Toolbar.js
│ │ ├── AssetPalette.js
│ │ ├── HUD.js
│ │ └── Audio.js # WebAudio clip routing + debouncing
│ └── persistence/
│ └── SaveSystem.js
├── assets/ # PNG asset pack (pre-generated)
├── *.ogg # placement / UI sound effects
├── netlify.toml
└── netlify-build.mjs
Architecture notes
A few choices worth flagging if you want to hack on the renderer:
- Layered cache rendering.
Renderer.jskeeps four cache canvases: a screen-space backdrop + vignette pair (rebuilt on resize), a world-space platform (rebuilt on grid resize), a world-space terrain layer (rebuilt when the terrain version counter changes), and a world-space static-objects layer (rebuilt on add/remove). Each frame the renderer composites these caches and overlays only the currently animating tiles. Idle frames are essentially free. - High-DPI cache canvases. Cache canvases are sized at
world × CACHE_SCALE(2× on standard displays, 3× on retina) so that even after the camera scales them up, the pixels are at or near final on-screen resolution. The asset displayCanvases are pre-rendered at up to 6× their reference size, so detail flows through without any “softening” intermediate. - Spatial occupancy index in
TileMap. Object lookup and free-cell checks are O(1) per cell instead of O(N) over the object list. - Dirty-flag rendering.
markDirty()is called from camera / input / tool transitions; the loop early-exits when the scene is static and no animations are pending.
Contributing
PRs welcome. Please:
- Keep it framework-free — no bundlers, no transpilers, no
node_modulesfor the runtime. - Keep the asset count modest and the visual style coherent (cobalt-on-cream, soft shadows, gentle elastic motion).
- Don’t add per-frame
ctx.filter, ImageBitmap shenanigans, or anything that would re-introduce frame drops at heavy scenes. The renderer’s caching invariants are load-bearing.
License
MIT — see LICENSE.
The PNG asset pack in assets/ is released under the same license,
generated for this project. Audio clips were authored separately;
see file metadata if you need to attribute them.
Similar Articles
@tom_doerr: https://deck.gl maps raw data into stacks of visual layers, streamlining the creation of high-performance, interactive …
deck.gl is a GPU-powered framework that enables the creation of high-performance, interactive spatial visualizations for large datasets through composable visual layers.
@dabit3: Blown away at how simple to use, fun, and beautiful Canvas UI is! My portfolio site is a living experiment, so today I …
Nader Dabit shares his excitement about Canvas UI, a new open-source component library that renders HTML in Canvas, enabling real-time shaders over interactive UI. He used DevinAI to turn his portfolio into a Canvas UI playground.
@browser_use: You can make games like this on Browser Use Cloud!
Alexander Yue open sources Flowline, a tool for creating single-file web games, encouraging community use and modification through Browser Use Cloud.
@tom_doerr: Turns complex terminal output into styled HTML pages https://github.com/nicobailon/visual-explainer…
visual-explainer is an agent skill that transforms complex terminal output—such as ASCII art diagrams and pipe tables—into styled, interactive HTML pages with Mermaid diagrams, supporting dark/light themes and multiple AI coding agent harnesses.
@theworldlabs: Summer vibes Built with Marble, Spark, and Three.js. Persistent World Models let you design for cohesive spaces instead…
The World Labs announces their World Jam ending this weekend, built with Marble, Spark, and Three.js for creating persistent 3D world models.