Skip to content

Repository files navigation

fmcmapper

fmcmapper turns your Minecraft world into a lightweight Google-Maps-style web map you can open in any browser. It reads the world straight from disk, renders a top-down image of every explored area, and keeps it up to date as your world grows. And the best part? It works in vanilla Minecraft. No modded server required. Better yet, no need for a server at all - it is even singleplayer-compatible.

The fmcmapper web viewer showing a rendered Minecraft world

  • 🗺️ Pan and zoom around your whole world in the browser, like Google Maps
  • 🎨 Styled after Minecraft's in-game map item — same top-down view, block colours, and height shading
  • 🌳 Biome-accurate grass, foliage, leaf-litter, and water tints
  • 📍 Optional live player positions (requires multiplayer server + RCON)
  • 🖱️ Display the coordinates + biome when hovering over the map
  • ⚡ Keeps your map up to date by continuously re-rendering only changed regions.
  • 🐳 Ships as a ready-to-run Docker image

Try the live demo


Contents


Supported Minecraft versions

The following versions of Minecraft (Java Edition) are supported by fmcmapper:

  • 26.2.x (tag :26.2)

The following versions of Minecraft (Java Edition) are supported but don't have their own container tag (use :26.2 or :latest instead, they're backwards-compatible):

  • 26.1.x
  • 1.21.x
  • 1.20.x
  • 1.19.x
  • 1.18.x
  • 1.17.x
  • 1.16.x

Generally the newest version of fmcmapper (tag :latest) is backwards compatible with these older Minecraft versions, so you can use this version for any world.

The following versions of Minecraft are not supported:

  • Java Edition 1.15.x and older
  • Bedrock Edition
  • Legacy Console Editions

Beginner: run on multiplayer worlds

This is the easiest path. You'll get two things running together:

  1. A Minecraft server (your game world).
  2. fmcmapper — watches the world, renders the map, and serves it to your browser at http://<your-server>:8080.

You don't need to know any code. You just need Docker.

What is Docker?

Docker runs software in self-contained "containers" so you don't have to install Node.js, Java, or anything else by hand — everything the program needs comes bundled. Docker Compose lets you describe several containers in one file and start them all with a single command. That file is already written for you.

Step 1 — Install Docker

Install Docker Desktop (Windows/macOS) or Docker Engine (Linux) by following the official guide: https://docs.docker.com/get-docker/. When it's working, this terminal command prints a version number:

docker --version

Step 2 — Create the compose file

Make a fresh, empty folder and, inside it, create a file named docker-compose.yml with this content:

services:
  # The Minecraft server itself (provided by itzg/minecraft-server).
  mcserver:
    image: itzg/minecraft-server
    container_name: mcserver
    restart: "unless-stopped"
    ports:
      - "25565:25565"
    environment:
      EULA: "TRUE"
      TYPE: "VANILLA"
      VERSION: "26.2"             # keep this matching the fmcmapper tag below
      ENABLE_RCON: "true"         # RCON is needed for live player positions
      RCON_PASSWORD: "changeme"   # pick your own
      RCON_PORT: "25575"
    volumes:
      - ./mcserver:/data

  # The map renderer + web viewer (this project): renders the world and serves
  # the map to your browser on port 8080.
  fmcmapper:
    image: ghcr.io/freekbes/fmcmapper:26.2  # keep this matching the Minecraft version above
    pull_policy: always
    container_name: fmcmapper
    restart: "unless-stopped"
    ports:
      - "8080:80"                 # open the map at http://localhost:8080
    environment:
      RENDER_INTERVAL: "5"        # re-render every 5 minutes
      RCON_HOST: "mcserver"
      RCON_PORT: "25575"
      RCON_PASSWORD: "changeme"   # must match the RCON password above
    volumes:
      - ./mcserver/world:/app/world:ro
      - ./mcserver/fmcmapper:/app/output
    depends_on:
      mcserver:
        condition: service_healthy

The Minecraft version is set to 26.2 in two places above — keep them the same so the map's colours match your server's blocks.

You can bump both to a newer Minecraft version when one releases, but fmcmapper may not support it yet: if no fmcmapper image has been built for that version, the pull will fail. In that case you can use ghcr.io/freekbes/fmcmapper:latest for the renderer — just be aware latest is the newest build and may be untested against your version (colours could be off or it may misbehave).

Step 3 — Start everything

Within the same folder as your docker-compose.yml, run:

