Web framework for ClojureScript on Node. WIP.
In the tradition of Django, Flask, and Rails. Designed for indie devs who ship fast. Battle tested on real sites.
Quick start | Examples | API
- Minimal.
- 12 factor.
- 👇 Batteries included.
Add Sitefox to your project as a dependency.
{:deps
{io.github.chr15m/sitefox {:git/tag "v0.0.1" :git/sha "????"}}}
An example server with two routes, one of which writes values to the key-value database.
(ns my.server
(:require
[sitefox.web :as web]
[sitefox.db :refer [kv]]
[sitefox.reloader :refer [reloader]]))
(defn home-page [req res]
; send a basic hello world response
(.send res "Hello world!"))
(defn hello [req res]
; write a value to the db key value database
(-> (kv "sometable")
(.write "key" "42")
(.then
(fn []
; database write is done
; send a basic hello world response
(.json res true))))
(defn setup-routes [app]
; flush all routes from express
(web/reset-routes app)
; set up an express route for "/"
(.get app "/" home-page)
; set up an express route for "/hello"
(.post app "/hello" hello)
; statically serve files from the "public" dir on "/"
; (or from "build" dir in PROD mode)
(web/static-folder app "/" (if (env "PROD") "build" "public")))
(defn main! []
; create an express server and start serving
; BIND_ADDRESS & PORT env vars set host & port.
(-> (web/start)
(.then (fn [app host port]
; reload the routes when the server js is modified (recompiled)
(reloader (partial #'setup-routes app))
; set up the routes for the first time
(setup-routes app)))))
More Sitefox examples here.
Sitefox uses the express
web server with sensible defaults for sessions and logging.
Create a new server with web/start
and set up a route which responds with "Hello world!" as follows:
(-> (web/start)
(.then (fn [app host port]
(.get app "/myroute"
(fn [req res]
(.send res "Hello world!"))))
Sitefox comes with an optional system to reload routes when the server is changed.
Your express routes will be reloaded every time your server code is refreshed (e.g. by a shadow-cljs build).
In this example the function setup-routes
will be called when a rebuild occurs.
(defn setup-routes [app]
; flush all routes from express
(web/reset-routes app)
; ask express to handle the route "/"
(.get app "/" (fn [req res] (.send res "Hello world!"))))
; during the server setup hook up the reloader
(reloader (partial #'setup-routes app))
I recommend the promesa library for managing promise control flow.
This example assumes require [promesa.core :as p]
:
(p/let [[app host port] (web/start)]
; now use express `app` to set up routes and middleware
)
Sitefox makes it easy to start storing key-value data with no configuration. You can then transition to more structured data later if you need. It bundles Keyv which is a database backed key-value store.
By default a local sqlite database is used so you can start persisting data on the server immediately without any configuration.
Once you move to production you can configure another database using the environment variable DATABASE_URL
.
For example, to use a postgres database called "somedatabase": DATABASE_URL=postgres://someuser:somepassword@somehost:5432/somedatabase
.
Or simply postgres:///somedatabase
if your user has local access on the deploy server.
Use the database and key-value interface as follows.
Require kv
from the database module:
[sitefox.db :as db]
Now you can use db/kv
to write a key-value to a namespaced "table":
(let [table (db/kv "sometable")]
(.set table "key" "42"))
Retrieve the value again:
(-> (.get table "key)
(.then (fn [val] (print val))))
You can use db/client
to access the underlying database connection.
For example to make a query against the configured database:
(let [c (db/client)]
(-> (.query db "select * from sometable WHERE x = 1")
(.then (fn [rows] (print rows)))))
Again, promesa is recommended for managing control flow during database operations.
TBD.
TBD.
TBD.
TBD.
Sitefox was made by Chris McCormick (@mccrmx). I iterated on it while building sites for myself and for clients.