Bauhaus is an opinionated set of foundational modules to optimize DevOps experience with Clojure-based services.
Bauhaus is a set of modules that are designed to be used together. The modules are designed to be used with Integrant, but can be used without it.
It is the distillation of the experience of running Clojure services in production in several different organizations.
Named after the influential design movement, Bauhaus emphasizes functional design, modular composition, and practical utility. Just as Bauhaus architecture focused on essential functionality without unnecessary ornamentation, this framework provides essential infrastructure without bloat.
"Form follows function" - applied to Clojure application architecture.
This is a monorepo containing multiple modules and example applications:
bauhaus/
βββ modules/ # Reusable Bauhaus modules
β βββ setup/ # Application setup utilities
β β βββ logging/ # Logging infrastructure
β β βββ shutdown/ # Graceful shutdown hooks
β β βββ cli/ # Command-line interface
β βββ dev-tooling/ # Development utilities
β β βββ config/ # Configuration management
β β βββ build/ # Build and deployment
β βββ clojure-contrib/ # Clojure utility extensions
β βββ collection/ # Collection utilities
βββ applications/ # Example applications
β βββ example/ # Basic Bauhaus application
β βββ example-http-service/ # HTTP service example
βββ docs/ # Documentation
There is an example application showing usage in applications/example and an example http service showing more elaborate usage in application/example-http-service.
See Documentation: Intro for a more detailed introduction utilizing the two example applications.
At least for starting, going with the monorepo approach is the way to go. It becomes more complicated if you do not have 10s of applications, but 100s or 1000s of deployment artefacts, but for moving fast within a scoped context, a monorepo approach is favourable.
Clone the entire repository (or your own fork) for development:
git clone https://github.com/gorillalabs/bauhaus.git
# Copy the basic example
cp -r applications/example applications/my-new-project
cd applications/my-new-project
# Update project namespace in src/example/ β src/my-project/
# Update deps.edn and configuration as needed
- Create project structure:
mkdir -p applications/my-project && cd applications/my-project
mkdir -p {src,resources,dev,dev-resources,test}
- Create deps.edn:
{:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.12.0"}
integrant/integrant {:mvn/version "0.13.1"}
aero/aero {:mvn/version "1.1.6"}
;; Add Bauhaus modules as needed
org.gorillalabs.bauhaus/setup-logging
{:git/url "https://github.com/gorillalabs/bauhaus.git"
:git/sha "LATEST_SHA"
:deps/root "modules/setup/logging"}}
:aliases
{:dev {:extra-paths ["dev" "dev-resources"]
:extra-deps {integrant/repl {:mvn/version "0.4.0"}
org.gorillalabs.bauhaus/dev-config
{:git/url "https://github.com/gorillalabs/bauhaus.git"
:git/sha "LATEST_SHA"
:deps/root "modules/dev-tooling/config"}}}
:build {:deps {org.gorillalabs.bauhaus/build
{:git/url "https://github.com/gorillalabs/bauhaus.git"
:git/sha "LATEST_SHA"
:deps/root "modules/dev-tooling/build"}}
:paths ["build"]
:ns-default build}}}
- Set up development workflow:
;; dev/user.clj
(ns user
(:require [integrant.repl :as ig-repl]
[gorillalabs.bauhaus.dev-tooling.config :as dev-config]))
(ig-repl/set-prep! (constantly (dev-config/ig-config "dev-resources/dev-config.edn")))
(def go ig-repl/go)
(def halt ig-repl/halt)
(def reset ig-repl/reset)
- Create your system configuration:
;; src/my_project/system.clj
(ns my-project.system
(:require [integrant.core :as ig]))
(defn system-config [config]
{:my-project/core {:message (:message config)}})
(defmethod ig/init-key :my-project/core [_ config]
(println "Starting with:" (:message config))
config)
(defmethod ig/halt-key! :my-project/core [_ component]
(println "Stopping"))
To use Bauhaus build tools in your project:
- Add build configuration:
;; build/build.clj
(ns build
(:require [gorillalabs.bauhaus.build.version :as version]))
(defn uber [opts]
(let [version-string (version/application-build-string)]
(println "Building version:" version-string)
;; Your build logic here
))
- Use git tags for versioning:
git tag v1.0.0 # Bauhaus build tools will use this
clj -T:build uber
Recommended module combinations:
- Basic CLI app: setup/logging + setup/cli + setup/shutdown
- Web service: + http-server
- Development: + dev-tooling/config + dev-tooling/build
You can, of course, reference specific modules even if you do not use all of Bauhaus or the monorepo structure:
{:deps {;; Core dependencies
org.clojure/clojure {:mvn/version "1.12.0"}
integrant/integrant {:mvn/version "0.13.1"}
;; Bauhaus modules (pick what you need)
org.gorillalabs.bauhaus/setup-logging
{:git/url "https://github.com/gorillalabs/bauhaus.git"
:git/sha "COMMIT_SHA" ; Pin to specific commit
:deps/root "modules/setup/logging"}
org.gorillalabs.bauhaus/setup-shutdown
{:git/url "https://github.com/gorillalabs/bauhaus.git"
:git/sha "COMMIT_SHA"
:deps/root "modules/setup/shutdown"}}}
π‘ Tip: Check latest commits for the most recent SHA
Foundation for application infrastructure
Module | Path | Description |
---|---|---|
Logging | modules/setup/logging | Setup proper logging infrastructure, fighting the JVM logging chaos. |
Shutdown | modules/setup/shutdown | Provide ordered shutdown hooks as proposed in Killing me softly: Graceful shutdowns in Clojure |
CLI | modules/setup/cli | Setup a CLI for your application. |
Enhanced developer experience
Module | Path | Description |
---|---|---|
Config | modules/dev-tooling/config | Handle development config and ease Integrant REPL integration. |
Build | modules/dev-tooling/build | Support building your app with version management. |
Enhanced standard library
Module | Path | Description |
---|---|---|
Collection | modules/clojure-contrib/collection | Collection utilities including deep-merge and more. |
- π Read the Philosophy: Design Choices - Understand the "why"
- β‘ Quick Win: Run the Basic Example in 2 minutes
cd applications/example clj -M:dev # In REPL: (go)
- π Real Application: Explore the HTTP Service Example
- π§ Build Your Own: Follow Creating New Projects
- π Deep Dive: Comprehensive Introduction
- Building CLI tools: Start with setup/logging + setup/cli
- Web applications: Try example-http-service first
- Learning Integrant: Both examples show different patterns
- Production deployment: Check build tooling and shutdown hooks
This project includes a Nix flake to provide a reproducible development environment.
You must have Nix installed with flake support enabled. You can find installation instructions on the official NixOS website.
Navigate to the project's root directory and run the following command:
nix develop
This will download all the required dependencies and drop you into a nushell
with the following tools available:
jdk23
clojure
git
Upon activation, it will confirm the Java and Clojure versions available in the shell.
We welcome contributions! Please:
- Check existing issues before creating new ones
- Fork the repository for your own modules, applications and/or pull requests.
- Follow the established patterns in existing modules
- Add tests for new functionality
- Update documentation as needed
"Module not found" errors:
- Verify the
:git/sha
points to a valid commit - Check that
:deps/root
path matches the actual module location - Ensure module dependencies are compatible
REPL development issues:
- Run
(reset)
if code changes aren't reflecting - Check that
dev-resources/dev-config.edn
exists - Verify Integrant system configuration is valid
Build problems:
- Check that build namespace is properly configured in
:build
alias
Getting Help:
- Check individual module READMEs for specific guidance
- Review the Introduction Guide for detailed examples
- Look at working examples in
applications/
directory
- Replace Mount states with Integrant components
- Use Bauhaus setup modules for logging and shutdown
- Leverage enhanced REPL workflow
- Integrant provides similar lifecycle management
- Bauhaus adds production-ready operational modules
- Configuration management is enhanced with Aero
- Gradual adoption - start with one or two modules
- Enhanced REPL development experience
- Production operational capabilities