docker compose up -d

-d means "run in the background". The first start downloads the images and generates a fresh Minecraft world, so give it a minute.

Step 4 — Open the map

Go to http://localhost:8080 in your browser (or http://<server-ip>:8080 if it's running on another machine). Until the first render finishes you'll see a "rendering in progress" page that refreshes itself; then the map appears and fills in as the server generates and saves chunks.

The map refreshes automatically every 5 minutes. To stop everything (run in the same folder as the compose file):

docker compose down

What this sets up

Service What it is Port
mcserver A vanilla Minecraft server 25565
fmcmapper Renders the map and serves it (this project) 8080

A mcserver/ folder appears next to your compose file — that's your world and server files. By using this compose file you accept the Minecraft EULA (it's set to TRUE in the file).

The Minecraft server part isn't ours — it's the excellent itzg/minecraft-server image. It handles running the server, EULA, version, mods, and much more. If you want to change the Minecraft version, switch to Paper/Fabric/Forge, add plugins, or tune the server, see its documentation. fmcmapper only reads the world it produces.

That's all a beginner needs. The sections below are optional.


Beginner: run on singleplayer worlds

Yes, fmcmapper works with singleplayer worlds too. Follow the steps above, but use the following docker-compose file instead of the one above:

services:
  fmcmapper:
    image: ghcr.io/freekbes/fmcmapper:latest  # optionally change latest to your Minecraft version
    pull_policy: always
    container_name: fmcmapper
    restart: "unless-stopped"
    ports:
      - "8080:80"            # open the map at http://localhost:8080
    environment:
      RENDER_INTERVAL: "5"   # re-render every 5 minutes
    volumes:
      - "/path/to/your/world:/app/world:ro"
      - "./output:/app/output"

You can find the path to your singleplayer world in the Minecraft launcher under Installations → <your profile> → More Options → Game Directory. The world is in saves/ under that directory. Point the first volumes path to it — on Windows use forward slashes and quote the whole entry, e.g. "C:/Users/YourName/AppData/Roaming/.minecraft/saves/My World:/app/world:ro".


Advanced: configuration & existing servers

Use fmcmapper with a server you already run

You don't have to use the bundled Minecraft server. Point fmcmapper at any world folder on disk. The minimal piece is the fmcmapper service:

services:
  fmcmapper:
    image: ghcr.io/freekbes/fmcmapper:26.2  # change 26.2 to your Minecraft version
    pull_policy: always
    ports:
      - "8080:80"                   # the map in your browser
    environment:
      RENDER_INTERVAL: "5"          # re-render every 5 minutes
      RCON_HOST: "mcserver"         # must match your local server IP/hostname
      RCON_PORT: "25575"
      RCON_PASSWORD: "changeme"     # must match the server above
      # PLAYERS_POLL_INTERVAL: "2"  # seconds between polls (default 2, for large player counts increase this number)
    volumes:
      - /path/to/your/world:/app/world:ro   # your world (read-only)
      - /path/to/output:/app/output         # where the map is written

That single container renders the world and serves the map: a built-in nginx instance hosts the map contents — with cache revalidation (so the map refreshes as the world changes without serving stale tiles), gzip, and the live-player WebSocket reverse-proxied at /players. Just publish port 8080 and open http://localhost:8080.

⚠️ Match the Minecraft version. The image tag (:26.2) is the Minecraft version its colours were built for. If your world is a different version, fmcmapper still renders, but some block/biome colours may be slightly off and it prints a warning on startup. Use the image tag that matches your server, or regenerate the colour tables (see Custom colour tables).

Environment variables

Variable Default What it does
WORLD_PATH ./world Path to the world folder to render.
OUTPUT_PATH ./output Where the map (tiles + index.html) is written.
DIMENSION minecraft:overworld Which dimension to map (minecraft:the_nether, minecraft:the_end, or a modded id).
RENDER_INTERVAL (unset) Minutes between renders. Unset = render once and exit. Set it to run as a service.
TILER_JOBS a quarter of your CPU cores How many regions to render in parallel. Raise it for faster renders at the cost of more RAM.
TILER_FULL 0 Set to 1 to force a full redraw instead of an incremental one.
SERVE_ONLY 0 Set to 1 to only serve the existing OUTPUT_PATH and never render. Lets you keep serving a finished map after deleting the world to save disk; no world is read and live players are off.
RCON_HOST (unset) The host to connect to via RCON to fetch live player locations.
RCON_PORT (unset) The port to connect to via RCON to fetch live player locations.
RCON_PASSWORD (unset) The password used for the RCON connection to fetch live player locations.
PLAYERS_POLL_INTERVAL 2 Seconds between polling live player locations to display on the map.

Render once instead of continuously — add the --once flag (overrides RENDER_INTERVAL). Handy for a manual one-off against the running service:

docker compose run --rm fmcmapper --once

Map appearance (optional tuning)

These tweak how the map looks. All are optional.

Variable Default Effect
MAP_BRIGHTNESS 1 Overall brightness (1 = unchanged, <1 darker).
MAP_FOLIAGE_BRIGHTNESS 0.55 Darkening applied to leaves.
MAP_GRASS_BRIGHTNESS 0.8 Darkening applied to grass blocks.
MAP_GRASS_FOLIAGE_BRIGHTNESS 0.8 Darkening for ground plants (short/tall grass, ferns) — foliage-coloured but brighter than leaves.
MAP_DRY_FOLIAGE_BRIGHTNESS 0.8 Darkening applied to leaf litter (dry-foliage tint).
MAP_WATER_BRIGHTNESS 0.7 Darkening applied to water.
MAP_BIOME_BLEND 2 Biome colour blend radius (like in-game Biome Blend); 0 disables.

Custom colour tables

fmcmapper colours blocks using bundled map_colors.json and biome_colors.json tables generated for a specific Minecraft version. If you run a different version (or want exact colours), you can regenerate them with the companion map-color-dump mod and point fmcmapper at the results with MAP_COLORS_PATH and BIOME_COLORS_PATH. See MapColorDumpMod/README.md.

The map-color-dump mod might also be compatible with mods, though I never tried this.

Image tags

Images are published to the GitHub Container Registry and tagged by the Minecraft version they target:

  • ghcr.io/freekbes/fmcmapper:26.2 — newest build for Minecraft 26.2 (use this)
  • ghcr.io/freekbes/fmcmapper:26.2-<n> — a specific immutable build, for rollback
  • ghcr.io/freekbes/fmcmapper:latest — newest build overall

With pull_policy: always, docker compose up re-pulls the moving :26.2 tag, so you always get the latest render code without editing anything.


Development: building from source

Run it locally with Node.js

Requires Node.js 24+.

npm install
npm run build          # compile TypeScript -> build/
npm start              # render: reads WORLD_PATH/OUTPUT_PATH or ./world -> ./output

Regenerate just the viewer page from an existing render:

npm run viewer         # uses OUTPUT_PATH or ./output

Run from source with Docker Compose

Two compose files in the repo build from your local checkout instead of pulling the published images — use them while developing:

  • docker-compose.dev.yml — the full stack (Minecraft server + fmcmapper, which renders and serves the map), with fmcmapper built from this repo's Dockerfile. The same beginner setup, but local-built:

    docker compose -f docker-compose.dev.yml up --build
    
  • docker-compose.dump.yml — builds the map-color-dump mod from MapColorDumpMod/ and writes fresh map_colors.json / biome_colors.json into assets/. Run this to regenerate the colour tables (e.g. for a new Minecraft version):

    docker compose -f docker-compose.dump.yml up --build
    

    See MapColorDumpMod/README.md for details.

Project structure

Path What it is
src/buildtiles.ts Entry point — region discovery, scheduling, tile pyramid.
src/worker.ts Renders one region to an image (runs in worker threads).
src/chunkmap.ts Block/biome → colour logic.
src/gamedata.ts Tinting rules + block/biome id-rename tables.
src/viewer.ts Generates the Leaflet index.html.
src/players.ts Live player tracking (RCON poll + WebSocket server).
src/biomevector.ts Builds the biome polygons for the hover tooltip layer.
src/renderconfig.ts Resolves the MAP_* appearance env vars and defaults.
src/container/ Image runtime: nginx config, entrypoint, loading page.
Dockerfile Builds the fmcmapper image (renderer + built-in nginx).
assets/ Bundled map_colors.json / biome_colors.json.
MapColorDumpMod/ Companion Fabric mod that generates colour tables. README.

Contributing

To contribute, fork the repo, make your changes, and open a pull request. See CONTRIBUTING.md for details.

About

Browse your vanilla Minecraft world/server in a faithful web map, deployed easily with Docker

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

Used by

Contributors

Languages