diff --git a/app/vmselect/main.go b/app/vmselect/main.go
index 71c2c00b1e..af80bd4131 100644
--- a/app/vmselect/main.go
+++ b/app/vmselect/main.go
@@ -477,7 +477,6 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
 		return true
 	case "/expand-with-exprs":
 		expandWithExprsRequests.Inc()
-		httpserver.EnableCORS(w, r)
 		prometheus.ExpandWithExprs(w, r)
 		return true
 	case "/api/v1/rules", "/rules":
diff --git a/app/vmselect/prometheus/expand-with-exprs.qtpl b/app/vmselect/prometheus/expand-with-exprs.qtpl
index 5e42d71a57..604f10fd0d 100644
--- a/app/vmselect/prometheus/expand-with-exprs.qtpl
+++ b/app/vmselect/prometheus/expand-with-exprs.qtpl
@@ -54,6 +54,28 @@ textarea { margin: 1em }
 	{% endif %}
 {% endfunc %}
 
+{% func ExpandWithExprsJSONResponse(q string) %}
+    {% if len(q) == 0 %}
+        {
+            "status": "error",
+            "error": "query string cannot be empty"
+        }
+        {% return %}
+    {% endif %}
+
+{
+    {% code expr, err := metricsql.Parse(q) %}
+    {% if err != nil %}
+        "status": "error",
+        "error": {%q fmt.Sprintf("Cannot parse query: %s", err) %}
+    {% else %}
+        {% code expr = metricsql.Optimize(expr) %}
+        "status": "success",
+        "expr": {%qz expr.AppendString(nil) %}
+    {% endif %}
+}
+{% endfunc %}
+
 {% endstripspace %}
 
 {% func withExprsTutorial() %}
