A web application using Deck.gl and Mapbox GL JS to visualize weather and groundwater data sourced through DMI and HIP APIs. The project pairs a Vite-powered frontend with an Express proxy backend so API keys stay server-side.
Create a .env file in the project root before running any workflow:
# .env (never commit this)
DMI_API_KEY_METOBS="YOUR_DMI_METOBS_API_KEY"
DMI_API_KEY_CLIMATE="YOUR_DMI_CLIMATE_API_KEY"
HIP_API_KEY="YOUR_HIP_API_KEY"
MAPTILER_API_KEY="YOUR_MAPTILER_API_KEY"
VITE_MAPBOX_TOKEN="YOUR_PUBLIC_MAPBOX_TOKEN"
PORT=3000
ALLOWED_ORIGINS="http://localhost:4173"Note: Docker Compose also recognises two additional variables from your shell:
APP_ENV—development(default) enables hot-reload,productionserves the built bundle.CLOUDFLARE_TUNNEL_TOKEN— required when exposing production traffic through Cloudflare Tunnel.
The repository ships with a multi-stage Dockerfile and a single docker-compose.yml that flexes between development and production based on APP_ENV.
- Ensure Docker Engine and Docker Compose Plugin v2 are installed.
- From the project root run:
APP_ENV=development docker compose up geodaisy
- What you get:
- Express API on http://localhost:3000.
- Vite dev server with live reload via polling on http://localhost:4173.
- File changes on your host are mirrored into the container through a bind mount, so the preview refreshes automatically.
- Stop with
Ctrl+C, or keep the app running in the background withAPP_ENV=development docker compose up -d geodaisyand view aggregated logs viadocker compose logs -f.
- Generate or copy an existing Cloudflare Tunnel token. Save it securely—Compose expects it via
CLOUDFLARE_TUNNEL_TOKEN. - Build and start the hardened stack:
APP_ENV=production \ CLOUDFLARE_TUNNEL_TOKEN=YOUR_TUNNEL_TOKEN \ docker compose up --build -d
- Behaviour in production mode:
- The container boots from the production stage of the multi-stage build and serves pre-built assets with
npm run start-prod-server. - The Cloudflare sidecar only activates when
APP_ENV=productionand a tunnel token is present; otherwise it idles safely. - Default ports remain published locally (3000 API, 4173 preview) for health checks or internal access.
- The container boots from the production stage of the multi-stage build and serves pre-built assets with
- Rotate or revoke the tunnel by updating
CLOUDFLARE_TUNNEL_TOKENand re-runningdocker compose up -d. - Tear everything down with:
APP_ENV=production docker compose down --remove-orphans
# Rebuild after dependency changes
APP_ENV=development docker compose build
# Tail logs for both services
docker compose logs -f
# Run a one-off command in the app container
docker compose exec geodaisy npm testRunning outside Docker is still supported when Node.js 20+ is installed locally.
- Install dependencies:
npm install
- Start the dev experience:
The command concurrently launches the backend (
npm run dev
nodemon) and Vite dev server (now bound to0.0.0.0for parity with Docker). - Build for production or serve locally:
npm run build npm run start-prod-server
If you manage the app directly on a Linux host (without containers), you can still use the included install-service.sh.
- Ensure prerequisites are installed:
rsync,useradd,groupadd,systemctl, Node.js/npm, and that your.envfile is present. - Install the service (the script provisions a locked-down
geodaisysystem user by default):sudo SERVICE_USER=<your-user-if-needed> npm run install-service
- Manage the service via standard commands:
sudo systemctl status geodaisy.servicesudo systemctl stop geodaisy.servicesudo systemctl start geodaisy.service
- Uninstall cleanly:
npm run uninstall-service
- Frontend:
/src,app.js,index.html,env.js. - Backend:
server.jsexposes/api/*endpoints and mediates external API requests. - Static assets: Store icons and images in
/public.
The basemap in this example is provided by CARTO free basemap service. To use an alternative base map solution, visit this guide.