Warning
This project is currently under heavy development and makes use of vibe-coding. Expect frequent breaking changes, bugs, and incomplete documentation. Read the disclaimer below.
A web-based geospatial visualization system with 3D model and point cloud support, designed for historical map data and geographical features.
- 📍 Interactive 2D Maps - OpenLayers-based mapping with custom CRS support
- 🗻 3D Viewer - Three.js-based 3D visualization of models and point clouds
- 📊 Multi-format Support - GeoJSON, 3D models (.obj, .ply), point clouds (.laz, .ply), GeoTIFFs
- 🐳 Docker Ready - Complete containerized setup with all dependencies
- 🛠️ Flexible Configuration - YAML-based map config with per-feature 3D data links
The easiest way to get started - no need to install GDAL, PDAL, or other dependencies:
# Start the application
docker compose up
# Access at:
# - Frontend: http://localhost:8080
# - Backend API: http://localhost:3000For development with hot-reload:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
# Frontend dev server: http://localhost:5173See DOCKER.md for complete Docker documentation.
- Node.js 20+
# Install dependencies
cd client && npm install
cd ../server && npm install
# Start development servers
cd client && npm run dev # Port 5173
cd server && npm start # Port 3000stratum3D/
├── docker-compose.yml # Base Docker configuration
├── docker-compose.dev.yml # Development overrides
├── docker-compose.prod.yml # Production overrides
├── .env.example # Root environment variable template
├── server/
│ ├── index.js # Express API server
│ ├── reset.js # Reset/cleanup utility
│ ├── src/ # Core server modules
│ │ ├── config.js # Environment-based configuration
│ │ ├── jobQueue.js # Async job queue for processing
│ │ ├── layerStore.js # UUID-based layer registry
│ │ ├── logger.js # Structured logging
│ │ └── utils.js # Shared utilities
│ ├── processors/ # Format-specific processing logic
│ │ ├── geotiffProcessor.js
│ │ ├── modelProcessor.js
│ │ ├── pointcloudProcessor.js
│ │ ├── shapeProcessor.js
│ │ └── uploadProcessor.js
│ └── data/ # Served data directory
│ ├── config.yaml # Map configuration
│ └── layers/ # Uploaded layers (UUID-based)
│ └── {uuid}/ # One folder per layer
└── client/ # Vue.js frontend application
├── src/
│ ├── App.vue
│ ├── main.js
│ ├── components/
│ │ ├── admin/ # Admin UI components
│ │ ├── contextMenus/ # Right-click context menus
│ │ ├── map/ # 2D map components
│ │ ├── modals/ # Dialog modals (incl. admin/)
│ │ ├── ui/ # Generic UI primitives
│ │ └── viewer3D/ # 3D viewer components
│ ├── composables/ # Reusable Vue composables
│ ├── constants/ # App-wide constants and config schema
│ ├── router/ # Vue Router configuration
│ ├── stores/ # Pinia state stores
│ │ ├── map/ # Map state (layers, pins, selection)
│ │ └── viewer3D/ # 3D viewer state
│ ├── utils/ # Frontend utilities
│ ├── views/ # Top-level views (MapView, 3DView, AdminView)
│ └── workers/ # Web Workers (GeoTIFF, layer, point cloud)
└── public/
└── wasm/ # WASM binaries (laz-perf)
Navigate to the Admin view in the app and upload files directly. Supported formats:
- GeoJSON / Shapefiles → vector layers
- GeoTIFF (
.tif) → raster layers - 3D models (
.obj+.mtl,.ply) - Point clouds (
.las,.laz,.ply) - CSV files → attribute join for GeoJSON layers
Each upload is assigned a unique UUID and stored under server/data/layers/{uuid}/.
Use the Admin interface to manage layers. The map title, CRS, and view settings can be adjusted in server/data/config.yaml if needed.
Open http://localhost:8080 (Docker) or http://localhost:5173 (dev) to see your map.
The Admin view allows you to manage data layers without touching config files:
- Upload and configure new layers (GeoJSON, GeoTIFF, 3D models, point clouds)
- Link sub-files (CSV attributes, MTL materials, textures)
- Edit layer metadata and display settings
- Remove layers and associated files
The 3D viewer supports:
- Multiple 3D models per feature
- Point cloud visualization
- Camera position files
- Interactive tools (wireframe, bounding box, measurements)
- QGIS-style ribbon menu
Each uploaded layer is stored in its own UUID directory under server/data/layers/:
{uuid}.{ext}— main data file{uuid}.meta.json— metadata sidecar- Sub-files (CSV, MTL, textures, linked models/point clouds) stored alongside
Vector Data:
- GeoJSON (
.geojson,.json) - Shapefiles (
.shp+ associated files)
3D Models:
- Wavefront OBJ (
.objwith.mtland textures) - PLY (
.ply)
Point Clouds:
- LAZ/LAS (
.laz,.las) - converted to COPC - PLY (
.ply) - COPC (
.copc.laz) - cloud-optimized format
Raster Data:
- GeoTIFF (
.tif,.tiff) - converted to COG
- Docker Setup - Complete Docker usage guide
# Client (Vue.js with hot-reload)
cd client
npm run dev # Port 5173
# Server (Express)
cd server
npm start # Port 3000# Build client
cd client
npm run build
# Serve via Express
cd server
npm startcd client
npm run lint # ESLint
npm run format # Prettier# Development (hot-reload)
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
# Rebuild after dependency changes
docker compose up --buildSet these in your root .env before building the client:
VITE_SITE_TITLE=My Map
VITE_SITE_FAVICON=/favicon.pngPlace the favicon file in client/public/ — everything in that folder is served from the root path, so client/public/favicon.png becomes /favicon.png. Then rebuild the client container to apply the changes:
sudo docker compose build client && sudo docker compose up -d clientChange ports in docker-compose.yml or the root .env file (copy .env.example as a starting point).
- Check that preprocessing completed or the upload succeeded
- Verify the layer UUID directory exists under
server/data/layers/ - Check browser console for errors
On first run a setup wizard will prompt you to set an admin password. To reset it, delete server/data/.credentials and restart the server.
Once your layers are configured you can hide the admin panel entirely. In your root .env file, set:
ADMIN_ENABLED=falseThen recreate the server container to apply the change:
docker compose up -d serverThis strips all /admin/* routes from the server at the network level. To re-enable it, set ADMIN_ENABLED=true and run docker compose up -d server again.
Note: Use
docker compose up -d(notdocker compose restart) when changing.env—restartdoes not re-read environment variables.
For very large files, upload and processing are handled automatically by the Admin interface. Processing options (decimation, COPC conversion, COG creation) can be configured before uploading.
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly (2D map, 3D viewer, preprocessing)
- Submit a pull request
This repository serves as a primary test case to determine the practical limits and efficacy of "vibe-coding." We are exploring how far rapid, intuition-led prototyping can carry a project before traditional engineering rigor must take over.
Because features are the result of rapid exploration, they may behave unexpectedly. Do not use this with sensitive data. A manual evaluation and code audit phase is scheduled for later this year to transition Stratum3D toward production-ready standards.
This project is licensed under the MIT License - see the LICENSE file for details.
- OpenLayers for 2D mapping
- Three.js for 3D visualization
- Vue.js for the frontend framework
- GDAL, PDAL, and untwine for data processing tools