# Ctmx - super lightweight web dev

**URL:** https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962
**Category:** Showcase
**Tags:** clojure, webapps
**Created:** [August 1, 2021, 7:03am UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962 "2021-08-01T07:03:13Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![PrestanceDesign](https://clojureverse.org/user_avatar/clojureverse.org/prestancedesign/32/3733_2.png) [@PrestanceDesign](https://clojureverse.org/u/PrestanceDesign)
#### Post date: [August 5, 2021, 9:24am UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/21 "2021-08-05T09:24:31Z")

</div>

Me too, I’m definitely looking forward to trying out your Ctmx lib.

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 5, 2021, 12:50pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/22 "2021-08-05T12:50:41Z")

</div>

Thanks to @md1frejo Jonas’s suggestion I made a template to easily create ctmx with leiningen. Go

```
lein new luminus my-project +ctmx
cd my-project
lein run

```

The ctmx source is entirely in the routes/home.clj ns, so you can see it is very simple.

---

<div class="post-metadata">

### Author: ![md1frejo](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/b3f665/32.png) [@md1frejo](https://clojureverse.org/u/md1frejo)
#### Post date: [August 6, 2021, 2:04pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/23 "2021-08-06T14:04:26Z")

</div>

great work. I can conform that it is working

---

<div class="post-metadata">

### Author: ![PrestanceDesign](https://clojureverse.org/user_avatar/clojureverse.org/prestancedesign/32/3733_2.png) [@PrestanceDesign](https://clojureverse.org/u/PrestanceDesign)
#### Post date: [August 10, 2021, 4:56pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/24 "2021-08-10T16:56:13Z")

</div>

Hi @Matthew_Molloy,

I want to say thanks to let me knew about htmx & ctmx.  
For the first approach, I toyed with Babashka + htmx little project and it was very fun!

> **[GitHub - prestancedesign/babashka-htmx-todoapp: Quick example of a todo list...](https://github.com/prestancedesign/babashka-htmx-todoapp)**
>
> Quick example of a todo list SPA using Babashka and htmx - GitHub - prestancedesign/babashka-htmx-todoapp: Quick example of a todo list SPA using Babashka and htmx

I plan to make a version with your ctmx lib.  
Cheers!

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 10, 2021, 5:52pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/25 "2021-08-10T17:52:22Z")

</div>

Great to hear Prestance! Shout out if you have any questions. I’m also interested to know if there’s anything confusing about the setup.

---

<div class="post-metadata">

### Author: ![hadils](https://clojureverse.org/user_avatar/clojureverse.org/hadils/32/3331_2.png) [@hadils](https://clojureverse.org/u/hadils)
#### Post date: [August 13, 2021, 5:10pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/26 "2021-08-13T17:10:33Z")

</div>

Hi @Matthew_Molloy ,

Thanks a lot for ctmx! I want to do an app in tools.deps and I am having a hard time setting up the middleware. Could you point me to a simple app that I could use as a template?

Thanks,  
Hadil

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 13, 2021, 5:28pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/27 "2021-08-13T17:28:28Z")

</div>

Sure @hadils,

