diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..feca861
Binary files /dev/null and b/.DS_Store differ
diff --git a/README.md b/README.md
index 280a2fd..cf514c5 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,37 @@ example, `lein run :population-size 100`. You can use something
 like `lein run | tee outfile` to send output both to the terminal 
 and to `outfile`.
 
+## CLJS Usage
+
+### Development
+
+Run in development:
+
+```bash
+yarn
+(mkdir -p target && cp assets/index.html target/)
+yarn shadow-cljs watch app
+```
+
+`shadow-cljs` will be installed in `node_modules/` when you run `yarn`.
+
+`:dev-http` specifies that `target/` will be served at http://localhost:8080 .
+
+### REPL
+
+After page is loaded, you may also start a REPL connected to browser with:
+
+```bash
+yarn shadow-cljs cljs-repl app
+```
+
+Once the REPL is loaded, load the core namespace with:
+
+```
+(ns propeller.core)
+```
+Calling `(-main)` will run the default genetic programming problem.
+
 ## Description
 
 Propel is an implementation of the Push programming 
diff --git a/assets/index.html b/assets/index.html
new file mode 100644
index 0000000..816c67c
--- /dev/null
+++ b/assets/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>propeller shadow-cljs</title>
+    <meta charset="UTF-8">
+</head>
+<body>
+<div>See Console!</div>
+<script src="main.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/deps.edn b/deps.edn
deleted file mode 100644
index dedbbfa..0000000
--- a/deps.edn
+++ /dev/null
@@ -1 +0,0 @@
-{:deps {org.clojure/clojurescript {:mvn/version "1.10.758"}}}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..33a73cb
--- /dev/null
+++ b/package.json
@@ -0,0 +1,21 @@
+{
+  "name": "propeller-cljs",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "watch": "shadow-cljs watch app",
+    "compile": "shadow-cljs compile app",
+    "release": "shadow-cljs release app",
+    "html": "mkdir -p target && cp assets/index.html target/",
+    "serve": "yarn html && http-server target/",
+    "del": "rm -r target/*",
+    "build": "yarn release && yarn html && yarn serve"
+  },
+  "author": "",
+  "license": "EPL",
+  "devDependencies": {
+    "http-server": "^0.12.3",
+    "shadow-cljs": "^2.10.10"
+  }
+}
diff --git a/shadow-cljs.edn b/shadow-cljs.edn
new file mode 100644
index 0000000..5901c31
--- /dev/null
+++ b/shadow-cljs.edn
@@ -0,0 +1,7 @@
+{:source-paths ["src"]
+ :dependencies []
+ :dev-http {8080 "target/"}
+ :builds {:app {:output-dir "target/"
+                :asset-path "."
+                :target :browser
+                :modules {:main {:init-fn propeller.main/main!}}}}}
\ No newline at end of file
diff --git a/src/.DS_Store b/src/.DS_Store
index 70cf722..bf7db11 100644
Binary files a/src/.DS_Store and b/src/.DS_Store differ
diff --git a/src/propeller/.DS_Store b/src/propeller/.DS_Store
index 0d0fca7..ed2fbb1 100644
Binary files a/src/propeller/.DS_Store and b/src/propeller/.DS_Store differ
diff --git a/src/propeller/main.cljs b/src/propeller/main.cljs
new file mode 100644
index 0000000..6dd3792
--- /dev/null
+++ b/src/propeller/main.cljs
@@ -0,0 +1,8 @@
+(ns propeller.main
+  (:require [propeller.core :as propeller]))
+
+(defn main! []
+  (println "Loading main..."))
+
+(defn ^:dev/after-load reload! []
+  (propeller/-main))
diff --git a/src/propeller/problems/software/smallest.cljc b/src/propeller/problems/software/smallest.cljc
index 7e8c3fb..e77c615 100755
--- a/src/propeller/problems/software/smallest.cljc
+++ b/src/propeller/problems/software/smallest.cljc
@@ -4,7 +4,8 @@
             [propeller.push.state :as state]
             [propeller.push.utils.helpers :refer [get-stack-instructions]]
             [propeller.utils :as utils]
-            [propeller.push.state :as state]))
+            [propeller.push.state :as state]
+            #?(:cljs [cljs.reader :refer [read-string]])))
 
 ;; =============================================================================
 ;; Tom Helmuth, thelmuth@cs.umass.edu
@@ -82,7 +83,8 @@
                       inputs)
          errors (map (fn [correct-output output]
                        (let [parsed-output (try (read-string output)
-                                                (catch Exception e 1))]
+                                                #?(:clj (catch Exception e 1000.0)
+                                                   :cljs (catch js/Error. e 1000.0)))]
                          (if (= correct-output parsed-output) 0 1)))
                      correct-outputs
                      outputs)]
diff --git a/src/propeller/push/.DS_Store b/src/propeller/push/.DS_Store
index 8544a8f..49c1bfb 100644
Binary files a/src/propeller/push/.DS_Store and b/src/propeller/push/.DS_Store differ
diff --git a/src/propeller/push/instructions/input_output.cljc b/src/propeller/push/instructions/input_output.cljc
index e5fccd4..55db2ee 100755
--- a/src/propeller/push/instructions/input_output.cljc
+++ b/src/propeller/push/instructions/input_output.cljc
@@ -19,7 +19,9 @@
   [state instruction]
   (if-let [input (instruction (:input state))]
     (state/push-to-stack state :exec input)
-    (throw (Exception. (str "Undefined input instruction " instruction)))))
+    (throw #?(:clj (Exception. (str "Undefined input instruction " instruction))
+              :cljs (js/Error
+                      (str "Undefined input instruction " instruction))))))
 
 ;; =============================================================================
 ;; OUTPUT Instructions
diff --git a/src/propeller/push/utils/macros.clj b/src/propeller/push/utils/macros.cljc
similarity index 100%
rename from src/propeller/push/utils/macros.clj
rename to src/propeller/push/utils/macros.cljc
diff --git a/src/propeller/tools/character.cljc b/src/propeller/tools/character.cljc
index 32d64d3..6c8b846 100755
--- a/src/propeller/tools/character.cljc
+++ b/src/propeller/tools/character.cljc
@@ -1,18 +1,24 @@
 (ns propeller.tools.character)
 
+(defn get-ascii
+  "Gets the ASCII code of a char"
+  [c]
+  #?(:clj (int c)
+     :cljs (.charCodeAt c 0)))
+
 (defn is-letter
   "Returns true if the given character is a letter, A-Z or a-z."
   [c]
-  (<= (int \A) (int c) (int \z)))
+  (<= (get-ascii \A) (get-ascii c) (get-ascii \z)))
 
 
 (defn is-digit
   "Returns true if the given character is a digit, 0-9."
   [c]
-  (<= (int \0) (int c) (int \9)))
+  (<= (get-ascii \0) (get-ascii c) (get-ascii \9)))
 
 
 (defn is-whitespace
   "Returns true if the given character is whitespace (newline, space, tab)."
   [c]
-  (contains? #{(int \newline) (int \tab) (int \space)} (int c)))
+  (contains? #{(get-ascii \newline) (get-ascii \tab) (get-ascii \space)} (get-ascii c)))