Start a new project

View the code for this section.

As with any Biff project, we'll need to run the new project script. We'll add a tutorial argument so that your project will be based on the same version of Biff that was used for writing this tutorial. Important bits (mainly, stuff you should type) are highlighted in yellow:

$ bb -e "$(curl -s" tutorial
Enter name for project directory: eelchat
Enter main namespace (e.g. com.example): com.eelchat

Your project is ready. Run the following commands to get started:

  cd eelchat
  git init
  bb dev

And run `bb tasks` for a list of available commands.

You'll need to install Babashka if you haven't already. After your project has been created, start up the app with bb dev:

$ cd eelchat/

$ git init
Initialized empty Git repository in /home/jacob/dev/eelchat/.git/

$ git add .

$ git commit -m "First commit"
[master (root-commit) 95db1ca] First commit
 22 files changed, 785 insertions(+)

$ bb dev
Downloading the latest version of Tailwind CSS...
[main] INFO com.biffweb.impl.util - System started.
[main] INFO com.eelchat - Go to http://localhost:8080
[chime-1] INFO com.eelchat.worker - There are 0 users. (This message gets printed every 5 minutes. You can disable it by setting `:com.eelchat/enable-worker false` in config.edn)
nREPL server started on port 7888 on host localhost - nrepl://localhost:7888

Once you see that "System started" message above, the application is running. Go to localhost:8080, then enter into the signin form. You'll see a link printed to the terminal:

[qtp1015916495-34] INFO com.biffweb.impl.middleware -   2ms 200 get  /
[qtp1015916495-37] INFO com.biffweb.impl.middleware -   1ms 200 get  /css/main.css?t=1667015729284
[qtp1015916495-33] INFO com.biffweb.impl.middleware -   1ms 200 get  /img/glider.png
[qtp1015916495-37] INFO com.biffweb.impl.middleware -   2ms 200 get  /
Click here to sign in as http://localhost:8080/auth/verify/ey[...]
[qtp1015916495-33] INFO com.biffweb.impl.middleware -  14ms 303 post /auth/send
[qtp1015916495-37] INFO com.biffweb.impl.middleware -   0ms 200 get  /auth/printed/
[qtp1015916495-33] INFO com.biffweb.impl.middleware -   0ms 200 get  /css/main.css?t=1667015729284

Open that link, and you should be signed in!

A screenshot of the example app after signing in

Delete some code

New projects come with a bunch of example code for you to inspect and tinker with. But since this is a tutorial, we'll delete most of it and start fresh. First, let's remove the com.eelchat.worker namespace. Remove it from com.eelchat first:

;; src/com/eelchat.clj
;; ...
             [ :as email]
             [ :as app]
             [com.eelchat.home :as home]
-            [com.eelchat.worker :as worker]
             [com.eelchat.schema :as schema]
             [clojure.test :as test]
             [ :as log]
;; ...
 (def plugins
    (biff/authentication-plugin {})
-   schema/plugin
-   worker/plugin])
+   schema/plugin])

 (def routes [["" {:middleware [biff/wrap-site-defaults]}
               (keep :routes plugins)]

Then delete the src/com/eelchat/worker.clj file.

Next, we'll go to and delete, well, almost everything. This file is responsible for everything you see in the screenshot above. We'll replace it with a simple Nothing here yet message:

;; src/com/eelchat/app.clj
  (:require [com.biffweb :as biff :refer [q]]
            [com.eelchat.middleware :as mid]
            [com.eelchat.ui :as ui]
            [xtdb.api :as xt]))

(defn app [{:keys [session biff/db] :as ctx}]
  (let [{:user/keys [email]} (xt/entity db (:uid session))]
     [:div "Signed in as " email ". "
       {:action "/auth/signout"
        :class "inline"}
       [:button.text-blue-500.hover:text-blue-800 {:type "submit"}
        "Sign out"])
     [:div "Nothing here yet."])))

(def plugin
  {:routes ["/app" {:middleware [mid/wrap-signed-in]}
            ["" {:get app}]]})

Go back to localhost:8080, and it should look like this after you refresh the page:

A screenshot of the example app after updating app.clj

Finally, let's update our schema (com.eelchat.schema). We'll remove the :msg document and the :user/foo and :user/bar attributes, all of which were used by the code in which we just deleted.

;; src/com/eelchat/schema.clj
;; ...
 (def schema
   {:user/id :uuid
    :user [:map {:closed true}
           [:xt/id                     :user/id]
           [:user/email                :string]
+          [:user/joined-at            inst?]]})
-          [:user/joined-at            inst?]
-          [:user/foo {:optional true} :string]
-          [:user/bar {:optional true} :string]]
-   :msg/id :uuid
-   :msg [:map {:closed true}
-         [:xt/id       :msg/id]
-         [:msg/user    :user/id]
-         [:msg/text    :string]
-         [:msg/sent-at inst?]]})

If you played around with the example app at all, you might already have some :msg documents or :user/foo/:user/bar attributes in your database. Let's clear out the database to ensure we don't have any non-schema-conforming documents. Hit Ctrl-C in your terminal to stop the app, then run rm -r storage/xtdb/. Afterward, start the app up again with bb dev.

Have a question? Join the #biff channel on Clojurians Slack.

Sign up for Biff: The Newsletter
Announcements, blog posts, et cetera et cetera.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.