To see a working setup try `lein new luminus my-project +ctmx`. Then look in the `routes/home.clj` namespace. CTMX will work with any setup that uses [reitit](https://github.com/metosin/reitit) for routing.

Matt

---

<div class="post-metadata">

### Author: ![hadils](https://clojureverse.org/user_avatar/clojureverse.org/hadils/32/3331_2.png) [@hadils](https://clojureverse.org/u/hadils)
#### Post date: [August 13, 2021, 5:31pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/28 "2021-08-13T17:31:43Z")

</div>

Thanks @Matthew_Molloy !

---

<div class="post-metadata">

### Author: ![md1frejo](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/b3f665/32.png) [@md1frejo](https://clojureverse.org/u/md1frejo)
#### Post date: [August 15, 2021, 12:39pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/29 "2021-08-15T12:39:26Z")

</div>

I am trying this out and it’s all new to me, so here is a simple question: I am trying to create a page with the “my name” exmaple but I get a 505 error. Any suggestions?

name.clj:

> (ns test.routes.name  
> (:require  
> [ctmx.core :as ctmx]))
> 
> (ctmx/defcomponent ^:endpoint hello [req my-name]  
> [:div#hello "hello " my-name])
> 
> (defn routes   
> (ctmx/make-routes “/name” (fn [req]  
> [:div  
> [:label “what is your name?”]  
> [:input {:name “my-name” :hx-patch “hello” :hx-target “#hello”}]  
> (hello req “”)])))

handler.clj:

> (ns test.handler  
> (:require  
> [test.middleware :as middleware]  
> [test.layout :refer [error-page]]  
> [test.routes.home :refer [home-routes]]  
> [test.routes.name :as name]  
> [reitit.ring :as ring]  
> [ring.middleware.content-type :refer [wrap-content-type]]  
> [ring.middleware.webjars :refer [wrap-webjars]]  
> [test.env :refer [defaults]]  
> [mount.core :as mount]))
> 
> (mount/defstate init-app  
> :start ((or (:init defaults) (fn )))  
> :stop ((or (:stop defaults) (fn ))))
> 
> (mount/defstate app-routes  
> :start  
> (ring/ring-handler  
> (ring/router  
> [(home-routes)  
> (name/routes)])  
> (ring/routes  
> (ring/create-resource-handler  
> {:path “/”})  
> (wrap-content-type  
> (wrap-webjars (constantly nil)))  
> (ring/create-default-handler  
> {:not-found  
> (constantly (error-page {:status 404, :title “404 - Page not found”}))  
> :method-not-allowed  
> (constantly (error-page {:status 405, :title “405 - Not allowed”}))  
> :not-acceptable  
> (constantly (error-page {:status 406, :title “406 - Not acceptable”}))}))))
> 
> (defn app   
> (middleware/wrap-base #'app-routes))

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 15, 2021, 1:07pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/30 "2021-08-15T13:07:30Z")

</div>

Can you put it on GitHub and send me a link please? Alternately zip the project and mail to matthew@molloy.link.

---

<div class="post-metadata">

### Author: ![md1frejo](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/b3f665/32.png) [@md1frejo](https://clojureverse.org/u/md1frejo)
#### Post date: [August 15, 2021, 1:41pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/31 "2021-08-15T13:41:15Z")

</div>

ok, here the link if got it right: [GitHub - md1frejo/clojure](https://github.com/md1frejo/clojure)

it is basically the template with an added name request

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 15, 2021, 2:40pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/32 "2021-08-15T14:40:37Z")

</div>

Thanks @md1frejo,

I have cloned your project, cd in, `lein run` then visited [http://localhost:3000](http://localhost:3000). I can click the div and it increments. What exact query did you run to get http 505? Which browser were you in?

Matt

---

<div class="post-metadata">

### Author: ![md1frejo](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/b3f665/32.png) [@md1frejo](https://clojureverse.org/u/md1frejo)
#### Post date: [August 15, 2021, 5:40pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/33 "2021-08-15T17:40:23Z")

</div>

try localhost:3000/name  
it should show an input form to write a name. thats in name.clj  
the browser was firefox

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 15, 2021, 9:48pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/34 "2021-08-15T21:48:10Z")

</div>

@md1frejo I see there’s something confusing about my documentation. I will now fix that. I have also added a pull request to your repository. See how you need to wrap the initial request in a rendering function?

---

<div class="post-metadata">

### Author: ![rmschindler](https://clojureverse.org/user_avatar/clojureverse.org/rmschindler/32/3638_2.png) [@rmschindler](https://clojureverse.org/u/rmschindler)
#### Post date: [August 15, 2021, 10:59pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/35 "2021-08-15T22:59:30Z")

</div>

If I may, pardon me if I ask a very “beginner” question, but you mention in your initial post, “and no compiled js on the frontend,” as if that is a bad thing. To a beginner like me, your comment seems to suggest that frontend JS is better avoided. Is this what you meant? And if so, why is frontend JS better to be avoided?

---

<div class="post-metadata">

### Author: ![hadils](https://clojureverse.org/user_avatar/clojureverse.org/hadils/32/3331_2.png) [@hadils](https://clojureverse.org/u/hadils)
#### Post date: [August 16, 2021, 1:59am UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/36 "2021-08-16T01:59:36Z")

</div>

The biggest problem is page rendering speed. Front end JS has to be loaded into the browser causing delays in first page render.

Subtler issue is state management on the browser. There are very simple to very complex solutions to this problem. They require learning on the developer’s part and need to be maintained.

A server-side solution reduces initial page load time. And all the state is on the server. You have to keep server state even with front end JS anyway.

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 16, 2021, 3:33am UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/37 "2021-08-16T03:33:18Z")

</div>

@rmschindler as @hadils mentioned too much js slows page load (especially on mobile and in countries with slower internet). The last few years have seen a big shift towards heavy frameworks that use a lot of javascript. Some developers like it because it ‘separates concerns’ by having all the rendering code running on the browser, but it makes web development slower and more complex. ctmx / html are part of a reaction against that.

---

<div class="post-metadata">

### Author: ![md1frejo](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/b3f665/32.png) [@md1frejo](https://clojureverse.org/u/md1frejo)
#### Post date: [August 16, 2021, 8:53pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/38 "2021-08-16T20:53:08Z")

</div>

yes, thanks. now it works. I might try to wrap a graph in a page, exploring the collatz (3n+1) conjecture just for fun and learning.

---

<div class="post-metadata">

### Author: ![Matthew\_Molloy](https://clojureverse.org/user_avatar/clojureverse.org/matthew_molloy/32/3936_2.png) [@Matthew\_Molloy](https://clojureverse.org/u/Matthew_Molloy)
#### Post date: [August 17, 2021, 12:21am UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/39 "2021-08-17T00:21:21Z")

</div>

Remember to push your findings to GitHub so we can see what you make!

---

<div class="post-metadata">

### Author: ![md1frejo](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/b3f665/32.png) [@md1frejo](https://clojureverse.org/u/md1frejo)
#### Post date: [August 23, 2021, 1:40pm UTC](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962/40 "2021-08-23T13:40:25Z")

</div>

A question, I see in your template that yuo don’t use hiccup bootstrap, is there any specific reassons for that? I am planning to use it but if there is some drawbakcs with with it I have to go with anoter one.

[Previous page](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962.md?page=1)

[Next page](https://clojureverse.org/t/ctmx-super-lightweight-web-dev/7962.md?page=3)
