      ]]]])
 
 ;; renders /sp/latest/1
-(defn latest [page {res :exs user :user}]
+(defn latest [url-fn page {res :exs user :user}]
    [:html 
     (head (str "ontrail.net :: " page))
     [:body [:div.main
      (header user)
-     (latest-paging page (count res))
+     (latest-paging url-fn page (count res))
      (for [entry res] (latest-list-entry entry))
-     (latest-paging page (count res))
+     (latest-paging url-fn page (count res))
      ]]])
 
 (defroutes templates

  (GET "/sp/latest/:page" {params :params cookies :cookies}
       (let [page (Integer/parseInt ^String (webutil/get-page params))
             user (auth/user-from-cookie cookies)]
         (render-with (partial latest page)
                      {:exs (ex/get-latest-ex-list-default-order 
                             user
                             {} 
                             page)
                       :user user})))
  
  (GET "/sp/ex/:id" {params :params cookies :cookies}
       (let [user (auth/user-from-cookie cookies)]
         (render-with single-exercise  

   [ontrail.webutil :as webutil]
   [ontrail.auth :as auth]
   [ontrail.formats :as formats]
   [ontrail.mongerfilter :as mongerfilter]

   [clj-time.core :as time]
   [hiccup.form :as form]
   [hiccup.core :as hiccup]
   [stencil.core :as stencil]
   [clojure.string :as string])
  (:import [java.net URLEncoder]))

(def #^{:private true} logger (org.slf4j.LoggerFactory/getLogger (str *ns*)))

(defn urlp [params]
  (if (empty? params)
    ""
    (str "?"
         (apply str 
                (interpose "&"
                 (map (fn [param] (str (-> param first name) "=" (-> param second URLEncoder/encode)))
                   params))))))

;; (url {:a "b" :c "d"} "/list/" page) = /list/page?a=b&c=d
(defn url[maybe-params & parts] 
  (if (map? maybe-params)
    (let [params (urlp maybe-params)]
      (apply (partial str "/sp") (concat parts [params])))
    (apply (partial str "/sp" maybe-params) parts)))

(defmacro render-with [render-fn data & [status]]
  `(try 
