Skip to content

Instantly share code, notes, and snippets.

@simon-brooke
Last active August 1, 2026 16:37
Show Gist options
  • Select an option

  • Save simon-brooke/430656ff7cddc6ebab8dee9a87fb1aef to your computer and use it in GitHub Desktop.

Select an option

Save simon-brooke/430656ff7cddc6ebab8dee9a87fb1aef to your computer and use it in GitHub Desktop.
Reagami calculator

Reagami calculator

This is just a very quick experiment with Michiel Borkent's Reagami package.

I found it an astonishingly easy way to build a web GUI. To play with this:

  1. Create a reagami app as documented here, but do not start it:
npm create reagami-app my-app
cd my-app
npm install
  1. Copy the app.cljs file from this gist to replace my-app/src/app.cljs;
  2. Copy the index.html from this gist to replace my-app/index.html;
  3. Start the runner:
npm run dev
  1. Browse to http://localhost:5173/ (or which ever port is indicated by the runner)

Edits that you make to these two files will then be immediately reflected in the browser.

(ns app
(:require [reagami.core :as r]
[clojure.string :refer [includes?]]))
(defonce !state (atom {:accumulator 0 :input ""}))
(def root (js/document.getElementById "app"))
(defn add-input [digit input]
(swap! !state assoc :input (str input digit)))
(defn view [{:keys [accumulator input]}]
[:div
[:h1 "reagami calculator"]
[:div {:class "gui"}
[:div {:class "row"} "accumulator: " [:span {:id "display" :style {:float "right"}} accumulator]]
[:div {:class "row"} "input:" [:span {:id "input" :style {:float "right"}} input]]
[:div {:class "row"}
[:button {:id "clear" :on-click (fn [_] (swap! !state assoc :input ""))} "C"]
[:button {:id "all-clear" :style {:width "4em"} :on-click (fn [_] (swap! !state assoc :input "" :accumulator 0))} "AC"]
[:button {:id "divide" :on-click (fn [_] (swap! !state assoc :accumulator (/ accumulator (js/Number input)) :input ""))} "/"]]
[:div {:class "row"} [:button {:id "seven" :on-click (fn [_] (add-input "7" input))} 7]
[:button {:id "eight" :on-click (fn [_] (add-input "8" input))} 8]
[:button {:id "nine" :on-click (fn [_] (add-input "9" input))} 9]
[:button {:id "multiply" :on-click (fn [_] (swap! !state assoc :accumulator (* accumulator (js/Number input)) :input ""))} "x"]]
[:div {:class "row"} [:button {:id "four" :on-click (fn [_] (add-input "4" input))} 4]
[:button {:id "five" :on-click (fn [_] (add-input "5" input))} 5]
[:button {:id "six" :on-click (fn [_] (add-input "6" input))} 6]
[:button {:id "subtract" :on-click (fn [_] (swap! !state assoc :accumulator (- accumulator (js/Number input)) :input ""))} "-"]]
[:div {:class "row"} [:button {:id "one" :on-click (fn [_] (add-input "1" input))} 1]
[:button {:id "two" :on-click (fn [_] (add-input "2" input))} 2]
[:button {:id "three" :on-click (fn [_] (add-input "3" input))} 3]
[:button {:id "add" :on-click (fn [_] (swap! !state assoc :accumulator (+ accumulator (js/Number input)) :input ""))} "+"]]
[:div {:class "row"} [:button {:id "zero" :on-click (fn [_] (add-input "0" input))} 0]
[:button {:id "period" :on-click (fn [_] (when-not (includes? input ".") (add-input "." input)))} "."]
[:button {:id "delete" :style {:width "4em"} :on-click (fn [_] (when (> (count input) 0) (swap! !state assoc :input (subs input 0 (dec (count input))))))} "<<"]]]])
(defn render! []
(r/render root (view @!state)))
(add-watch !state ::render (fn [_ _ _ _] (render!)))
(render!)
;; the Squint Vite plugin calls this after a hot reload, so an edit repaints
;; and the atom keeps its state
(defn ^:dev/after-load re-render [] (render!))
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>reagami app</title>
<style>
button {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: large;
width: 2em;
}
.row {
clear: left;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
width: 9em;
}
</style>
</head>
<body>
<div id="app"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment