0.1.23 docs





    Jan 30, 2017

    Will Farrell
    Providence, RI


    Index of all namespaces

    The README below is fetched from the published project artifact. Some relative links may be broken.



    A Clojure library designed to improve your development experience without putting you in a cage. I created it originally to help generate static sites, but it has grown into something with wider application.

    Aviary attempts to tastefully stitch together preexisting clojure tools (like http-kit, hawk, and figwheel) to provide a cohesive development environment. It relies on Sturt Sierra’s component library to manage service lifecycle, and comes with a number of useful components to help kickstart initial setup. Since they are “just” components, you can write your own, or use someone else’s.

    Aviary can provide a similar experience to chestnut, but since it’s a library, it’s easier to integrate into existing projects.

    Some (potentially) interesting Aviary features:

    • Uses plain components
    • Very flexible
    • Easily configurable
    • Uniform log messages
    • A name related to birds


    To quickly create a new project with aviary installed, use aviary/lein-template from the command line:

    lein new aviary <project-name>

    To install aviary in an existing project, add the following dependency to your project.clj file:

    Clojars Project


    Using Aviary is mostly about building systems of components, and then running the system. We’ll start with some simple examples.

    A Simple System

    Let’s build a simple system to reload clj namespaces as the files are changed on disk.

    Begin by requiring the necessary Aviary namespaces:

    (require '[aviary.system :refer [defsystem defsystem* start stop]]
             '[ :refer [watch watch-clj]])

    Then define the system with the defsystem macro:

    (defsystem dev
      (watch [(watch-clj ["src"])]))

    It’s also possible to name system components using the defsystem* macro. This is functionally equivalent to the above example:

    (defsystem* dev
      :watch (watch [(watch-clj ["src"])]))

    Now you can use the start and stop functions to control the lifecycle of the system (and all its components).

    ;; start the system
    (start dev)
    ;; stop the system
    (stop dev)

    While the system is running, namespaces are reloaded as you save changes to source files.

    See the API documentation for more details.

    A More Complicated System

    Now let’s see a more complicated example. This system will reload namespaces with, rebuild cljs with aviary.figwheel, and serve development assets with aviary.serve. Figwheel is also used to reload the browser when files change.

    (require '[ :as style]
             '[example.markup :as markup]
             '[aviary.system :refer [defsystem* start stop]]
             '[ :refer [watch] :as w]
             '[aviary.serve :refer [serve]]
             '[aviary.figwheel :as fw])
    ;; ...
    ;; manifests are functions that return a map of paths to content producing functions
    ;; example: (fn [config] {"" #(str "hello world")})
    (defn style-manifest []
      (style/manifest style-config))
    ;; same as above, but for markup files
    (defn markup-manifest []
      (markup/manifest markup-config))
    (defsystem* dev
      ;; create a component to serve development assets
      :serve (serve
              {:port 3000
                     ;; serve files from these resource paths
                     :resources ["assets"
                     ;; manifests are functions that return a map of paths to content producing functions
                     ;; (fn [config] {"" #(str "hello world")})
                     :manifests {"text/css" style-manifest
                                 "text/html" markup-manifest}})
      ;; the `using` macro is similar to `using` from the component library, but also creates a lexical binding for any dependencies.
      :watch (using [fw :figwheel]
                    ;; create a component to watch source code files for changes
                    (watch [(w/watch-clj
                             ;; the `watch-clj` handler accepts the reloaded namespace as an argument
                             #(condp = %
                                     ;; when the ' namespace changes, send a list of changed files to the client with figwheel
                                     ' (->> (style-manifest) keys (fw/reload-css fw))
                                     ;; same as above, only for markup changes
                                     'example.markup (->> (markup-manifest) keys (fw/reload-html fw)) nil))
                            ;; watch far changes to cljs source files
                            (fw/watch-cljs fw {:source-paths ["src/dev/cljs"
                                                             ;; build cljs files and send a list of changes to the client with figwheel
                                                             :build-options {:output-to "resources/target/assets/js/out/main.js"
                                                                                        :output-dir "resources/target/assets/js/out"
                                                                                        :optimizations :none
                                                                                        :source-map true
                                                                                        :pretty-print true
                                                                                        :warnings {:single-segment-namespace false}}})]))
      ;; create a component to manage the figwheel websocket server
      :figwheel (fw/serve {:port 3001
                                 :output-to "resources/target/assets/js/out/main.js"
                                 :output-dir "resources/target/assets/js/out"}))
    ;; start the dev system
    (start dev)
    ;; stop the dev system
    (stop dev)

    On the client, connect to the figwheel server to receive update notifications.

    (require '[example.core :as example]
             '[aviary.figwheel :as fw])
    ;; start the figwheel client
     ;; Since cljs is updated without refreshing the page, it can be necessary to update your app's state
     {:on-jsload #(do (example/stop) (example/start))
      ;; since figwheel isn't serving static assets, it's necessary to specify the figwheel websocket url
      :websocket-url "ws://localhost:3001/figwheel-ws"})


    For now, the best API documentation is the docstrings in the source code.


    To run the tests for Aviary, use lein:

    lein test


    Copyright (c) 2015 Will Farrell

    Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.