Satisfactory-Map-Renderer

Satisfactory-Map-Renderer

Docker app from Tunefish's Repository

Overview

Interactive map of your Satisfactory save game. Shows the whole factory (foundations, buildings, belts, pipes, railways, power), players, vehicles, resource nodes with purity, collectibles and more, with search and click-to-inspect. The save game is chosen in the web UI by an admin: upload a .sav file, fetch it from a running dedicated server through its HTTPS API (game version 1.0 or newer, API token from server.GenerateAPIToken), or copy it over SSH. A "Refresh snapshot" button fetches the current state again. Visitors only see the map. Reads saves from Update 5 up to 1.2.4. Works out of the box: the game's icons, names and in-game map (from Satisfactory 1.2.4) are included.

Satisfactory Map Renderer

An interactive map of your Satisfactory save game, in your browser.

A self-hosted web app: one Docker container reads a save game, renders the whole factory into a zoomable map and serves it. Load the save by drag and drop, fetch it from a running dedicated server, or copy it over SSH, and refresh it with one click. Everyone else just opens the page and sees the map.

The whole map with resource nodes, the factory and map markers

Questions and help: Discussions · Bugs: Issues · Changelog

What you get

  • Three base maps: a ground map (the world from above without any factory, made from the game's ground textures, water and heights), the in-game map, and a relief map with shaded terrain.
  • 3D view: the whole world as a 3D landscape you can rotate and zoom, with your factory standing on it in the game's own models and textures: machines, foundations, walls, belts, lifts, pipes and tracks. The ground shows the game's own ground textures and water, resource nodes and players stand where they are, and a click on a building or resource node shows its details.
  • The whole factory: foundations and walls, buildings (with their game icons when zoomed in), conveyor belts by tier, pipes and hypertubes, railways and the power grid.
  • Everything else on the map: players with their names, vehicles and trains, creatures and their spawners, landmarks (HUB, Space Elevator, M.A.M., AWESOME Sink), named stations, beacons and map markers, resource nodes with purity and whether they are in use, wells and geysers, power slugs, somersloops and mercer spheres, crash sites, plants, dropped items and hazards.
  • Tools: search, click any building or marker for details (recipe, clock speed, storage contents), layer groups with legends and filters, statistics, shareable links, light and dark theme.
  • Save game sources, chosen by an admin in the page:
    • browse or drag and drop a .sav file,
    • a dedicated server through its HTTPS API (game version 1.0 or newer, with an API token),
    • SSH to the machine that holds the saves.
  • Visitors only see the map. Choosing and refreshing the save needs the admin password.

Reads saves from Update 5 up to 1.2.4.

Zoomed in: buildings with their icons, belts, click for details Dark theme, statistics
A factory zoomed in, with the details of a smelter Dark theme with the object counts
3D view: the world with the game's ground and water 3D view: the factory in the game's own models
The whole world as a 3D landscape A factory in 3D with machines, belts and foundations

Water extractors and pipes in the 3D view

Installation

Docker Compose

Save this as docker-compose.yml, set a password, and run docker compose up -d:

services:
  map:
    image: ghcr.io/tunefish92/satisfactorymaprenderer:latest
    restart: unless-stopped
    environment:
      # Required, at least 8 characters. A "$" in the password must be written as "$$" here.
      SMR_ADMIN_PASSWORD: change-me-please
    ports:
      - "8080:8080"
    volumes:
      - ./map-data:/data
      # Optional, read-only: your Satisfactory installation. Only needed when your game is newer
      # than the game data in the image (new items or buildings show without icons).
      # - /path/to/Satisfactory:/game:ro

Open http://localhost:8080/, click Admin login in the Save game tab of the side panel, and choose your save game. The image is also on Docker Hub as tunefish92/satisfactorymaprenderer.

The admin password

The password may contain any characters and needs at least 8 of them. It is compared exactly: upper and lower case matter, and so do spaces at the beginning or end.

Mind the $ in Docker Compose. Compose reads $ in docker-compose.yml and in .env as the start of a variable and changes the password without telling you. The login then fails with the password you believe you set:

Written in docker-compose.yml or .env Password the app gets
pa$word123 pa
pa${word}123 pa123
pa$$word123 pa$word123

There are two ways around it:

  1. Write $$ for every $ of the password, as in the last row.

  2. Keep the password in its own file, which Compose passes on unchanged (needs Docker Compose 2.30 or newer). Create admin.env next to docker-compose.yml:

    SMR_ADMIN_PASSWORD=your password, exactly as it is
    

    and replace the environment: entry for the password with:

        env_file:
          - path: admin.env
            format: raw
    

    Everything after the = is the password: no quotes are needed, and $, #, quotes and spaces are ordinary characters there.

With docker run -e and on Unraid, Compose is not involved; quote the password for your shell as usual.

Unraid

From the Apps tab. Search for Satisfactory Map Renderer in Community Applications and click Install. The template lives in Tunefish92/unraid-templates; a copy is in unraid/.

If it is not listed (yet). Put the template on the flash drive yourself, from the Unraid terminal:

wget -O /boot/config/plugins/dockerMan/templates-user/my-Satisfactory-Map-Renderer.xml \
  https://raw.githubusercontent.com/Tunefish92/unraid-templates/main/templates/satisfactory-map-renderer.xml

Then open the Docker tab, click Add Container and choose Satisfactory-Map-Renderer from the Template list.

Settings in the template

Setting Default Meaning
WebUI Port 8080 Port the map is served on. Change it if another container already uses 8080.
Data Path /mnt/user/appdata/satisfactory-map-renderer The rendered map, settings and fetched saves.
Admin Password – Required, at least 8 characters, any characters. Unraid passes it on unchanged, so $ needs no escaping here.
Game Folder empty Normally not needed, see Game icons and the in-game map.
Max Zoom 9 Under Show more settings. Lower it to render faster and save disk space.
PUID / PGID 99 / 100 Under Show more settings. Unraid's nobody:users, so the files in appdata have the usual owner.

Click Apply, then open the map from the container's WebUI menu entry and log in under Save game → Admin login.

With a dedicated server on the same Unraid box, for example the ich777/steamcmd:satisfactory container:

  • HTTPS API (recommended): in the map's Save game tab enter your Unraid server's IP address as host and the server's game port (7777 by default; it must be mapped for TCP as well as UDP). Create the API token in the game: Server Manager → Console → server.GenerateAPIToken. Leave "Verify certificate" off.
  • SSH: possible, but needs a key in appdata/satisfactory-map-renderer/home/.ssh/ and SSH access to Unraid. With that container the saves are in /mnt/user/appdata/satisfactory/.config/Epic/FactoryGame/Saved/SaveGames/server/ (the path depends on where you mapped the server files).

From this repository

cp admin.env.example admin.env      # put the admin password into it
docker compose up -d --build

The repository's compose file already uses the admin.env approach from above. Optional settings (port, data folder, zoom) go into .env; see .env.example.

Choosing the save game

  • File: Browse… or drop a .sav anywhere on the page.
  • Dedicated server (HTTPS API): host, port (7777 by default) and an API token. Create the token in the server console with server.GenerateAPIToken. Servers use a self-signed certificate by default, so "Verify certificate" is off unless you switch it on. With "Save the running game first" the server writes a save named MapRenderer_snapshot (overwritten each time), so the map shows the current state; otherwise the newest existing save is taken. Check version shows the server's name, build and game version and whether it is supported. The API exists from game version 1.0 on; older servers need SSH or a file.
  • SSH: user@host, port and the path of a save file or of the folder with the saves (the newest .sav below it is taken). It uses the container's ssh with keys from map-data/home/.ssh/; passwords are not supported. A host is trusted the first time it is seen.
  • Refresh snapshot (also the ⟳ button at the top right of the map) fetches and renders the save again.

While a save is loaded, a progress window shows what is happening. Connection settings, including the API token, are stored in the data folder (cache/source.json), readable by the app's user only.

Game icons and the in-game map

The image works out of the box: it brings the game's icons, item and building names, resource data and the in-game map, exported from Satisfactory 1.2.4. No game installation is needed.

The 3D view button beside the zoom buttons opens the 3D view: the game's height data as a landscape, and the factory in the game's own 3D models, placed with the positions and rotations from the save.

  • Ground: the game's own ground textures where the game's landscape has them painted, with the sea, lakes and rivers as water. Steep faces get the game's cliff texture, because the game's rocks are separate objects that the ground data does not cover. Untick Realistic ground to see the in-game map on the terrain instead.
  • Factory: the models carry the game's textures and the standard paint colours (custom paint from the save is not shown). Conveyor belts, pipes, hypertubes and railway tracks are the game's own pieces laid along their paths, conveyor lifts are built from their end and middle pieces. Wires are simple strips at their real heights, and the few building types without a model are boxes.
  • World: the rocks, crystals and vents of the resource nodes stand where the game has them, and the players where they were when the game was saved.
  • Details: click a building or a resource node to see what the 2D map shows about it (recipe, power, contents; resource, purity, whether it is in use).
  • Moving around: drag to rotate, drag with the wheel button or Shift+drag to move, wheel to zoom towards the mouse; each layer can be switched off. Heights are the real ones, not exaggerated.

It needs a browser with WebGL 2 and, for a large factory, a dedicated graphics card.

The Map dropdown on the Layers tab switches between the game map and a relief map: the same map with the terrain shaded from the game's own height data, so mountains, cliffs, canyons and craters stand out.

When the game gets an update that the image does not know yet, new items and buildings appear without icons until the image is updated. To use your own game's data in the meantime, mount your Satisfactory installation read-only at /game (the folder that contains FactoryGame and CommunityResources) and delete map-data/gamedata/ if it exists: on the next start the data is exported into map-data/gamedata/, which from then on is used instead of the bundled data. The mount can be removed again afterwards.

Optional images in map-data/maps/ replace or add base maps, each covering the whole in-game map area: game-map.jpg (used instead of the bundled in-game map), ground-map.jpg (used instead of the bundled ground map) and relief-map.jpg (used instead of the bundled relief map). The bundled ground and relief maps are 32768 px wide (about 23 cm per pixel) and come cut into tiles with the image, so nothing has to be computed for them; an image of your own is cut into tiles when the map is rendered.

Settings

Variable Default Meaning
SMR_ADMIN_PASSWORD – Required, at least 8 characters, any characters (see The admin password). Only admins can choose or refresh the save game. Five wrong passwords block the login for a minute.
SMR_MAX_ZOOM 9 Highest rendered zoom level (3–9). 9 is about 6 cm per pixel; each level less renders about four times faster and needs a quarter of the disk space.
PUID / PGID 1000 Owner of the data folder; the app runs as this user.
Path Meaning
/data Everything the app keeps: map/ (the rendered map), gamedata/, maps/, cache/ (settings, fetched saves), home/ (with .ssh).
/game Optional, read-only: a Satisfactory installation, to export newer game data than the image has.

On the internet. The container speaks plain HTTP on port 8080. Put it behind a reverse proxy that adds HTTPS and forwards Host and X-Forwarded-Proto; otherwise the admin password travels unencrypted.

Updates. For admins the page checks this project's GitHub releases, at most every six hours, and shows a banner when a newer version is out. The Settings tab has the switches "Check for updates on GitHub" and "Include pre-releases". The check is a request from the admin's browser to api.github.com; visitors never make it.

Limitations

  • Building footprints come from a built-in table and are approximate; unknown buildables fall back to size heuristics.
  • A dedicated server offers no live feed. "Live" means fetching and rendering a new snapshot, about half a minute for a large factory at the default zoom.

Development

The app is one .NET 10 project: a save parser, a SkiaSharp tile renderer and a small HTTP server that serves the viewer (plain HTML/CSS/JS with Leaflet, bundled).

dotnet run --project src/SatisfactoryMapRenderer -c Release -- --serve 8000 -o output/map

serves it at http://localhost:8000/. On localhost no admin password is needed; --bind '*' listens on all interfaces and requires one. --help lists every option, among them --game <dir> and --export-game-data for the game's assets and --dump-json to write the completely decoded save as JSON.

dotnet test --solution SatisfactoryMapRenderer.slnx          # parser, extraction, rendering (xUnit v3)
node tests/viewer/viewer-smoke.mjs <output>/index.html       # clicks through the viewer in a headless browser
  • The tests build complete synthetic .sav files in memory for 10 save versions (Update 5 → 1.2.4, both property tag formats); each is parsed, turned into map features and exported to tiles. Corrupt and truncated files must produce a clean SaveFormatException.
  • RealSaveTests checks real saves for full decoding: set SMR_TEST_SAVES=a.sav;b.sav.
  • The browser smoke test needs a Chromium-based browser (BROWSER=/path/to/browser).
src/SatisfactoryMapRenderer/
  Save/          binary reader, header, chunk decompression, levels/objects, property decoder, JSON dump
  World/         class catalog (names, categories, footprints) and save → map feature extraction
  Game/          reading icons, names and level data from a game installation
  Rendering/     tile renderer, viewer export
  Serve/         HTTP server, admin login, dedicated server API client, SSH
  Assets/        the viewer and bundled Leaflet
docs/SAVE_FORMAT.md   save file format reference, including all version differences

Releases: a tag v1.2.3 builds the image for amd64 and arm64 and publishes it to GHCR and, when the repository variable DOCKERHUB_USERNAME and the secret DOCKERHUB_TOKEN are set, to Docker Hub. A tag with a hyphen (v1.3.0-beta.1) is a pre-release and does not move latest.

Licence and credits

The code is under the MIT licence.

The game data in gamedata/ (icons, names, level data, logo, in-game map) and the map and icons visible in the screenshots are the property of Coffee Stain Studios and are not covered by that licence. They are included so that this fan-made tool can display save games of their game. This project is not affiliated with or endorsed by Coffee Stain Studios.

Media gallery

1 / 3

Download Statistics

153
Total Downloads

Related apps

Details

Repository
tunefish92/satisfactorymaprenderer:latest
Last Updated2026-10-10
First Seen2026-10-14

Runtime arguments

Web UI
http://[IP]:[PORT:8080]/
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Port the map is served on.

Target
8080
Default
8080
Value
8080
Data PathPathrw

The rendered map, exported game data, map images and the save game source settings (including the server's API token).

Target
/data
Default
/mnt/user/appdata/satisfactory-map-renderer
Value
/mnt/user/appdata/satisfactory-map-renderer
Admin PasswordVariable

Required, at least 8 characters. Only admins who log in with it (Save game tab of the side panel) can choose or refresh the save game.

Target
SMR_ADMIN_PASSWORD
Game FolderPathro

Optional, normally not needed. A Satisfactory installation (the folder that contains FactoryGame and CommunityResources): if your game is newer than the game data in the image, the icons, names and in-game map are exported from it once.

Target
/game
Max ZoomVariable

Highest rendered zoom level, 3 to 9. 9 is the sharpest; each level less renders about four times faster and needs a quarter of the disk space.

Target
SMR_MAX_ZOOM
Default
9
Value
9
PUIDVariable

User ID that owns the data path; the app runs as this user. Unraid default: 99 (nobody).

Default
99
Value
99
PGIDVariable

Group ID that owns the data path. Unraid default: 100 (users).

Default
100
Value
100