Files
(jenkins) 228032c913
Tests / backend-test (pull_request) Successful in 10s
Tests / frontend-test (pull_request) Successful in 9m25s
Tests / e2e-test (pull_request) Has been cancelled
Update application ports to 3050 and enhance Playwright tests with WebGL mock
2026-04-01 11:04:16 +01:00

4.2 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What This Project Is

Line of Sight is a geospatial web app that draws a great-circle line from a user-selected point on Earth in a chosen direction, then finds all cities along that path. It includes a flight-over animation that speeds up 20x over water and slows to normal speed over land.

Commands

Docker (preferred workflow)

docker-compose up --build       # Start all services (frontend :3050, backend :3001, postgres)
docker-compose down             # Stop all services
docker-compose logs -f          # View logs

# Run tests inside containers
docker-compose exec backend npm test
docker-compose exec frontend npm test -- --run
docker-compose exec frontend npm run test:e2e

Local development (without Docker)

# Backend
cd backend && npm run dev       # Nodemon dev server on :3001

# Frontend
cd frontend && npm run start    # Vite dev server on :3050

Tests

# Backend unit tests (Jest + Supertest)
cd backend && npm test

# Frontend unit tests (Vitest)
cd frontend && npm test          # Watch mode
cd frontend && npm test -- --run # Single run (CI mode)

# E2E tests (Playwright)
cd frontend && npm run test:e2e

# Seed the database with GeoNames city data
cd backend && npm run seed-data

Build

cd frontend && npm run build    # Vite production build → frontend/build/

Architecture

This is a monorepo with three services orchestrated by Docker Compose:

frontend/  → React 19 + Vite 6 SPA (MapLibre GL, Turf.js, Axios)
backend/   → Node 24 + Express 5 REST API
docker/    → PostgreSQL + PostGIS initialization

Data flow

  1. User clicks map → sets start point (lat/lon)
  2. User selects direction (0360°) and tolerance (km radius)
  3. Frontend calls GET /api/line-of-sight?lat=&lon=&direction=&tolerance=
  4. Backend generates 80 path points along a great-circle arc (up to 20,000 km)
  5. For each point, a PostGIS ST_DWithin() query finds cities within tolerance
  6. Backend also checks whether each point is over land (500 km radius land check)
  7. Response includes line coordinates with per-point water flags and matching cities
  8. Frontend renders the path on a 3D globe map and shows city markers

Backend: backend/app/server.js

Single-file Express app. Key internals:

  • calculateDestination() — Haversine formula for great-circle destination points
  • GET /api/line-of-sight — main endpoint: path generation + PostGIS city lookup
  • GET /api/health — health check
  • Returns up to 200 cities ordered by position along the line

Frontend: frontend/src/App.jsx

Single large React component (~687 lines) managing all state and map logic:

  • MapLibre GL map with 3D globe projection and terrain/sky effects
  • Direction slider drives a live preview line before the user commits
  • After "Show Line of Sight", map locks (prevents moving start point)
  • Flight animation uses Turf.js to interpolate positions along the path; speed is 1× over land, 20× over water with smooth acceleration (0.005 step), predictive look-ahead of 2000 km
  • New cities are fetched every 2000 km during flight via the same API
  • Three map styles: light, dark, satellite (Esri tiles)

Database

PostGIS cities table with a GIST index on geom GEOGRAPHY(POINT, 4326). All coordinates use WGS84 / SRID 4326. The init SQL seeds 10 major cities; the seed-data script imports from GeoNames for a fuller dataset.

Conventions

  • Geospatial: WGS84 / SRID 4326 everywhere; PostGIS GEOGRAPHY type for distance queries
  • API: RESTful; query params for GET /api/line-of-sight; env var VITE_API_URL (frontend) or DATABASE_URL (backend)
  • Styling: Plain CSS files in frontend/src/styles/ — no CSS framework
  • Tests: Backend mocks the pg Pool; frontend mocks MapLibre GL and the API service. E2E tests use Playwright with a mock API response

CI

Gitea workflow (.gitea/workflows/test.yml) runs on push/PR to main:

  1. backend-testnpm ci && npm test
  2. frontend-testnpm ci && npm test -- --run
  3. e2e-test — uses mcr.microsoft.com/playwright:v1.50.1 container