Detailed setup for Kit applications that render server-side HTML pages.
This guide targets:
- generated Kit apps
- apps with HTML rendering enabled through
:kit/html/ Selmer - optional SQL capture through Kit SQL components
This toolbar only injects into full HTML responses. API-only Kit apps will not show the toolbar unless they also render complete HTML pages with a closing </body> tag.
neil new io.github.kit-clj/kit yourname/guestbookclojure -Tclj-new create :template io.github.kit-clj :name yourname/guestbookIf your Kit app does not already render HTML pages, install Kit HTML support first.
(require '[kit.api :as kit])
(kit/sync-modules)
(kit/install-module :kit/html)After installing a Kit module, restart your REPL before continuing.
Add debug_toolbar to your project deps.edn.
{:deps
{laconiccrafts/debug-toolbar
{:git/url "https://github.com/laconiccrafts/debug_toolbar.git"
:git/tag "v0.3.1"
:git/sha "0bdf4a1ea68af6eb4e6f29eaefc4c96e2422bebb"}}}If deps.edn already has a :deps map, add only the laconiccrafts/debug-toolbar entry.
Add toolbar middleware in Kit development middleware so it runs only in development.
(ns my-app.dev-middleware
(:require
[laconiccrafts.debug-toolbar.core :as debug-toolbar]))
(defn wrap-dev
[handler opts]
(-> handler
(debug-toolbar/wrap-debug-toolbar
{:enabled? (= :dev (:profile opts))
:route-info-fn debug-toolbar/reitit-route-info
:ui-options {:collapsed-by-default? true
:slow-query-threshold-ms 100
:include-session? true
:include-identity? true}})))ui-options controls only toolbar presentation and which request data gets shown. Current supported keys are:
:collapsed-by-default?controls initial open state of toolbar panel.:slow-query-threshold-mssets SQL timing threshold used by default UI to mark query row as slow. Queries at or above this number get highlighted in SQL tab.:include-session?controls whether request:sessiondata is copied into toolbar payload and shown in Session tab.:include-identity?controls whether authenticated user data is shown. When enabled, toolbar uses request:identityfirst, then falls back to[:session :identity]if present.
The toolbar does not know which template rendered your page unless your app records that explicitly.
Create one shared layout helper and route all page rendering through it.
(ns my-app.web.pages.layout
(:require
[laconiccrafts.debug-toolbar.core :as debug-toolbar]))
(defn render
[opts request template context]
(debug-toolbar/record-view-render!
template
(debug-toolbar/template-path template)
context)
{:status 200
:headers {"Content-Type" "text/html; charset=utf-8"}
:body ((get-in opts [:templating/selmer :render-file])
template
context)})If your app already has a layout helper, keep its existing response-shaping logic and add only the record-view-render! call.
template-path is safe for both file-backed templates and embedded
resources loaded from an uberjar.
Update page routes to call the shared helper instead of calling Selmer directly.
(ns my-app.web.routes.pages
(:require
[my-app.web.pages.layout :as layout]))
(defn home
[opts request]
(layout/render opts request "home.html"
{:page-title "Home"}))
(defn page-routes
[opts]
[["/" {:get (partial home opts)}]])If you render HTML from controllers, use same helper there too.
(ns my-app.web.controllers.dashboard
(:require
[my-app.web.pages.layout :as layout]))
(defn index
[{:keys [query-fn] :as opts} request]
(layout/render opts request "dashboard.html"
{:stats (query-fn :get-dashboard-stats {})}))Wrap Kit datasource component once, then point your query functions at wrapped datasource.
Load toolbar SQL namespace once so Integrant sees the shared init method.
(ns my-app.db
(:require
[laconiccrafts.debug-toolbar.sql]))That require registers ig/init-key :db.sql/debug-connection.
[my-app.db]Now add wrapped datasource component and point query execution at it.
Where this code goes: your app resources/system.edn.
:db.sql/connection
#profile {:dev {:jdbc-url "jdbc:postgresql://localhost/my_app?user=my_app&password=my_app"}
:test {}
:prod {:jdbc-url #env JDBC_URL
:init-size 1
:min-idle 1
:max-idle 8
:max-active 32}}
:db.sql/debug-connection
{:datasource #ig/ref :db.sql/connection
:enabled? #profile {:dev true
:test false
:prod false}
:name "my-app-debug-toolbar"}
:db.sql/query-fn
{:conn #ig/ref :db.sql/debug-connection
:options {}
:filename "queries.sql"
:env #ig/ref :system/env}For current Kit Conman setup, this works because :db.sql/connection resolves to a datasource-backed pooled connection object that wrap-datasource can decorate.
If your app already has a :db.sql/migrations entry, point that datasource at the wrapped connection too.
:db.sql/migrations
{:store :database
:db {:datasource #ig/ref :db.sql/debug-connection}
:migrate-on-init? true}If your app uses Hikari or a custom datasource key instead of :db.sql/connection, use same pattern:
- reference your real datasource component under
:datasource - keep
:db.sql/debug-connectionas wrapper layer - point query and migration config at wrapped datasource key
Start your Kit REPL and boot the app.
Where this command runs: terminal inside your Kit app.
clj -M:devWhere this code goes: REPL inside your Kit app.
(go)Then verify behavior in browser:
- Load a normal HTML page such as
/. Toolbar should appear. - Hit a page that executes SQL.
SQL Queriestab should list statements and timings. - Hit a page rendered through
layout/render.View TemplateandView Contextshould be populated. - Trigger an HTMX fragment request. Toolbar should not be injected into fragment response.
If toolbar does not appear, check these first:
- response content type starts with
text/html - response body contains a closing
</body>tag - request is not an HTMX fragment request
wrap-devis active in current:devprofile- rendered page goes through your shared
layout/renderhelper - SQL queries use wrapped datasource instead of raw datasource
This guide matches current debug_toolbar behavior:
- toolbar injects only into full HTML responses
- HTMX fragment requests are skipped
- SQL capture happens through
laconiccrafts.debug-toolbar.sql/wrap-datasource - view metadata appears only when
laconiccrafts.debug-toolbar.core/record-view-render!is called