@@ -244,31 +266,3 @@ WITH (
 </pre>
 
 {% endfunc %}
-
-{% stripspace %}
-{% func ExpandWithExprsJSONResponse(q string) %}
-    {%= expandWithExprsJSON(q) %}
-{% endfunc %}
-
-{% func expandWithExprsJSON(q string) %}
-    {% if len(q) == 0 %}
-        {
-            "status": "error",
-            "error": "query string cannot be empty"
-        }
-        {% return %}
-    {% endif %}
-
-{
-    {% code	expr, err := metricsql.Parse(q) %}
-        {% if err != nil %}
-                "status": "error",
-                "error": {%q= fmt.Sprintf("Cannot parse query: %s", err) %}
-        {% else %}
-        {% code expr = metricsql.Optimize(expr) %}
-                "status": "success",
-                "expr": {%q= string(expr.AppendString(nil)) %}
-        {% endif %}
-}
-{% endfunc %}
-{% endstripspace %}
diff --git a/app/vmselect/prometheus/expand-with-exprs.qtpl.go b/app/vmselect/prometheus/expand-with-exprs.qtpl.go
index aa65c7fec0..2fd45395bc 100644
--- a/app/vmselect/prometheus/expand-with-exprs.qtpl.go
+++ b/app/vmselect/prometheus/expand-with-exprs.qtpl.go
@@ -125,9 +125,72 @@ func expandWithExprs(q string) string {
 //line app/vmselect/prometheus/expand-with-exprs.qtpl:55
 }
 
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:59
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:57
+func StreamExpandWithExprsJSONResponse(qw422016 *qt422016.Writer, q string) {
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:58
+	if len(q) == 0 {
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:58
+		qw422016.N().S(`{"status": "error","error": "query string cannot be empty"}`)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:63
+		return
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:64
+	}
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:64
+	qw422016.N().S(`{`)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:67
+	expr, err := metricsql.Parse(q)
+
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:68
+	if err != nil {
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:68
+		qw422016.N().S(`"status": "error","error":`)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:70
+		qw422016.E().Q(fmt.Sprintf("Cannot parse query: %s", err))
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:71
+	} else {
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:72
+		expr = metricsql.Optimize(expr)
+
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:72
+		qw422016.N().S(`"status": "success","expr":`)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:74
+		qw422016.E().QZ(expr.AppendString(nil))
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:75
+	}
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:75
+	qw422016.N().S(`}`)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+}
+
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+func WriteExpandWithExprsJSONResponse(qq422016 qtio422016.Writer, q string) {
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	qw422016 := qt422016.AcquireWriter(qq422016)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	StreamExpandWithExprsJSONResponse(qw422016, q)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	qt422016.ReleaseWriter(qw422016)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+}
+
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+func ExpandWithExprsJSONResponse(q string) string {
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	qb422016 := qt422016.AcquireByteBuffer()
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	WriteExpandWithExprsJSONResponse(qb422016, q)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	qs422016 := string(qb422016.B)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	qt422016.ReleaseByteBuffer(qb422016)
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+	return qs422016
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
+}
+
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:81
 func streamwithExprsTutorial(qw422016 *qt422016.Writer) {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:59
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:81
 	qw422016.N().S(`
 <h3>Tutorial for WITH expressions in <a href="https://docs.victoriametrics.com/MetricsQL.html">MetricsQL</a></h3>
 
@@ -316,127 +379,31 @@ WITH (
 </pre>
 
 `)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 }
 
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 func writewithExprsTutorial(qq422016 qtio422016.Writer) {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	streamwithExprsTutorial(qw422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	qt422016.ReleaseWriter(qw422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 }
 
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 func withExprsTutorial() string {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	qb422016 := qt422016.AcquireByteBuffer()
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	writewithExprsTutorial(qb422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
-	qs422016 := string(qb422016.B)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
-	qt422016.ReleaseByteBuffer(qb422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
-	return qs422016
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:246
-}
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:249
-func StreamExpandWithExprsJSONResponse(qw422016 *qt422016.Writer, q string) {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:250
-	streamexpandWithExprsJSON(qw422016, q)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-}
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-func WriteExpandWithExprsJSONResponse(qq422016 qtio422016.Writer, q string) {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	qw422016 := qt422016.AcquireWriter(qq422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	StreamExpandWithExprsJSONResponse(qw422016, q)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	qt422016.ReleaseWriter(qw422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-}
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-func ExpandWithExprsJSONResponse(q string) string {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	qb422016 := qt422016.AcquireByteBuffer()
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	WriteExpandWithExprsJSONResponse(qb422016, q)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	qs422016 := string(qb422016.B)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	qt422016.ReleaseByteBuffer(qb422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-	return qs422016
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:251
-}
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:253
-func streamexpandWithExprsJSON(qw422016 *qt422016.Writer, q string) {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:254
-	if len(q) == 0 {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:254
-		qw422016.N().S(`{"status": "error","error": "query string cannot be empty"}`)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:259
-		return
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:260
-	}
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:260
-	qw422016.N().S(`{`)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:263
-	expr, err := metricsql.Parse(q)
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:264
-	if err != nil {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:264
-		qw422016.N().S(`"status": "error","error":`)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:266
-		qw422016.N().Q(fmt.Sprintf("Cannot parse query: %s", err))
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:267
-	} else {
 //line app/vmselect/prometheus/expand-with-exprs.qtpl:268
-		expr = metricsql.Optimize(expr)
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
-		qw422016.N().S(`"status": "success","expr":`)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:270
-		qw422016.N().Q(string(expr.AppendString(nil)))
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:271
-	}
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:271
-	qw422016.N().S(`}`)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-}
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-func writeexpandWithExprsJSON(qq422016 qtio422016.Writer, q string) {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-	qw422016 := qt422016.AcquireWriter(qq422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-	streamexpandWithExprsJSON(qw422016, q)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-	qt422016.ReleaseWriter(qw422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-}
-
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-func expandWithExprsJSON(q string) string {
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-	qb422016 := qt422016.AcquireByteBuffer()
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
-	writeexpandWithExprsJSON(qb422016, q)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
 	qs422016 := string(qb422016.B)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	qt422016.ReleaseByteBuffer(qb422016)
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 	return qs422016
-//line app/vmselect/prometheus/expand-with-exprs.qtpl:273
+//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
 }
diff --git a/app/vmselect/prometheus/prometheus.go b/app/vmselect/prometheus/prometheus.go
index d74bbb9b64..a6a3f949e3 100644
--- a/app/vmselect/prometheus/prometheus.go
+++ b/app/vmselect/prometheus/prometheus.go
@@ -60,13 +60,13 @@ const defaultStep = 5 * 60 * 1000
 
 // ExpandWithExprs handles the request to /expand-with-exprs
 func ExpandWithExprs(w http.ResponseWriter, r *http.Request) {
-
 	query := r.FormValue("query")
 	format := r.FormValue("format")
 	bw := bufferedwriter.Get(w)
 	defer bufferedwriter.Put(bw)
 	if format == "json" {
 		w.Header().Set("Content-Type", "application/json")
+		httpserver.EnableCORS(w, r)
 		WriteExpandWithExprsJSONResponse(bw, query)
 	} else {
 		WriteExpandWithExprsResponse(bw, query)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 7dfbca9efb..e7bbf804de 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -33,7 +33,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
 * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): support new filtering options `filter` and `node_filter` for [consul service discovery](https://docs.victoriametrics.com/sd_configs.html#consul_sd_configs). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4183) for details.
 * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): support new [consulagent service discovery](https://docs.victoriametrics.com/sd_configs.html#consulagent_sd_configs). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3953) for details.
 * FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): add support for [different time formats](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats) for `--vm-native-filter-time-start` and `--vm-native-filter-time-end` command-line flags. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4091).
-* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): integrate WITH template playground. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3811).
+* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add `WITH template` playground to `vmui`. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3811).
 * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add a comparison of data from the previous day with data from the current day to the `Cardinality Explorer`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3967).
 * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): display histogram metrics as a heatmap in the `explore metrics` tab. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4111).
 * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add support of recursive globs for `-rule` and `-rule.templates` by using `**` in the glob pattern. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4041).