Skip to content

Commit 645b096

Browse files
add post about hot reload scittle
1 parent ecc2209 commit 645b096

File tree

3 files changed

+189
-3
lines changed

3 files changed

+189
-3
lines changed

deps.edn

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
metosin/malli {:mvn/version "0.19.1"}
1212
clj-fuzzy/clj-fuzzy {:mvn/version "0.4.1"}
1313
clj-thamil/clj-thamil {:mvn/version "0.2.0"}
14-
org.scicloj/clay {:mvn/version "2-beta50"
15-
#_#_:git/url "https://github.com/scicloj/clay.git"
16-
#_#_:git/sha "1f8c5a717287fe85ee6054eafd5b2c53000d9e3a"}
14+
org.scicloj/clay {#_#_:mvn/version "2-beta50"
15+
:git/url "https://github.com/scicloj/clay.git"
16+
:git/sha "3332652eebc5d6b432f5f1b49ef4b8792e49acf9"}
1717
org.eclipse.elk/org.eclipse.elk.core {:mvn/version "0.10.0"}
1818
org.eclipse.elk/org.eclipse.elk.graph {:mvn/version "0.10.0"}
1919
org.eclipse.elk/org.eclipse.elk.graph.json {:mvn/version "0.10.0"}

src/scicloj/clay/uncompiled.cljs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(ns scicloj.clay.uncompiled
2+
(:require [reagent.core :as r]
3+
[reagent.dom :as rdom]))
4+
5+
(rdom/render
6+
[:div "hello from Scittle"]
7+
(js/document.getElementById "app"))
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
^:kindly/hide-code
2+
^{:clay {:title "The Sandwich Approach to ClojureScript Development"
3+
:quarto {:author :timothypratley
4+
:description "A lightweight way to cook with Clay and Scittle"
5+
:type :post
6+
:draft true
7+
:date "2025-08-13"
8+
:category :clay
9+
:tags [:clay :workflow :scittle :reagent]}}}
10+
(ns scicloj.clay.uncompiled-clojurescript
11+
(:require [scicloj.kindly.v4.kind :as kind]))
12+
13+
;; Imagine you're making breakfast for your significant other one morning,
14+
;; you just cracked the eggs into a frypan and they call out "poached please".
15+
;; What do you do?
16+
;; No need to start over, just add some water.
17+
;; That's the spirit of hot reload; keep your state and adjust the functions.
18+
19+
;; This kind of fluid adaptation is exactly what we want in our development workflow.
20+
;; Let's see how to cook up that experience with two key ingredients.
21+
22+
;; ## The Main Ingredient: Scittle
23+
24+
;; [Scittle](https://github.com/babashka/scittle) by the amazing [borkdude](https://github.com/borkdude) is a ClojureScript interpreter that runs in the browser.
25+
;; No build step, no config, just static files. That makes it perfect to include in Clay notebooks like this one.
26+
27+
;; When you're hungry, do you always cook a gourmet meal?
28+
;; Sometimes you just want to make a quick sandwich—grab what you need,
29+
;; slap it together, and start eating. No prep work, no cleanup.
30+
;; That's Scittle: quick, simple, satisfying ClojureScript without the ceremony.
31+
;; Sometimes you don't need the full kitchen setup with build tools and configurations.
32+
33+
;; Clay lets us interleave plain Hiccup with Reagent/Scittle components:
34+
35+
(kind/hiccup
36+
[:div [:strong "Hello from Hiccup"]
37+
['(fn []
38+
[:em "Hello from Scittle/Reagent"])]])
39+
40+
;; But because Clay serves HTML, re-evaluating this namespace normally reloads the whole page.
41+
;; Wouldn’t it be great to get a Figwheel/shadow-cljs style experience where code updates in place?
42+
43+
;; ::: {.callout-note}
44+
;; Hot Reloading injects only the modified code into the running application without restarting it entirely.
45+
;; This allows you to preserve state and treat the browser like a REPL.
46+
;; :::
47+
48+
;; ## The Inspiration: Hot Reload Scittle
49+
50+
;; [Chris McCormick](https://github.com/chr15m) showed us something clever
51+
;; with [cljs-josh](https://github.com/chr15m/cljs-josh): Scittle code can be hot-reloaded. Here's his demo:
52+
53+
^:kind/video ^:kindly/hide-code
54+
{:youtube-id "4tbjE0_W-58"
55+
:iframe-width "100%"}
56+
57+
;; We'll take that idea but do it the Clay way,
58+
;; using Clay's live reload to manage our pages.
59+
60+
;; ## Clay Can Hot Reload Scittle
61+
62+
;; Here’s the code in our ClojureScript file:
63+
64+
;; **uncompiled.cljs**:
65+
^:kindly/hide-code
66+
(kind/code (slurp "src/scicloj/clay/uncompiled.cljs"))
67+
68+
;; We need a target div for `uncompiled.cljs` to render into, and we load it via Scittle:
69+
70+
(kind/hiccup
71+
[:div#app
72+
[:script {:type "application/x-scittle"
73+
:src "uncompiled.cljs"}]])
74+
75+
;; ## Turn Up the Heat
76+
77+
;; Time to get cooking! Clay needs `:live-reload true` to simmer.
78+
;; You can fire it up from the command line, via [editor integration](https://scicloj.github.io/clay/#setup),
79+
;; or drop this in your REPL:
80+
81+
;; ```clojure
82+
;; (require '[scicloj.clay.v2.snippets :as snippets])
83+
;; (snippets/watch! {})
84+
;; ```
85+
86+
;; Now whenever you save a `.cljs` file, the change is injected into the current Clay page without a full reload.
87+
88+
;; If you prefer editor integration, bind a key to call
89+
;; `scicloj.clay.v2.server/scittle-eval-string!` on the current form.
90+
91+
;; ::: {.callout-tip}
92+
;; To take full advantage of hot reload with Reagent, use `defonce` for app state.
93+
;; This preserves atoms/ratoms across code swaps.
94+
;; :::
95+
96+
;; ## A Taste Test
97+
98+
;; Let's walk through a small example to see hot reload in action.
99+
;; I recommend copying these snippets into the `uncompiled.cljs` and saving as you go.
100+
;; First, we'll set up our ingredients (app state):
101+
102+
;; ```clojure
103+
;; (ns my-app.core
104+
;; (:require [reagent.core :as r]))
105+
;;
106+
;; (defonce app-state ; <- defonce preserves state during reload
107+
;; (r/atom {:style "scrambled"
108+
;; :eggs 2}))
109+
;; ```
110+
111+
;; Next, we'll create a simple component to display our breakfast order:
112+
113+
;; ```clojure
114+
;; (defn breakfast-order []
115+
;; [:div
116+
;; [:h3 "Breakfast Order"]
117+
;; [:p "Style: " (:style @app-state)]
118+
;; [:p "Eggs: " (:eggs @app-state)]])
119+
;; ```
120+
121+
;; We can mount our new component on the `app` div.
122+
123+
;; ```clojure
124+
;; (rdom/render
125+
;; [breakfast-order]
126+
;; (js/document.getElementById "app"))
127+
;; ```
128+
129+
;; Just like our opening story, imagine the order changes mid-cook.
130+
;; We can update our component without losing the current state:
131+
132+
;; ```clojure
133+
;; (defn breakfast-order []
134+
;; [:div
135+
;; [:h3 "Breakfast Order"]
136+
;; [:p "Style: " [:em (:style @app-state)]] ; <- added emphasis
137+
;; [:p "Eggs: " (:eggs @app-state)]
138+
;; [:small "Water added for poaching..."]]) ; <- new status line
139+
;; ```
140+
141+
;; Save the file, and voilà! The display updates while preserving the
142+
;; existing order details in app-state. No need to start over or lose
143+
;; your place in the cooking process.
144+
145+
;; ## Why Go Light?
146+
147+
;; A Michelin-star kitchen is a marvel of efficiency.
148+
;; Sous chefs prepping ingredients,
149+
;; line cooks at their stations, everything precisely mise en place.
150+
;; That's your typical ClojureScript setup: build tools, asset compilation,
151+
;; development servers, and careful configuration.
152+
;;
153+
;; But sometimes you just want to slap some cold cuts and cheese in a sandwich and start munching.
154+
;; That's Scittle: quick, simple, and satisfying.
155+
;; No waiting for the kitchen to warm up, no cleanup afterward.
156+
;; Just write some code and see it work.
157+
158+
;; ## Chef's Notes
159+
160+
;; Clay blends the traditional with the experimental.
161+
;; Write a namespace, get a webpage.
162+
;; Add some Scittle, get interactive components.
163+
164+
;; The magic happens in how Clay handles changes:
165+
166+
;; - For your narrative and page structure in Clojure live reload refreshes the whole view
167+
;; - For your Scittle components hot reload updates just the code, keeping state alive
168+
169+
;; This is especially sweet when you're cooking up interactive elements like mini-games
170+
;; with matter.js. Tweak physics parameters or game logic, and watch them take effect
171+
;; instantly. Your game state, scores, and position all preserved.
172+
;;
173+
;; Remember how we started with those poached eggs?
174+
;; Maybe they were destined for a sandwich all along.
175+
;; That's the beauty of this approach: start simple,
176+
;; stay flexible, and build exactly what you need.
177+
;; Clay lets you shape your story with markdown, spice it up with interactive widgets,
178+
;; and adjust the ingredients.
179+
;; That's the kind of flow that keeps creative coding delicious.

0 commit comments

Comments
 (0)