https://github.com/brettatoms/zodiac
A simple web framework for Clojure
https://github.com/brettatoms/zodiac
clojure web
Last synced: 3 months ago
JSON representation
A simple web framework for Clojure
- Host: GitHub
- URL: https://github.com/brettatoms/zodiac
- Owner: brettatoms
- License: mit
- Created: 2024-10-03T23:19:30.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2025-08-18T12:49:49.000Z (5 months ago)
- Last Synced: 2025-09-21T06:11:31.959Z (4 months ago)
- Topics: clojure, web
- Language: Clojure
- Homepage: https://cljdoc.org/d/com.github.brettatoms/zodiac
- Size: 83 KB
- Stars: 101
- Watchers: 4
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Zodiac
[](https://clojars.org/com.github.brettatoms/zodiac)
Come chat in [#zodiac](https://clojurians.slack.com/archives/C07V6RVUN7J)
Zodiac is a small web framework for Clojure that provides a reasonable set of defaults while also being easily extensible. Zodiac stands on the shoulders of giants rather than being innovative. At its core Zodiac is mostly just a preconfigured Ring app and not more that a few hundred lines of code.
Zodiac tries to fill a similar niche as the [Flask](https://flask.palletsprojects.com) framework with defaults that make it quick to start a new Clojure based web app without being heavy-handed.
What Zodiac includes by default:
- Routing and middleware. We use [Reitit](https://github.com/metosin/reitit)
- Request and response handing with [Ring](https://github.com/ring-clojure/ring).
- A Jetty server (though Jetty can be turned off)
- Automatic Hiccup-based HTML rendering using [Chassis](https://github.com/onionpancakes/chassis).
- Websocket support
- File streaming
- Flash messages
- Cookies and secure session handler
- Form and JSON request parsing
- Extensible, see [Zodiac Assets](https://github.com/brettatoms/zodiac-assets) and [Zodiac SQL](https://github.com/brettatoms/zodiac-sql)
- Convenience
- Helpers to lookup routes
- Helpers to return hiccup and JSON responses
- A request context
- Variables dynamically bound to the current request, router and session
What Zodiac doesn't do:
- Dictate a file structure with generators or scaffolding.
- No configuration over code
- No path based routing, etc.
- Expect a certain database - (see [Zodiac SQL](https://github.com/brettatoms/zodiac-sql))
- Asset bundling (see [Zodiac Assets](https://github.com/brettatoms/zodiac-assets))
And that's about it. Zodiac is mostly feature complete although you can expect plenty of bug fixes and polish before a 1.0.x release.
Read the [docs](https://cljdoc.org/d/com.github.brettatoms/zodiac).
### Getting started
``` clojure
(ns myapp
(:require [zodiac.core :as z]))
(defn routes []
;; routes use the reitit route syntax
["/" {:handler (constantly {:status 200
:body "ok"})}])
(z/start {:routes #'routes})
```
### Options
The `zodiac.core/start` function takes a single options map with the following keys:
- `:routes`: The route definition using the reitit route syntax
- `:extensions`: A sequence of functions that accept an integrant system configuration map and return a modified integrant system configuration app.
- `:request-context`: A map of values values to add to the `::z/context` map in the request map.
- `:cookie-secret`: The secret used to encrypt the cookie
- `:cookie-attrs`: Override the code settings. Defaults to `{:http-only true :same-site :lax}`.
- `:jetty`: A map of options to pass to `run-jetty` function of the embedded [ring-jetty-adapter](https://ring-clojure.github.io/ring/ring.adapter.jetty.html)
- `:port`: The port to listen for connections. If the port is also specified in the `:jetty` map then this value will be ignored. The default is `3000`.
- `:error-handlers`: A map of types to error handler functions
- `:anti-forgery-whitelist`: A sequence or strings or regular expressions to bypass anti-forgery/csrf checking for matching routes.
- `:reload-per-request?`: Reload the routes on every request. For this to work you will need to pass the var of the routes function, e.g. `#'routes`.
- `:print-request-diffs?`: Print a diff of each request between each middleware.
- `:start-server?`: Set to `false` to disable the embedded jetty server.
- `:middleware`: A list of ring middleware. Wraps, not replaces, the default middleware.
- `:default-handler`: Add a handler that gets called if a requested route doesn't match. Zodiac already includes a default handler created with [create-default-handler](https://cljdoc.org/d/metosin/reitit/0.9.1/api/reitit.ring?q=create-default-#create-default-handler). This option allows a handler to be called before the regular default handler gets called. For more information see the [Default handler](https://cljdoc.org/d/metosin/reitit/0.9.1/doc/ring/default-handler?q=create-default-#default-handler) section in the Reitit docs.
### Render HTML
Return a vector from the response handler to automatically convert the vector to an html response.
``` clojure
(ns myapp
(:require [zodiac.core :as z]))
(defn routes []
;; Returns a text/html response with
hi for the body.
["/" {:handler (fn [_] [:div "hi"])}])
(z/start {:routes #'routes})
```
### Render JSON
Use the `zodiac.core/json-response` function to encode Clojure maps to JSON and return `application/json` HTTP responses.
``` clojure
(ns myapp
(:require [zodiac.core :as z]))
(defn routes []
;; Returns an application/json response with {"hello": "world"} for the body.
["/" {:handler (fn [_] (z/json-response {:hello "world"}))}])
(z/start {:routes #'routes})
```
### Extending
Zodiac can be extended using a sequence of functions that take an integrant system map and return a modified integrant system map.
``` clojure
(defn service-ext [cfg]
(-> cfg
;; Add a ::service component to the config map
(assoc ::service {:value "hi"})
;; Put an instance of the service in the request context
(assoc-in [::z/middleware :context :service] (ig/ref ::service))))
(defn routes []
;; routes use the reitit route syntax
["/" {:handler (fn [{:keys [::z/context]}]
{:status 200
:body (-> context :service :value)})}])
(z/start {:routes #'routes
:extensions [service-ext]})
```
### Examples
- [Clojure Land](https://clojure.land): Discover open-source Clojure libraries and frameworks.
- [Zodiac Todo App](https://github.com/brettatoms/zodiac-todo-example): A very basic todo app build with Zodiac, Zodiac Assets, Zodiac SQL, Sqlite, AlpineJS, Htmx, Tailwind and Vite.
- [Websocket example](/examples/websocket): An example of how to uses websockets with Zodiac
### Extensions
- [Zodiac Assets](https://github.com/brettatoms/zodiac-assets): Static asset
building and url lookup with [Vite](https://vite.dev/).
- [Zodiac SQL](https://github.com/brettatoms/zodiac-sql): Helper for connecting
to SQL database and running
[HoneySQL](https://github.com/seancorfield/honeysql) queries.