diff --git a/examples/frontend-links/README.md b/examples/frontend-links/README.md
new file mode 100644
index 00000000..72eddd36
--- /dev/null
+++ b/examples/frontend-links/README.md
@@ -0,0 +1,13 @@
+# reitit-frontend example
+
+## Usage
+
+```clj
+> lein figwheel
+```
+
+Go with browser to http://localhost:3449
+
+## License
+
+Copyright © 2018 Metosin Oy
diff --git a/examples/frontend-links/project.clj b/examples/frontend-links/project.clj
new file mode 100644
index 00000000..189d69fd
--- /dev/null
+++ b/examples/frontend-links/project.clj
@@ -0,0 +1,62 @@
+(defproject frontend "0.1.0-SNAPSHOT"
+ :description "FIXME: write description"
+ :url "http://example.com/FIXME"
+ :license {:name "Eclipse Public License"
+ :url "http://www.eclipse.org/legal/epl-v10.html"}
+
+ :dependencies [[org.clojure/clojure "1.10.0"]
+ [ring-server "0.5.0"]
+ [reagent "0.8.1"]
+ [ring "1.7.1"]
+ [hiccup "1.0.5"]
+ [org.clojure/clojurescript "1.10.520"]
+ [metosin/reitit "0.3.1"]
+ [metosin/reitit-spec "0.3.1"]
+ [metosin/reitit-frontend "0.3.1"]
+ ;; Just for pretty printting the match
+ [fipp "0.6.14"]]
+
+ :plugins [[lein-cljsbuild "1.1.7"]
+ [lein-figwheel "0.5.18"]
+ [cider/cider-nrepl "0.21.1"]]
+
+ :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}
+
+ :source-paths ["src"]
+ :resource-paths ["resources" "target/cljsbuild"]
+
+ :profiles
+ {:dev
+ {:dependencies
+ [[binaryage/devtools "0.9.10"]
+ [cider/piggieback "0.4.0"]
+ [figwheel-sidecar "0.5.18"]]}}
+
+ :cljsbuild
+ {:builds
+ [{:id "app"
+ :figwheel true
+ :source-paths ["src"]
+ :compiler {:main "frontend.core"
+ :asset-path "/js/out"
+ :output-to "target/cljsbuild/public/js/app.js"
+ :output-dir "target/cljsbuild/public/js/out"
+ :source-map true
+ :optimizations :none
+ :pretty-print true
+ :preloads [devtools.preload]
+ :aot-cache true}}
+ {:id "min"
+ :source-paths ["src"]
+ :compiler {:output-to "target/cljsbuild/public/js/app.js"
+ :output-dir "target/cljsbuild/public/js"
+ :source-map "target/cljsbuild/public/js/app.js.map"
+ :optimizations :advanced
+ :pretty-print false
+ :aot-cache true}}]}
+
+ :figwheel {:http-server-root "public"
+ :server-port 3449
+ :nrepl-port 7002
+ ;; Server index.html for all routes for HTML5 routing
+ :ring-handler backend.server/handler})
diff --git a/examples/frontend-links/resources/public/index.html b/examples/frontend-links/resources/public/index.html
new file mode 100644
index 00000000..ce1dd45b
--- /dev/null
+++ b/examples/frontend-links/resources/public/index.html
@@ -0,0 +1,10 @@
+
+
+
+ Reitit frontend example
+
+
+
+
+
+
diff --git a/examples/frontend-links/src/backend/server.clj b/examples/frontend-links/src/backend/server.clj
new file mode 100644
index 00000000..88171cfa
--- /dev/null
+++ b/examples/frontend-links/src/backend/server.clj
@@ -0,0 +1,11 @@
+(ns backend.server
+ (:require [clojure.java.io :as io]
+ [ring.util.response :as resp]
+ [ring.middleware.content-type :as content-type]))
+
+(def handler
+ (-> (fn [request]
+ (or (resp/resource-response (:uri request) {:root "public"})
+ (-> (resp/resource-response "index.html" {:root "public"})
+ (resp/content-type "text/html"))))
+ content-type/wrap-content-type))
diff --git a/examples/frontend-links/src/frontend/core.cljs b/examples/frontend-links/src/frontend/core.cljs
new file mode 100644
index 00000000..cc84dcf3
--- /dev/null
+++ b/examples/frontend-links/src/frontend/core.cljs
@@ -0,0 +1,147 @@
+(ns frontend.core
+ (:require [clojure.string :as string]
+ [fipp.edn :as fedn]
+ [reagent.core :as r]
+ [reitit.coercion :as rc]
+ [reitit.coercion.spec :as rss]
+ [reitit.frontend :as rf]
+ [reitit.frontend.easy :as rfe]
+ [spec-tools.data-spec :as ds]))
+
+;; Components similar to react-router `Link`, `NavLink` and `Redirect`
+;; with Reitit frontend.
+
+(defn home-page []
+ [:div
+ [:h2 "Welcome to frontend"]
+ [:p "This is home page"]])
+
+(defn about-page []
+ [:div
+ [:h2 "About frontend"]
+ [:p "This is about page"]])
+
+(defn redirect!
+ "If `push` is truthy, previous page will be left in history."
+ [{:keys [to path-params query-params push]}]
+ (if push
+ (rfe/push-state to path-params query-params)
+ (rfe/replace-state to path-params query-params)))
+
+(defn Redirect
+ "Component that only causes a redirect side-effect."
+ [props]
+ (r/create-class
+ {:component-did-mount (fn [this] (redirect! (r/props this)))
+ :component-did-update (fn [this [_ prev-props]]
+ (if (not= (r/props this) prev-props)
+ (redirect! (r/props this))))
+ :render (fn [this] nil)}))
+
+(defn item-page [match]
+ (let [{:keys [path query]} (:parameters match)
+ {:keys [id]} path]
+ (if (< id 1)
+ [Redirect {:to ::frontpage}]
+ [:div
+ [:h2 "Selected item " id]
+ (when (:foo query)
+ [:p "Optional foo query param: " (:foo query)])])))
+
+(def routes
+ [["/"
+ {:name ::frontpage
+ :view home-page}]
+
+ ["/about"
+ {:name ::about
+ :view about-page}]
+
+ ["/item/:id"
+ {:name ::item
+ :view item-page
+ :parameters
+ {:path {:id int?}
+ :query {(ds/opt :foo) keyword?}}}]])
+
+(def router
+ (rf/router routes {:data {:coercion rss/coercion}}))
+
+(defonce current-match (r/atom nil))
+
+(defn- resolve-href
+ [to path-params query-params]
+ (if (keyword? to)
+ (rfe/href to path-params query-params)
+ (let [match (rf/match-by-path router to)
+ route (-> match :data :name)
+ params (or path-params (:path-params match))
+ query (or query-params (:query-params match))]
+ (if match
+ (rfe/href route params query)
+ to))))
+
+(defn Link
+ [{:keys [to path-params query-params active]} & children]
+ (let [href (resolve-href to path-params query-params)]
+ (into
+ [:a {:href href} (when active "> ")] ;; Apply styles or whatever
+ children)))
+
+(defn- name-matches?
+ [name path-params match]
+ (and (= name (-> match :data :name))
+ (= (not-empty path-params)
+ (-> match :parameters :path not-empty))))
+
+(defn- url-matches?
+ [url match]
+ (= (-> url (string/split #"\?") first)
+ (:path match)))
+
+(defn NavLink
+ [{:keys [to path-params] :as props} & children]
+ (let [active (or (name-matches? to path-params @current-match)
+ (url-matches? to @current-match))]
+ [Link (assoc props :active active) children]))
+
+(defn current-page []
+ [:div
+
+ [:h4 "Link"]
+ [:ul
+ [:li [Link {:to ::frontpage} "Frontpage"]]
+ [:li [Link {:to "/about"} "About"]]
+ [:li [Link {:to ::item :path-params {:id 1}} "Item 1"]]
+ [:li [Link {:to "/item/2?foo=bar"} "Item 2"]]
+ [:li [Link {:to "/item/-1"} "Item -1 (redirects to frontpage)"]]
+ [:li [Link {:to "http://www.google.fi"} "Google"]]]
+
+ [:h4 "NavLink"]
+ [:ul
+ [:li [NavLink {:to ::frontpage} "Frontpage"]]
+ [:li [NavLink {:to "/about"} "About"]]
+ [:li [NavLink {:to ::item :path-params {:id 1}} "Item 1"]]
+ [:li [NavLink {:to "/item/2?foo=bar"} "Item 2"]]
+ [:li [NavLink {:to "/item/-1"} "Item -1 (redirects to frontpage)"]]
+ [:li [NavLink {:to "http://www.google.fi"} "Google"]]]
+
+ (if @current-match
+ (let [view (:view (:data @current-match))]
+ [view @current-match]))
+
+ [:pre (with-out-str (fedn/pprint @current-match))]])
+
+(defn init! []
+ (rfe/start!
+ router
+ (fn [m] (reset! current-match m))
+ ;; set to false to enable HistoryAPI
+ {:use-fragment true})
+ (r/render [current-page] (.getElementById js/document "app")))
+
+(init!)
+
+(comment
+ (rf/match-by-path router "/about?kissa=1&koira=true")
+ (rf/match-by-path router "/item/2?kissa=1&koira=true"))
diff --git a/examples/frontend-prompt/README.md b/examples/frontend-prompt/README.md
new file mode 100644
index 00000000..72eddd36
--- /dev/null
+++ b/examples/frontend-prompt/README.md
@@ -0,0 +1,13 @@
+# reitit-frontend example
+
+## Usage
+
+```clj
+> lein figwheel
+```
+
+Go with browser to http://localhost:3449
+
+## License
+
+Copyright © 2018 Metosin Oy
diff --git a/examples/frontend-prompt/project.clj b/examples/frontend-prompt/project.clj
new file mode 100644
index 00000000..189d69fd
--- /dev/null
+++ b/examples/frontend-prompt/project.clj
@@ -0,0 +1,62 @@
+(defproject frontend "0.1.0-SNAPSHOT"
+ :description "FIXME: write description"
+ :url "http://example.com/FIXME"
+ :license {:name "Eclipse Public License"
+ :url "http://www.eclipse.org/legal/epl-v10.html"}
+
+ :dependencies [[org.clojure/clojure "1.10.0"]
+ [ring-server "0.5.0"]
+ [reagent "0.8.1"]
+ [ring "1.7.1"]
+ [hiccup "1.0.5"]
+ [org.clojure/clojurescript "1.10.520"]
+ [metosin/reitit "0.3.1"]
+ [metosin/reitit-spec "0.3.1"]
+ [metosin/reitit-frontend "0.3.1"]
+ ;; Just for pretty printting the match
+ [fipp "0.6.14"]]
+
+ :plugins [[lein-cljsbuild "1.1.7"]
+ [lein-figwheel "0.5.18"]
+ [cider/cider-nrepl "0.21.1"]]
+
+ :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}
+
+ :source-paths ["src"]
+ :resource-paths ["resources" "target/cljsbuild"]
+
+ :profiles
+ {:dev
+ {:dependencies
+ [[binaryage/devtools "0.9.10"]
+ [cider/piggieback "0.4.0"]
+ [figwheel-sidecar "0.5.18"]]}}
+
+ :cljsbuild
+ {:builds
+ [{:id "app"
+ :figwheel true
+ :source-paths ["src"]
+ :compiler {:main "frontend.core"
+ :asset-path "/js/out"
+ :output-to "target/cljsbuild/public/js/app.js"
+ :output-dir "target/cljsbuild/public/js/out"
+ :source-map true
+ :optimizations :none
+ :pretty-print true
+ :preloads [devtools.preload]
+ :aot-cache true}}
+ {:id "min"
+ :source-paths ["src"]
+ :compiler {:output-to "target/cljsbuild/public/js/app.js"
+ :output-dir "target/cljsbuild/public/js"
+ :source-map "target/cljsbuild/public/js/app.js.map"
+ :optimizations :advanced
+ :pretty-print false
+ :aot-cache true}}]}
+
+ :figwheel {:http-server-root "public"
+ :server-port 3449
+ :nrepl-port 7002
+ ;; Server index.html for all routes for HTML5 routing
+ :ring-handler backend.server/handler})
diff --git a/examples/frontend-prompt/resources/public/index.html b/examples/frontend-prompt/resources/public/index.html
new file mode 100644
index 00000000..ce1dd45b
--- /dev/null
+++ b/examples/frontend-prompt/resources/public/index.html
@@ -0,0 +1,10 @@
+
+
+
+ Reitit frontend example
+
+
+
+
+
+
diff --git a/examples/frontend-prompt/src/backend/server.clj b/examples/frontend-prompt/src/backend/server.clj
new file mode 100644
index 00000000..88171cfa
--- /dev/null
+++ b/examples/frontend-prompt/src/backend/server.clj
@@ -0,0 +1,11 @@
+(ns backend.server
+ (:require [clojure.java.io :as io]
+ [ring.util.response :as resp]
+ [ring.middleware.content-type :as content-type]))
+
+(def handler
+ (-> (fn [request]
+ (or (resp/resource-response (:uri request) {:root "public"})
+ (-> (resp/resource-response "index.html" {:root "public"})
+ (resp/content-type "text/html"))))
+ content-type/wrap-content-type))
diff --git a/examples/frontend-prompt/src/frontend/core.cljs b/examples/frontend-prompt/src/frontend/core.cljs
new file mode 100644
index 00000000..27754c1d
--- /dev/null
+++ b/examples/frontend-prompt/src/frontend/core.cljs
@@ -0,0 +1,70 @@
+(ns frontend.core
+ (:require [fipp.edn :as fedn]
+ [reagent.core :as r]
+ [reitit.coercion :as rc]
+ [reitit.coercion.spec :as rss]
+ [reitit.frontend :as rf]
+ [reitit.frontend.easy :as rfe]
+ [spec-tools.data-spec :as ds]))
+
+;; Implementing conditional prompt on navigation with Reitit frontend.
+
+(defn home-page []
+ [:div
+ [:h2 "Home"]
+ [:p "You will not be prompted to leave this page"]])
+
+(defn prompt-page []
+ [:div
+ [:h2 "Prompt"]
+ [:p "You will be prompted to leave this page"]])
+
+(def routes
+ [["/"
+ {:name ::home
+ :view home-page}]
+
+ ["/prompt"
+ {:name ::prompt
+ :view prompt-page
+ ;; Routes can contain arbitrary keys so we add custom :prompt
+ ;; key here. See how it's handled in `on-navigate` function.
+ :prompt "Are you sure you want to leave?"
+ ;; It would be possible to define a function here that resolves
+ ;; wheter prompting is needed or not but we'll keep it simple.
+ }]])
+
+(def router
+ (rf/router routes {:data {:coercion rss/coercion}}))
+
+(defonce current-match (r/atom nil))
+
+(defn current-page []
+ [:div
+
+ [:ul
+ [:li [:a {:href (rfe/href ::home)} "Home"]]
+ [:li [:a {:href (rfe/href ::prompt)} "Prompt page"]]]
+
+ (if @current-match
+ (let [view (-> @current-match :data :view)]
+ [view @current-match]))
+ [:pre (with-out-str (fedn/pprint @current-match))]])
+
+(defn on-navigate [m]
+ (if-let [prompt (and (not= @current-match m)
+ (-> @current-match :data :prompt))]
+ (if (js/window.confirm prompt) ;; Returns true if OK is pressed.
+ (reset! current-match m)
+ (.back js/window.history)) ;; Restore browser location
+ (reset! current-match m)))
+
+(defn init! []
+ (rfe/start!
+ router
+ on-navigate
+ ;; set to false to enable HistoryAPI
+ {:use-fragment true})
+ (r/render [current-page] (.getElementById js/document "app")))
+
+(init!)
diff --git a/examples/frontend-re-frame/README.md b/examples/frontend-re-frame/README.md
new file mode 100644
index 00000000..f5b31f0f
--- /dev/null
+++ b/examples/frontend-re-frame/README.md
@@ -0,0 +1,26 @@
+# frontend-re-frame
+
+A [re-frame](https://github.com/Day8/re-frame) application designed to ... well, that part is up to you.
+
+## Development Mode
+
+### Run application:
+
+```
+lein clean
+lein figwheel dev
+```
+
+Figwheel will automatically push cljs changes to the browser.
+
+Wait a bit, then browse to [http://localhost:3449](http://localhost:3449).
+
+## Production Build
+
+
+To compile clojurescript to javascript:
+
+```
+lein clean
+lein cljsbuild once min
+```
diff --git a/examples/frontend-re-frame/project.clj b/examples/frontend-re-frame/project.clj
new file mode 100644
index 00000000..b487ce7c
--- /dev/null
+++ b/examples/frontend-re-frame/project.clj
@@ -0,0 +1,56 @@
+(defproject frontend-re-frame "0.1.0-SNAPSHOT"
+ :dependencies [[org.clojure/clojure "1.10.0"]
+ [org.clojure/clojurescript "1.10.520"]
+ [metosin/reitit "0.3.1"]
+ [reagent "0.8.1"]
+ [re-frame "0.10.6"]]
+
+ :plugins [[lein-cljsbuild "1.1.7"]
+ [lein-figwheel "0.5.18"]
+ [cider/cider-nrepl "0.21.1"]]
+
+ :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}
+ :min-lein-version "2.5.3"
+ :source-paths ["src/clj" "src/cljs"]
+ :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
+ :figwheel
+ {:css-dirs ["resources/public/css"]
+ :server-port 3449
+ :nrepl-port 7002
+ :ring-handler backend.server/handler}
+
+ :profiles
+ {:dev
+ {:dependencies
+ [[binaryage/devtools "0.9.10"]
+ [cider/piggieback "0.4.0"]
+ [figwheel-sidecar "0.5.18"]]
+
+ :plugins [[lein-figwheel "0.5.18"]]}
+ :prod {}}
+
+ :cljsbuild
+ {:builds
+ [{:id "dev"
+ :source-paths ["src/cljs"]
+ :figwheel {:on-jsload "frontend-re-frame.core/mount-root"}
+ :compiler {:main frontend-re-frame.core
+ :output-to "resources/public/js/compiled/app.js"
+ :output-dir "resources/public/js/compiled/out"
+ :asset-path "js/compiled/out"
+ :source-map-timestamp true
+ :preloads [devtools.preload]
+ :external-config {:devtools/config {:features-to-install :all}}
+ }}
+
+ {:id "min"
+ :source-paths ["src/cljs"]
+ :compiler {:main frontend-re-frame.core
+ :output-to "resources/public/js/compiled/app.js"
+ :optimizations :advanced
+ :closure-defines {goog.DEBUG false}
+ :pretty-print false}}
+
+
+ ]}
+ )
diff --git a/examples/frontend-re-frame/resources/public/index.html b/examples/frontend-re-frame/resources/public/index.html
new file mode 100644
index 00000000..c17ffaac
--- /dev/null
+++ b/examples/frontend-re-frame/resources/public/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/frontend-re-frame/src/clj/backend/server.clj b/examples/frontend-re-frame/src/clj/backend/server.clj
new file mode 100644
index 00000000..88171cfa
--- /dev/null
+++ b/examples/frontend-re-frame/src/clj/backend/server.clj
@@ -0,0 +1,11 @@
+(ns backend.server
+ (:require [clojure.java.io :as io]
+ [ring.util.response :as resp]
+ [ring.middleware.content-type :as content-type]))
+
+(def handler
+ (-> (fn [request]
+ (or (resp/resource-response (:uri request) {:root "public"})
+ (-> (resp/resource-response "index.html" {:root "public"})
+ (resp/content-type "text/html"))))
+ content-type/wrap-content-type))
diff --git a/examples/frontend-re-frame/src/clj/frontend_re_frame/core.clj b/examples/frontend-re-frame/src/clj/frontend_re_frame/core.clj
new file mode 100644
index 00000000..c7f9f1b7
--- /dev/null
+++ b/examples/frontend-re-frame/src/clj/frontend_re_frame/core.clj
@@ -0,0 +1 @@
+(ns frontend-re-frame.core)
diff --git a/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs b/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs
new file mode 100644
index 00000000..f7b33cc8
--- /dev/null
+++ b/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs
@@ -0,0 +1,155 @@
+(ns frontend-re-frame.core
+ (:require
+ [re-frame.core :as re-frame]
+ [reagent.core :as reagent]
+ [reitit.core :as r]
+ [reitit.coercion :as rc]
+ [reitit.coercion.spec :as rss]
+ [reitit.frontend :as rf]
+ [reitit.frontend.controllers :as rfc]
+ [reitit.frontend.easy :as rfe]))
+
+;;; Events ;;;
+
+(re-frame/reg-event-db
+ ::initialize-db
+ (fn [_ _]
+ {:current-route nil}))
+
+(re-frame/reg-event-fx
+ ::navigate
+ (fn [db [_ route]]
+ ;; See `navigate` effect in routes.cljs
+ {::navigate! route}))
+
+(re-frame/reg-event-db
+ ::navigated
+ (fn [db [_ new-match]]
+ (let [old-match (:current-route db)
+ controllers (rfc/apply-controllers (:controllers old-match) new-match)]
+ (assoc db :current-route (assoc new-match :controllers controllers)))))
+
+;;; Subscriptions ;;;
+
+(re-frame/reg-sub
+ ::current-route
+ (fn [db]
+ (:current-route db)))
+
+;;; Views ;;;
+
+(defn home-page []
+ [:div
+ [:h1 "This is home page"]
+ [:button
+ ;; Dispatch navigate event that triggers a (side)effect.
+ {:on-click #(re-frame/dispatch [::navigate ::sub-page2])}
+ "Go to sub-page 2"]])
+
+(defn sub-page1 []
+ [:div
+ [:h1 "This is sub-page 1"]])
+
+(defn sub-page2 []
+ [:div
+ [:h1 "This is sub-page 2"]])
+
+;;; Effects ;;;
+
+;; Triggering navigation from events.
+(re-frame/reg-fx
+ ::navigate!
+ (fn [k params query]
+ (rfe/push-state k params query)))
+
+;;; Routes ;;;
+
+(defn href
+ "Return relative url for given route. Url can be used in HTML links."
+ ([k]
+ (href k nil nil))
+ ([k params]
+ (href k params nil))
+ ([k params query]
+ (rfe/href k params query)))
+
+(def routes
+ ["/"
+ [""
+ {:name ::home
+ :view home-page
+ :link-text "Home"
+ :controllers
+ [{;; Do whatever initialization needed for home page
+ ;; I.e (re-frame/dispatch [::events/load-something-with-ajax])
+ :start (fn [& params](js/console.log "Entering home page"))
+ ;; Teardown can be done here.
+ :stop (fn [& params] (js/console.log "Leaving home page"))}]}]
+ ["sub-page1"
+ {:name ::sub-page1
+ :view sub-page1
+ :link-text "Sub page 1"
+ :controllers
+ [{:start (fn [& params] (js/console.log "Entering sub-page 1"))
+ :stop (fn [& params] (js/console.log "Leaving sub-page 1"))}]}]
+ ["sub-page2"
+ {:name ::sub-page2
+ :view sub-page2
+ :link-text "Sub-page 2"
+ :controllers
+ [{:start (fn [& params] (js/console.log "Entering sub-page 2"))
+ :stop (fn [& params] (js/console.log "Leaving sub-page 2"))}]}]])
+
+(defn on-navigate [new-match]
+ (when new-match
+ (re-frame/dispatch [::navigated new-match])))
+
+(def router
+ (rf/router
+ routes
+ {:data {:coercion rss/coercion}}))
+
+(defn init-routes! []
+ (js/console.log "initializing routes")
+ (rfe/start!
+ router
+ on-navigate
+ {:use-fragment true}))
+
+(defn nav [{:keys [router current-route]}]
+ [:ul
+ (for [route-name (r/route-names router)
+ :let [route (r/match-by-name router route-name)
+ text (-> route :data :link-text)]]
+ [:li {:key route-name}
+ (when (= route-name (-> current-route :data :name))
+ "> ")
+ ;; Create a normal links that user can click
+ [:a {:href (href route-name)} text]])])
+
+(defn router-component [{:keys [router]}]
+ (let [current-route @(re-frame/subscribe [::current-route])]
+ [:div
+ [nav {:router router :current-route current-route}]
+ (when current-route
+ [(-> current-route :data :view)])]))
+
+;;; Setup ;;;
+
+(def debug? ^boolean goog.DEBUG)
+
+(defn dev-setup []
+ (when debug?
+ (enable-console-print!)
+ (println "dev mode")))
+
+(defn mount-root []
+ (re-frame/clear-subscription-cache!)
+ (init-routes!) ;; Reset routes on figwheel reload
+ (reagent/render [router-component {:router router}]
+ (.getElementById js/document "app")))
+
+(defn ^:export init []
+ (re-frame/dispatch-sync [::initialize-db])
+ (dev-setup)
+ (mount-root))
diff --git a/modules/reitit-core/src/reitit/core.cljc b/modules/reitit-core/src/reitit/core.cljc
index 2f33c605..573ba5b2 100644
--- a/modules/reitit-core/src/reitit/core.cljc
+++ b/modules/reitit-core/src/reitit/core.cljc
@@ -67,7 +67,7 @@
([match]
(match->path match nil))
([match query-params]
- (some-> match :path (cond-> query-params (str "?" (impl/query-string query-params))))))
+ (some-> match :path (cond-> (seq query-params) (str "?" (impl/query-string query-params))))))
;;
;; Different routers
diff --git a/test/cljc/reitit/core_test.cljc b/test/cljc/reitit/core_test.cljc
index c48f6348..4d9ee770 100644
--- a/test/cljc/reitit/core_test.cljc
+++ b/test/cljc/reitit/core_test.cljc
@@ -354,6 +354,10 @@
(-> router
(r/match-by-name! ::route {:a "olipa", :b "kerran"})
(r/match->path))))
+ (is (= "/olipa/kerran"
+ (-> router
+ (r/match-by-name! ::route {:a "olipa", :b "kerran"})
+ (r/match->path {}))))
(is (= "/olipa/kerran?iso=p%C3%B6ril%C3%A4inen"
(-> router
(r/match-by-name! ::route {:a "olipa", :b "kerran"})