🐳 Easiest setup (for non-developers): run the ENTIRE app with one command via Docker — no manual MapServer or Node.js install, and no two terminals. See Chapter 8 — Run with Docker.
MapFile Preview is a browser-based tool that helps you edit MapServer mapfiles and immediately preview what they publish (WMS/WFS). It includes a UI for editing text and viewing the map, and an API service that reads/writes mapfiles from a workspace folder, validates them with MapServer, and forwards preview requests to your MapServer installation.
- Edit MapServer
.mapfiles from a configured workspace folder - Create new mapfiles (guided form) or “Quick New” templates
- Save / Save As to manage mapfiles and aliases in the workspace
- Format (pretty-print) mapfiles for readability
- Validate mapfiles with MapServer and show errors/warnings
- Auto Metadata helper (adds common OGC metadata for WMS/WFS)
- Preview:
- WMS (GetMap / GetLegendGraphic / Capabilities)
- WFS (choose a layer and preview features on the map)
- Mapfile Teacher (Gemini): ask questions and get answers grounded in the MapServer PDF (requires your own Gemini API key)
Open mapfile (by alias + path).
Opens an existing .map file from the workspace by letting you assign (or re-use) a short alias (e.g., MY_MAP) and a relative path inside the workspace (e.g., subfolder/my_map.map). The alias is used for previews so you don’t have to type long file paths.
New / Quick New mapfile.
Creates a new mapfile for you using a guided form. “New” lets you fill in more options (projection/EPSG, map size, extent, optional paths, and service metadata), while “Quick New” creates a fast starter mapfile with minimal inputs so you can begin editing immediately.
Save / Save As.
Saves your current changes back to the workspace. “Save As” helps you store the mapfile under a new file name and optionally in a chosen folder inside the workspace, with an option to overwrite if a file already exists.
Format mapfile.
Reformats the mapfile text so it is easier to read and review (consistent indentation and structure). This reduces mistakes caused by messy formatting and makes troubleshooting easier.
Validate mapfile.
Runs MapServer’s validation on the mapfile and returns any errors or warnings. This is the quickest way to confirm whether the mapfile can be parsed and whether common configuration problems exist before you try to publish services.
Auto Metadata.
Helps you add (or generate) common OGC-related metadata blocks for WEB/METADATA or LAYER/METADATA. You can choose which capabilities to include (OWS/WMS/WFS/WCS), and the tool prepares a ready-to-insert metadata snippet so you don’t have to write it from scratch.
WMS Preview.
Lets you test WMS output quickly: view maps, legends, and capabilities. The preview uses your MapServer endpoint and the currently opened mapfile, so you can immediately see if style/extent/projection changes behave as expected.
WFS Preview (Layer Picker).
Helps you test WFS layers by listing the available layers and letting you choose one to preview. This is useful when a service exposes many layers—pick a single layer and view its features on the map to confirm geometry and attributes look correct.
Mapfile Teacher (Gemini).
A “chat-like” helper where you ask MapServer/mapfile questions and get answers grounded in a PDF reference. For best results, download MapServer.pdf from the official MapServer documentation page and point the Teacher to the local file path. The Teacher requires your own personal Gemini API key (see Configuration).
MapServer documentation page (download MapServer.pdf there):
https://mapserver.org/documentation.html
-
UI (Frontend)
Provides the editor, dialogs (open/save/new), and the preview map. It calls the API (default:http://localhost:4300) for file operations, validation, and previews. -
API (Backend)
Reads/writes mapfiles from a workspace folder, validates them, stores settings, and forwards WMS/WFS/CGI preview requests to your MapServer endpoint. -
MapServer (External requirement)
- A local MapServer binary (
mapserv) for validation - A MapServer CGI endpoint reachable over HTTP for WMS/WFS previews (e.g., served via IIS/Apache)
- A local MapServer binary (
- Node.js: recommend Node 20+ (https://nodejs.org/en/blog/release/v20.20.0)
- Package manager: npm (package-lock files present)
- External services / software:
- MapServer 8+ (required)
- Local
mapservbinary path (for validation) - HTTP base URL for MapServer CGI (for preview)
- Local
- Mapfile Teacher (optional):
- A personal Gemini API key (required to use Teacher - (https://ai.google.dev/gemini-api/docs/api-key))
- MapServer 8+ (required)
Installation at a glance — do these steps in order:
- Install MapServer (required for validation & preview) — see Step 1 below.
- Install Node.js 20+ (this also installs npm) — detailed in Step 3 → Part A below; for the Git option also install Git (see Prerequisites).
- Get the project files (ZIP or Git) — Step 2.
- Install dependencies (UI + API) — Step 3 → Part B.
When done, continue to 6. Configuration and 7. Running the App (Dev).
The app needs MapServer for two separate things:
- a local
mapservbinary (e.g.mapserv.exe) used for validation → later set asMAPSERV_PATH - a MapServer CGI endpoint over HTTP (served by a web server) used for WMS/WFS preview → later set as
MAPSERV_URL
On Windows the easiest option is MS4W, because one installer provides both the mapserv.exe binary and a ready web server with a CGI endpoint (no manual IIS/Apache setup needed).
Option A — MS4W (recommended for Windows)
- Home / docs: https://ms4w.com/
- Download page: https://ms4w.com/download.html
- Direct installer (.exe): https://ms4w.com/release/ms4w-5.2.0-setup.exe
- Install guide (README): https://ms4w.com/README_INSTALL.html
After installing MS4W, the binary is typically at
C:\ms4w\Apache\cgi-bin\mapserv.exeand the CGI endpoint athttp://localhost/cgi-bin/mapserv.exe. Use your actual path/URL in 6. Configuration (MAPSERV_PATH/MAPSERV_URL) — they may differ from the example defaults.
Option B — OSGeo4W (select the mapserver package during setup)
- Project page: https://www.osgeo.org/projects/osgeo4w/
- Network installer: https://download.osgeo.org/osgeo4w/v2/osgeo4w-setup.exe
Official MapServer pages
- Download: https://mapserver.org/download.html
- Installation docs: https://mapserver.org/installation/index.html
Need MapServer.pdf for the optional Mapfile Teacher? Direct download: https://download.osgeo.org/mapserver/docs/MapServer.pdf
Option A — ZIP
Windows users: the
unzipcommand below is for macOS/Linux. On Windows, right-click the downloaded.zip→ Extract All…, then open the extracted folder.
unzip Mapfile-Preview.zip
cd Mapfile-PreviewThe ZIP file can be found at https://github.com/Consortis-Geospatial/Mapfile-Preview/
under the Code tab.

Alternatively, you can use the releases listed in the Releases section on the right side of the GitHub page.

Once you click Releases, it will open and you can choose the version you want. For example:

Option B — Git (recommended) Clone the repository to get the latest code (requires Git installed — download it from https://git-scm.com/download/win), then enter the project folder:
git clone https://github.com/Consortis-Geospatial/Mapfile-Preview.git
cd Mapfile-PreviewThis step has two parts:
- Part A: install Node.js (the engine that runs the project) and confirm it works.
- Part B: download the project's "building blocks" (the libraries it needs) for both the UI and the API.
A few words in plain language (no jargon needed):
- Node.js is the program that lets this project run on your computer. Installing it also installs npm, a helper that automatically downloads everything the project needs.
- The
clientfolder is the UI — the screen you look at and click. It is built with a technology called Angular. You do not install Angular by hand; npm does it for you in Part B.- The
serverfolder is the API — the "engine" that works in the background (reading/saving mapfiles, talking to MapServer). It runs on Node.js.- You will set up both folders, one after the other.
- Open this page in your browser: https://nodejs.org/en/blog/release/v20.20.0 (or the Node.js home page https://nodejs.org/) and download the Windows Installer (.msi) for version 20 or newer (the "LTS" version).
- Run the downloaded file and click Next through the installer, leaving every option at its default. (Leave the "Add to PATH" option checked — it is on by default. This is what lets you type
nodein any window.) - When it finishes, click Finish. You do not need to restart the computer, but you must open a new Command Prompt window after installing (windows opened earlier won't know Node.js exists yet).
Check that it worked. Open a Command Prompt (Start → type cmd → press Enter) and type these two lines, pressing Enter after each:
node -v
npm -vYou should see a version number after each one — for example v20.20.0 and 10.8.2. The exact numbers may differ; that's fine, as long as Node is 20 or higher. If instead you see "'node' is not recognized", close the window, open a new Command Prompt, and try again. If it still fails, re-run the Node.js installer.
First, open a Command Prompt inside the project's root folder. The "root folder" is the one you unzipped/cloned in Step 2 that contains both the client and server folders.
- Open a Command Prompt (Start → type
cmd→ press Enter). A normal (non-administrator) window is fine. - Type
cd— that is the two lettersc,d, followed by a space. - Copy the full path of the project folder, paste it right after
cd, and press Enter. (Tip: in File Explorer, click once on the address bar to reveal the full path, or simply drag the project folder onto the Command Prompt window to paste its path automatically.)
Important — run the two commands below in this order, in the SAME window. First the UI, then the API. The API command uses
cd ../server, which only works if you are coming from theclientfolder.
1) UI (the Angular screen) — folder client:
cd client
npm ci
2) API (the Node engine) — folder server:
cd ../server
npm ci
What to expect while npm ci runs:
npm cireads the project's list of required libraries and downloads them into a new folder callednode_modules. (cistands for "clean install".)- It can take several minutes for each folder, especially the UI. You'll see many lines of text scrolling by — that's completely normal.
- It's finished when the scrolling stops and you get the prompt back (a line ending in
>waiting for you to type). A short summary such asadded 1234 packagesmeans it worked. You can ignore yellownpm warnlines; only rednpm errorlines indicate a real problem.
Troubleshooting
npm ci:
- Red "lockfile" / "package-lock.json" mismatch error: run this instead, in the same folder:
npm install- Permissions error (e.g.
EPERM, "access is denied"): close the window, reopen Command Prompt as Administrator (Start → typecmd→ right-click Command Prompt → Run as administrator), go back to the project folder, and run the command again.- "'npm' is not recognized": Node.js isn't installed, or you opened the window before installing it — do Part A first, then open a new window.
- It hangs or fails to download:
npm cineeds the internet. Make sure you're online and try again.
Most day-to-day usage is done through the app’s Settings (where available). If you run the app yourself, the API also supports configuration via environment variables and an optional local JSON file.
Configuration is applied in this order (highest priority first):
server/src/config.local.json(if present)
You’ll typically configure these so the app can find your workspace and your MapServer installation.
| Variable | What it controls | Example |
|---|---|---|
PORT |
API listening port | 4300 |
WORKSPACE_DIR |
Folder where mapfiles are stored (read/write) | C:\data\maps |
CURRENT_MAP |
Default mapfile to open (full path) | C:\data\maps\example.map |
CURRENT_MAP_ALIAS |
Default alias used for preview | MY_MAP |
USE_MAP_ALIAS |
If 1, previews use map=<alias>; if 0, use full map path |
1 |
MAPSERV_PATH |
Local path to mapserv binary (validation) |
C:\mapserver8\bin\mapserv.exe |
MAPSERV_URL |
Base URL of MapServer CGI endpoint (previews) | http://localhost:8080/mapserver-8 |
MAPSERVER_CONF / MAPSERVER_CONFIG_FILE |
Path to MapServer config file (used for alias-related configuration) | C:\data\maps\mapserver.conf |
To use Mapfile Teacher, you must provide:
- A local PDF path (recommended: the official MapServer.pdf you downloaded)
- Your own personal Gemini API key
Gemini key can be provided as:
- Environment variable
GEMINI_API_KEY(orGOOGLE_API_KEY), or - In
server/src/config.local.jsonunderllm.geminiApiKey
Keep your API key private. Do not commit it to source control.
This file is for local overrides and may also be written by the app’s Settings screen (if enabled).
Example:
{
"port": 4300,
"workspaceDir": "C:\\data\\maps",
"mapservPath": "C:\\mapserver8\\bin\\mapserv.exe",
"mapservUrl": "http://localhost:8080/mapserver-8",
"useMapAlias": true,
"currentMapAlias": "MY_MAP",
"llm": {
"enabled": true,
"typeLLM": "Gemini",
"geminiApiKey": "YOUR_PERSONAL_KEY"
},
"geminiMpTeacher": {
"pdfPath": "C:\\path\\to\\MapServer.pdf",
"model": "gemini-2.5-flash",
"topK": 6
}
}The UI is configured via a small JSON file (e.g., config.json) and browser-local preferences.
Example config.json:
{
"language": "el",
"theme": "light",
"use_AI": true,
"apiURL": "http://localhost:4300"
}- apiURL: base URL of the API backend (default:
http://localhost:4300) - language / theme / use_AI: UI defaults
- Teacher PDF path (and some other preferences): stored in the browser (local preferences)
If you run the API on a different host/port, update apiURL (or deploy the UI behind a proxy) so the UI can reach the API correctly.
You run the app every time you want to use it. It has two parts that must both be running at the same time, each in its own terminal window:
- Terminal #1 → API (the
server, runs on Node.js) — the background engine. - Terminal #2 → UI (the
client, the Angular screen) — what you actually look at.
Why two windows? Each part keeps running and "listens" for work, so it takes over its window and can't share it with the other. Keep both windows open the whole time you use the app — closing a window stops that part.
Order matters: start the API first, then the UI. The UI needs the API to be ready to answer it.
- Open a Command Prompt (Start → type
cmd→ press Enter). A normal window is fine. - Go to the project root folder (the one that contains
clientandserver): typecd, a space, then paste the folder path (or drag the folder onto the window) and press Enter. - Type these two lines, pressing Enter after each:
cd server
npm startWhat to expect:
- After a moment you'll see a confirmation line, typically:
Server on http://localhost:4300. - The window then stays open and looks "busy" — it does not return to a normal prompt. That is correct; it means the API is running. Leave this window open.
- If it instead printed an error and gave you the prompt back, see Troubleshooting below.
- Open a second, separate Command Prompt window. (Don't reuse the first one — that window is busy running the API.)
- Go to the same project root folder again (type
cd, a space, paste the path, press Enter). - Type these two lines, pressing Enter after each:
cd client
npm startWhat to expect:
- The UI is built with Angular, so the first start takes a while (often 30 seconds to a couple of minutes) while it compiles. This is normal — please be patient and let it finish.
- When it's ready you'll see a green message similar to "Application bundle generation complete", followed by a line like:
➜ Local: http://localhost:4200/
- Like the API window, this window stays open and busy. Leave it open too.
Once Terminal #2 shows it's ready, open your web browser (Chrome, Edge, Firefox, …) and go to:
http://localhost:4200
- You only open the UI address (
4200). The UI talks to the API (4300) automatically in the background — you don't open4300yourself. - If the page doesn't load on the very first try, wait a few seconds (the UI may still be finishing its compile) and then refresh the page.
When you're finished using the app:
- Click on Terminal #1, then press
Ctrl + Con the keyboard. If Windows asks "Terminate batch job (Y/N)?", typeYand press Enter. - Do exactly the same in Terminal #2.
- You can now close both windows.
To use the app again another day, you do not need to reinstall anything from Section 5 — just repeat the steps in this section (start the API, then the UI, then open
http://localhost:4200).
| What you see | What it means | What to do |
|---|---|---|
'npm' is not recognized |
Node.js isn't installed, or the window was opened before installing it | Install Node.js (Section 5, Step 3 → Part A), then open a new Command Prompt and try again |
Missing script: "start" or Cannot find module … |
You're in the wrong folder, or dependencies weren't installed | Make sure you typed cd server / cd client first, and that you ran npm ci in Step 3 |
| A message that port 4300 (API) or port 4200 (UI) is already in use | The app — or another program — is already using that port | Close any old terminal windows that may still be running the app, then start again. If Angular offers to use a different port, you can accept it |
| Browser shows an error or "cannot reach the API" | The API (Terminal #1) isn't running, or you started the UI first | Make sure Terminal #1 is still open and shows Server on http://localhost:4300, then refresh the browser |
| A window seems "frozen" with logs and won't accept typing | This is normal — it's the running app, not a freeze | Don't type in that window; use the other window for commands. Press Ctrl + C there only when you want to stop that part |
Who this is for: non-developers (or anyone who wants the fastest setup). This path lets you skip Chapters 4–7: you don't install MapServer, Node.js, or open two terminals. The only thing you install once is Docker Desktop.
Docker bundles the whole application — UI + API + MapServer + web server — into a single, ready-to-run image. In practice that means:
- One install (Docker Desktop) instead of three (MapServer + Node.js + Git), and no IIS/Apache setup.
- One command (
docker compose up) — nonpm ciin two folders, no two terminals kept open. - Nothing is installed on your computer except Docker: MapServer and Node run inside the container and don't clutter your system.
- Same result on every machine (Windows/Mac/Linux) — no more "it worked on mine".
- Clean removal: a single
docker compose downleaves nothing behind — no MapServer/Node to uninstall.
Download and install Docker Desktop:
- Download (all operating systems): https://www.docker.com/products/docker-desktop/
- Detailed install guide for Windows: https://docs.docker.com/desktop/setup/install/windows-install/
- General instructions (Mac/Linux): https://docs.docker.com/get-docker/
After installing, open Docker Desktop and wait until you see the green "Engine running" at the bottom-left. That's all — no further configuration is needed.
Get the project files (exactly as in Chapter 5 → Step 2): either as a ZIP (Code → Download ZIP → right-click → Extract All…) or with git clone. Open the folder that contains client, server, and docker-compose.yml.
-
Open a terminal inside the project folder (where
docker-compose.ymllives):- Windows tip: in the File Explorer address bar, while inside the folder, type
cmdand press Enter — this opens a terminal in exactly that folder.
- Windows tip: in the File Explorer address bar, while inside the folder, type
-
Run:
docker compose up -d --build
- The first time it builds the image (downloads MapServer/Node, a few minutes — this happens only once).
-druns it in the background (no need to keep a terminal open).
-
Open in your browser:
http://localhost:4300That's it. The UI and the API run on the same address (
4300), so no configuration is needed — you only open this one link.
In the project's workspace/ folder (on your computer). It is mounted into the container as /data/maps, which means:
- Any
.mapfile (together with the data it references: shapefiles, rasters, etc.) that you drop intoworkspace/is immediately visible to the app. - On the first run an
example.mapis created automatically so you have something to open right away.
⚠️ About paths: inside the container the OS is Linux. So paths inside your mapfiles must be relative (e.g.SHAPEPATH ".") or Linux-style under/data/maps— not absolute Windows paths (e.g.C:\data\...). If a mapfile points to an external database (PostGIS), make sure it is reachable from the container.
| What you want | Command |
|---|---|
| Start | docker compose up -d |
| Start after code changes | docker compose up -d --build |
| Stop | docker compose down |
| View logs (live) | docker compose logs -f |
| Restart | docker compose restart |
The single image contains and runs together:
- the API (Node/Express), which also serves the UI (Angular build) on port
4300; - MapServer 8: the binary for validation (called directly by the API) and a CGI endpoint via Apache for preview (called by the API internally — not exposed outside);
- ready-made settings via environment variables (see Chapter 6 — Configuration). The Docker defaults are already correct (Linux paths), so you don't need to change anything to get started.
The Teacher is optional. To make it work inside Docker:
-
In
docker-compose.yml, underenvironment, provide your own Gemini API key (uncomment it):environment: GEMINI_API_KEY: "your-personal-key"
-
Put
MapServer.pdfinto theworkspace/folder and, from the app's Settings, enable the Teacher pointing it to the path/data/maps/MapServer.pdf. -
Run
docker compose up -dto apply the changes.
By default the image bundles its own MapServer 8 (used both for validation and for WMS/WFS preview). If you already have a MapServer running — for example MS4W on your Windows machine, a remote server, or another container — you can point the app to it instead, without rebuilding the image.
The app uses MapServer in two distinct ways, each controlled by its own environment variable:
| Purpose | Variable | What it controls |
|---|---|---|
| Validation | MAPSERV_PATH |
Path to the mapserv binary called directly |
| WMS/WFS preview | MAPSERV_URL |
HTTP URL of the MapServer CGI endpoint |
You can override either or both in docker-compose.yml.
If your MapServer already serves maps over HTTP (e.g. http://192.168.1.50/cgi-bin/mapserv), set MAPSERV_URL. The bundled binary is still used for validation.
environment:
TZ: "Europe/Athens"
MAPSERV_URL: "http://192.168.1.50/cgi-bin/mapserv" # ← your serverNote: use the server's real IP address or hostname, not
localhost— inside the containerlocalhostrefers to the container itself, not your host machine. On Windows/Mac you can use the special hostnamehost.docker.internalto reach your host:MAPSERV_URL: "http://host.docker.internal/cgi-bin/mapserv"
If you also want to replace the validation binary with your own, mount the mapserv binary into the container and set MAPSERV_PATH:
volumes:
- ./workspace:/data/maps
- /path/to/your/mapserv:/usr/local/bin/mapserv-ext:ro # mount your binary
environment:
MAPSERV_PATH: "/usr/local/bin/mapserv-ext"
MAPSERV_URL: "http://192.168.1.50/cgi-bin/mapserv"Important: the container runs Linux (Debian). The binary you mount must be compiled for Linux — a Windows
mapserv.exewill not work inside the container.
If your MapServer is also a Docker container, put both services in the same docker-compose.yml and let them share a network:
services:
mapfile-preview:
build: .
ports:
- "4300:4300"
volumes:
- ./workspace:/data/maps
environment:
TZ: "Europe/Athens"
MAPSERV_URL: "http://my-mapserver/cgi-bin/mapserv" # service name = hostname
networks:
- gis-net
my-mapserver: # your existing MapServer container
image: camptocamp/mapserver:latest # replace with your actual image
volumes:
- ./workspace:/data/maps # share the same mapfiles
networks:
- gis-net
networks:
gis-net:Docker automatically resolves my-mapserver (the service name) to the right IP inside the shared network. Run docker compose up -d --build as usual.
Quick reference — what to change depending on what you need:
| I want… | What to set |
|---|---|
| Only preview → my MapServer | MAPSERV_URL in docker-compose.yml |
| Validation too → my binary (Linux) | MAPSERV_PATH + mount the binary |
| MapServer in another container | Shared network + MAPSERV_URL using the service name |
-
http://localhost:4300doesn't open → make sure Docker Desktop is running ("Engine running"). Check the logs:docker compose logs -f. -
I want to change the port → keep the internal
4300and change only the left number inports, AND setAPP_ORIGINso the UI knows where the API is. Example indocker-compose.yml:ports: - "8080:4300" environment: APP_ORIGIN: "http://localhost:8080"
Then run
docker compose up -dand openhttp://localhost:8080. -
The preview is blank or shows an error → usually the mapfile points to data that isn't inside
workspace/, or to a Windows path. Fix the paths as in 8.5.
.
├─ client/ # UI (editor + map preview)
├─ server/ # API (workspace, validation, WMS/WFS/CGI proxy, Teacher)
├─ workspace/ # Your mapfiles & data (mounted into the container as /data/maps)
├─ docker/ # Docker support files (MapServer/Apache config, entrypoint, example.map)
├─ Dockerfile # Single all-in-one image (UI + API + MapServer)
├─ docker-compose.yml # One-command run (docker compose up -d --build)
├─ .dockerignore # Files excluded from the image build
└─ zip_project.bat # Helper script (if used in your environment)