diff --git a/layers/dot-cams/al/get_data.py b/layers/dot-cams/al/get_data.py
new file mode 100755
index 0000000..8c732dc
--- /dev/null
+++ b/layers/dot-cams/al/get_data.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python3
+
+import requests
+import json
+
+cameras = []
+
+res = requests.get("https://api.algotraffic.com/v3.0/Cameras")
+res.raise_for_status()
+
+for c in res.json():
+ cameras.append({
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [c['location']['longitude'], c['location']['latitude']], # yes, [lon, lat] since it's [x, y]
+ },
+ "properties": {
+ 'originalData': c,
+ },
+ })
+
+geojson = {
+ "type": "FeatureCollection",
+ "features": cameras,
+}
+
+with open("data.geojson", "w") as f:
+ f.write(json.dumps(geojson))
+
+print(f"{len(cameras)} locations found")
diff --git a/layers/dot-cams/al/layer.js b/layers/dot-cams/al/layer.js
new file mode 100644
index 0000000..cffc4fb
--- /dev/null
+++ b/layers/dot-cams/al/layer.js
@@ -0,0 +1,46 @@
+import VectorLayer from 'ol/layer/Vector';
+import {Vector as VectorSource} from 'ol/source.js';
+import GeoJSON from 'ol/format/GeoJSON.js';
+
+import Hls from 'hls.js';
+
+import {Style} from 'ol/style.js';
+import Icon from 'ol/style/Icon.js';
+
+import url from './data.geojson?url'; // TODO: remove `?url`?
+import pin from './pin.svg?url'; // TODO: remove `?url`?
+
+const vectorLayer = new VectorLayer({
+ source: new VectorSource({
+ url: url,
+ format: new GeoJSON,
+ }),
+ style: new Style({
+ image: new Icon({
+ anchor: [0.5, 1],
+ src: pin,
+ }),
+ }),
+});
+
+vectorLayer.customPopup = function(feature) {
+ return ``;
+};
+
+vectorLayer.customPopupCallback = function(feature) {
+
+ const video = document.getElementById('popupVideo');
+
+ const videoSrc = feature.values_.originalData.hlsUrl;
+ if (Hls.isSupported()) {
+ var hls = new Hls();
+ hls.loadSource(videoSrc);
+ hls.attachMedia(video);
+ }
+ // iDevice support, untested (only works in Safari; required for iPhones)
+ else if (video.canPlayType('application/vnd.apple.mpegurl')) {
+ video.src = videoSrc;
+ }
+}
+
+export default vectorLayer;
diff --git a/layers/dot-cams/al/pin.svg b/layers/dot-cams/al/pin.svg
new file mode 100644
index 0000000..fb93212
--- /dev/null
+++ b/layers/dot-cams/al/pin.svg
@@ -0,0 +1,21 @@
+
+