From a map action to an inspectable RF result
A.T.O.M is a local-first React and Go application. The browser owns planning state and map presentation; the Go service owns validation, bounded computation, spatial queries, and deterministic RF analysis. An optional sidecar adds 5G communication-path state without changing the radio model.
The shortest useful mental model
A planning action becomes a validated JSON request. The backend narrows the active validated dataset pack through an in-memory spatial index, executes the selected deterministic engine, and returns GeoJSON plus statistics. The browser then renders only the layers and result view relevant to that operation.
System context
The production image contains the built frontend, Go API, and default Ankara dataset pack. Basemap tiles remain an external dependency unless replaced or cached. Core Lab is opt-in and communicates through a separate adapter.
/api/*.
The RF engines and datasets run locally. Leaflet currently requests OpenStreetMap tiles over the network unless a local tile source is configured separately.
Runtime components
Frontend responsibilities stop at orchestration and presentation. Domain validation and RF calculations stay behind the Go API, while the data layer exposes bounded spatial candidates to each engine.
React workspace
Go + Gin service
Data and integrations
Data preparation and spatial querying
The Python pipeline is not part of normal request handling. It prepares files ahead of time; the Go service loads those files once at startup and serves all analyses from memory.
| Runtime artifact | Purpose | Lifecycle | Important consequence |
|---|---|---|---|
| ankara_buildings.geojson | Footprints and demand properties | Loaded once into memory | Fast requests, higher startup memory |
| ankara_5g_nodes.geojson | Tower coordinates and cell identifiers | Loaded once; also served to frontend | No live tower API dependency |
| manifest.json | Pack identity, provenance, schema, bounds, and hashes | Validated before runtime readiness | Invalid or incompatible packs fail /readyz |
| Building R-tree | Bounding-box candidate search | Built during startup | Avoids scanning every polygon per ray |
| Demand summary | Dataset confidence and counts | Computed from loaded footprints | Visible in Data and reports |
| Analysis GeoJSON | Rays, gaps, and radio-quality samples | Generated per request | Not stored server-side |
| Project scenarios | Exact inputs, model metadata, summaries, and recent layers | Stored in browser IndexedDB | Portable without adding a server database |
Principal request lifecycles
The browser deliberately serializes expensive per-cell rendering where needed. This keeps a network workflow inside the backend capacity budget while preserving a single cancellation boundary for the whole operation.
Run Sector
Single selected cell/api/simulate and /api/coverage-gaps execute together.Evaluate or Optimize Network
Two to six selected cells/api/simulate call per selected cell to avoid RF-capacity collisions.Analyze Interference
4G or 5G; two to six cellsRecommend Candidate Sites
4G or 5G network plan with a drawn areaValidate Measurements
CSV evidence for 4G or 5GInspect and report
Client-side detail flow.atom-project.json files.5G communication-path overlay
Core Lab is intentionally independent from radio interference. It describes control and user-plane paths for selected 5G cells; Core scenarios do not alter RF propagation, and radio load does not alter Core function health.
NG-RAN
Fallback and session paths
direct_xn, ng_fallback, or unreachable with a reason.Core functions and scenarios
Without configured Open5GS endpoints, the adapter reports a deterministic simulated_overlay. With endpoints, it probes external state briefly and retains the same frontend-facing JSON contracts.
Resource and reliability controls
RF jobs are intentionally bounded. The frontend avoids stale commits and unnecessary concurrency; the backend rejects oversized or excess work before it can monopolize the process.
| Control | Current behavior | User-visible result |
|---|---|---|
| Request body limit | 1 MiB for incoming requests | 413 for oversized bodies |
| RF job limiter | 2 concurrent jobs by default through MAX_CONCURRENT_RF_REQUESTS | 429 plus Retry-After when saturated |
| Per-job workers | At most 4 Go workers for expensive RF operations | Predictable CPU pressure per request |
| Client cancellation | Superseded settings abort the active RF request channel | Old work stops when possible |
| Latest-response check | Request ID and settings fingerprint must still match | Old responses cannot replace newer results |
| Network render queue | Per-cell ray requests run sequentially | Network evaluation avoids self-generated overload |
| HTTP timeouts | 5s headers, 15s read, 120s write, 60s idle | Long RF writes are allowed without unbounded connections |
| Liveness | /healthz reports the process and loaded counts | Process monitoring remains independent of readiness |
| Readiness | /readyz requires buildings, towers, and frontend bundle | 503 until the instance can serve the application |
Deployment topology
The same interfaces are used in development and production; only asset serving and the optional Core adapter boundary change.
Local development
Vite serves the frontend on port 5173 and proxies API, health, and readiness requests to the Go service on port 8080.
- Fast frontend refresh and source maps
- Go service reads data from repository-relative paths
- Core adapter can run separately on port 8090
Production container
A multi-stage Docker build compiles the React bundle and Go binary, then copies both plus the data into a non-root Alpine runtime.
- One public port: 8080
- Go serves both static frontend and API
- Readiness healthcheck is built into the image
Optional Core Lab profile
The compose overlay enables the backend Core proxy and starts the adapter sidecar. The default app remains Core-free.
- Stable proxy routes remain under
/api/core/* - Adapter is internal to the compose network
- Open5GS integration is optional
Internet-facing boundary
The API has no built-in authentication. Public deployments need a trusted reverse proxy or gateway for TLS, authentication, and external rate policy.
- Keep
/healthzand/readyzavailable to probes - Preserve the 120 second RF response window
- Do not expose the adapter directly without need
Model and trust boundaries
Architecture quality includes stating what the system does not claim. These limits apply to the current implementation and reports.
No diffraction, reflection-heavy multipath, fast fading, sidelobes, MIMO beamforming gain, scheduling, adjacent-channel leakage, or uplink model.
Static OSM/OpenCellID-derived geometry and synthetic demand can be incomplete or stale. Confidence is context, not calibration.
RSRP, SINR, RSRQ, RSSI, and coverage values remain deterministic planning estimates. Uploaded field data validates residuals; its optional global bias correction is not full propagation calibration.
No authentication, server-side project database, multi-user collaboration, or job queue is included. Project history is durable only in the current browser or an exported project file.