diff --git a/public/resources/gallery/config.json b/public/resources/gallery/config.json
new file mode 100644
index 000000000..c06c47504
--- /dev/null
+++ b/public/resources/gallery/config.json
@@ -0,0 +1,32 @@
+{
+ "options": {
+ "paths": {
+ "root": "/usr/src/app/node_modules/tileserver-gl-styles",
+ "fonts": "fonts",
+ "styles": "styles",
+ "mbtiles": "/data",
+ "pmtiles": "/data"
+ },
+ "staticAttributionText": "© OpenStreetMap",
+ "watermark": "THIS IS A TEST WATERMARK",
+ "allowRemoteMarkerIcons": true
+ },
+ "styles": {
+ "basic-preview": {
+ "style": "basic-preview/style.json",
+ "tilejson": {
+ "bounds": [
+ 8.275,
+ 47.225,
+ 8.8,
+ 47.533
+ ]
+ }
+ }
+ },
+ "data": {
+ "v3": {
+ "mbtiles": "/usr/src/app/public/resources/gallery/zurich_switzerland.mbtiles"
+ }
+ }
+}
diff --git a/public/resources/gallery/encoded-path-auto.png b/public/resources/gallery/encoded-path-auto.png
new file mode 100644
index 000000000..ee1ab690a
Binary files /dev/null and b/public/resources/gallery/encoded-path-auto.png differ
diff --git a/public/resources/gallery/gallery.html b/public/resources/gallery/gallery.html
new file mode 100644
index 000000000..216a95632
--- /dev/null
+++ b/public/resources/gallery/gallery.html
@@ -0,0 +1,127 @@
+
+
+
+
+ Tileserver-gl tests
+
+
+
+
+
+
+Tileserver-gl tests
+A fast way to visually check for regressions. Each row shows: a test picture, the expected output, then the difference with
pixelmatch.
+Put zurich_switzerland.mbtiles in public/resources/gallery/ then run with:
+docker build . && docker run --rm -it -p 8080:8080 $(docker build -q .) -V --config /usr/src/app/public/resources/gallery/config.json
+
+
+Interactive vector
+
+
+
+Interactive raster
+
+
+
+Loading...
+
+
+
+
+
+
+More tests we could write:
+
+- endpoint /styles/{id}/static/{minx},{miny},{maxx},{maxy}/{width}x{height}[@2x].{format} (area-based)
+
+- arg latlng - indicates coordinates are in lat,lng
+
+- padding
+
+- border + borderwidth
+
+- fill|stroke|width global vs local
+
+
+
diff --git a/public/resources/gallery/interactive-raster.png b/public/resources/gallery/interactive-raster.png
new file mode 100644
index 000000000..1a2421ea6
Binary files /dev/null and b/public/resources/gallery/interactive-raster.png differ
diff --git a/public/resources/gallery/interactive-vector.png b/public/resources/gallery/interactive-vector.png
new file mode 100644
index 000000000..d5e111f5d
Binary files /dev/null and b/public/resources/gallery/interactive-vector.png differ
diff --git a/public/resources/gallery/linecap-linejoin-bevel-square.png b/public/resources/gallery/linecap-linejoin-bevel-square.png
new file mode 100644
index 000000000..6cde5372a
Binary files /dev/null and b/public/resources/gallery/linecap-linejoin-bevel-square.png differ
diff --git a/public/resources/gallery/linecap-linejoin-round-round.png b/public/resources/gallery/linecap-linejoin-round-round.png
new file mode 100644
index 000000000..de1f2a451
Binary files /dev/null and b/public/resources/gallery/linecap-linejoin-round-round.png differ
diff --git a/public/resources/gallery/markers.png b/public/resources/gallery/markers.png
new file mode 100644
index 000000000..61f0984b3
Binary files /dev/null and b/public/resources/gallery/markers.png differ
diff --git a/public/resources/gallery/path-auto.png b/public/resources/gallery/path-auto.png
new file mode 100644
index 000000000..617e19125
Binary files /dev/null and b/public/resources/gallery/path-auto.png differ
diff --git a/public/resources/gallery/pixelmatch-5.3.0.0.js b/public/resources/gallery/pixelmatch-5.3.0.0.js
new file mode 100644
index 000000000..61726b99f
--- /dev/null
+++ b/public/resources/gallery/pixelmatch-5.3.0.0.js
@@ -0,0 +1,8 @@
+/**
+ * Minified by jsDelivr using Terser v5.10.0.
+ * Original file: /npm/pixelmatch@5.3.0/index.js
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+"use strict";module.exports=pixelmatch;const defaultOptions={threshold:.1,includeAA:!1,alpha:.1,aaColor:[255,255,0],diffColor:[255,0,0],diffColorAlt:null,diffMask:!1};function pixelmatch(t,e,r,n,i,a){if(!isPixelData(t)||!isPixelData(e)||r&&!isPixelData(r))throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected.");if(t.length!==e.length||r&&r.length!==t.length)throw new Error("Image sizes do not match.");if(t.length!==n*i*4)throw new Error("Image data size does not match width/height.");a=Object.assign({},defaultOptions,a);const l=n*i,o=new Uint32Array(t.buffer,t.byteOffset,l),f=new Uint32Array(e.buffer,e.byteOffset,l);let s=!0;for(let t=0;td?a.includeAA||!antialiased(t,o,l,n,i,e)&&!antialiased(e,o,l,n,i,t)?(r&&drawPixel(r,f,...s<0&&a.diffColorAlt||a.diffColor),u++):r&&!a.diffMask&&drawPixel(r,f,...a.aaColor):r&&(a.diffMask||drawGrayPixel(t,f,a.alpha,r))}return u}function isPixelData(t){return ArrayBuffer.isView(t)&&1===t.constructor.BYTES_PER_ELEMENT}function antialiased(t,e,r,n,i,a){const l=Math.max(e-1,0),o=Math.max(r-1,0),f=Math.min(e+1,n-1),s=Math.min(r+1,i-1),d=4*(r*n+e);let u,c,h,b,g=e===l||e===f||r===o||r===s?1:0,x=0,y=0;for(let i=l;i<=f;i++)for(let a=o;a<=s;a++){if(i===e&&a===r)continue;const l=colorDelta(t,t,d,4*(a*n+i),!0);if(0===l){if(g++,g>2)return!1}else ly&&(y=l,h=i,b=a)}return 0!==x&&0!==y&&(hasManySiblings(t,u,c,n,i)&&hasManySiblings(a,u,c,n,i)||hasManySiblings(t,h,b,n,i)&&hasManySiblings(a,h,b,n,i))}function hasManySiblings(t,e,r,n,i){const a=Math.max(e-1,0),l=Math.max(r-1,0),o=Math.min(e+1,n-1),f=Math.min(r+1,i-1),s=4*(r*n+e);let d=e===a||e===o||r===l||r===f?1:0;for(let i=a;i<=o;i++)for(let a=l;a<=f;a++){if(i===e&&a===r)continue;const l=4*(a*n+i);if(t[s]===t[l]&&t[s+1]===t[l+1]&&t[s+2]===t[l+2]&&t[s+3]===t[l+3]&&d++,d>2)return!0}return!1}function colorDelta(t,e,r,n,i){let a=t[r+0],l=t[r+1],o=t[r+2],f=t[r+3],s=e[n+0],d=e[n+1],u=e[n+2],c=e[n+3];if(f===c&&a===s&&l===d&&o===u)return 0;f<255&&(f/=255,a=blend(a,f),l=blend(l,f),o=blend(o,f)),c<255&&(c/=255,s=blend(s,c),d=blend(d,c),u=blend(u,c));const h=rgb2y(a,l,o),b=rgb2y(s,d,u),g=h-b;if(i)return g;const x=rgb2i(a,l,o)-rgb2i(s,d,u),y=rgb2q(a,l,o)-rgb2q(s,d,u),M=.5053*g*g+.299*x*x+.1957*y*y;return h>b?-M:M}function rgb2y(t,e,r){return.29889531*t+.58662247*e+.11448223*r}function rgb2i(t,e,r){return.59597799*t-.2741761*e-.32180189*r}function rgb2q(t,e,r){return.21147017*t-.52261711*e+.31114694*r}function blend(t,e){return 255+(t-255)*e}function drawPixel(t,e,r,n,i){t[e+0]=r,t[e+1]=n,t[e+2]=i,t[e+3]=255}function drawGrayPixel(t,e,r,n){const i=blend(rgb2y(t[e+0],t[e+1],t[e+2]),r*t[e+3]/255);drawPixel(n,e,i,i,i)}
+//# sourceMappingURL=/sm/c63ff0ee83224674e743a369cf841b9f0a69d1938d5d74c59d8ae9cf4947611a.map
\ No newline at end of file
diff --git a/public/resources/gallery/static-bearing-pitch.png b/public/resources/gallery/static-bearing-pitch.png
new file mode 100644
index 000000000..d00b6072d
Binary files /dev/null and b/public/resources/gallery/static-bearing-pitch.png differ
diff --git a/public/resources/gallery/static-bearing.png b/public/resources/gallery/static-bearing.png
new file mode 100644
index 000000000..8ff0d84b4
Binary files /dev/null and b/public/resources/gallery/static-bearing.png differ
diff --git a/public/resources/gallery/static-lat-lng.png b/public/resources/gallery/static-lat-lng.png
new file mode 100644
index 000000000..2bad26aa8
Binary files /dev/null and b/public/resources/gallery/static-lat-lng.png differ
diff --git a/public/resources/gallery/static-pixel-ratio-2x.png b/public/resources/gallery/static-pixel-ratio-2x.png
new file mode 100644
index 000000000..9ed7f1f9c
Binary files /dev/null and b/public/resources/gallery/static-pixel-ratio-2x.png differ