Docs Why Wagoe Libraries Blog GitHub Get Started →
v1.0.0-beta-2 — Now available

The Clojure framework
that ships the whole stack.

25 independent libraries. Enforced FC/IS architecture. One coherent stack, zero lock-in.

$ curl -fsSL https://get.wagoe.org | bash
25
Independent Libraries
FC/IS
Enforced by Design
1.12
Clojure Compatibility
Zero
Vendor Lock-in
What's included

The full stack, built in.

Stop stitching together libraries. Every component follows the same patterns, tests the same way, and swaps via configuration.


Architecture

Enforced. Not suggested.

Every Wagoe module follows Functional Core / Imperative Shell. The directory structure makes clean architecture the default — not a convention that erodes over time.

Imperative Shell
shell/
I/O · HTTP handlers · Persistence · Side effects
http.clj service.clj persistence.clj
Ports — Protocol Definitions
ports.clj
Interfaces only · Injectable adapters · No implementation
defprotocol
Functional Core
core/
Pure functions · Business logic · No I/O · No mocks needed
validation.clj domain.clj rules.clj

Enforced by directory layout + clj-kondo rules  ·  Every library follows the same structure


25 Libraries

Pick what you need.
Drop what you don't.

Each library is a standard deps.edn dependency, independently publishable to Clojars.


Real code

See the patterns. Feel the clarity.

Terminal
# Natural language module generation
$ bb scaffold ai "order module with customer, total, status"

 Schema defined       schema.clj
 Validation rules     core/validation.clj
 Persistence layer    shell/persistence.clj
 HTTP routes          shell/routes.clj
 Service layer        shell/service.clj
 Tests generated      test/core_test.clj

Generated 6 files in libs/order/
All tests passing: 12/12
schema.clj
(ns wagoe.order.schema
  (:require [malli.core :as m]))

(def Order
  [:map
   [:id          :uuid]
   [:customer-id :uuid]
   [:total       [:and :decimal [:> 0]]]
   [:status      [:enum
                  :pending
                  :paid
                  :shipped
                  :delivered]]
   [:created-at  :instant]])
order/workflow.clj
(defworkflow order-workflow
  {:initial-state :pending
   :states        #{:pending :paid
                    :shipped :delivered
                    :cancelled}
   :transitions
   [{:from :pending
     :to   :paid
     :required-permissions [:finance]}
    {:from  :paid
     :to    :shipped
     :guard :payment-confirmed}
    {:from :shipped
     :to   :delivered}]})

; Pure core logic — no I/O, no mocks needed

Pure business logic

The entire state machine lives in core/ — no I/O, no side effects. Test every transition without a database or mock.

Audit trail by default

Every state change is recorded with who, when, and from/to state. Query with plain SQL.

Guards + permissions

Role-based guards and custom guard functions. The workflow rejects invalid transitions at the transition layer.

config.edn
;;; Development — zero setup, zero config
{:wagoe/db-context
 {:adapter   :sqlite
  :db        "dev.db"}

 :wagoe/cache
 {:adapter   :in-memory}

 :wagoe/observability
 {:log-adapter  :stdout
  :err-adapter  :no-op}}

;;; Production — one key change each. Zero code changes.
{:wagoe/db-context
 {:adapter   :postgresql
  :host      #env DB_HOST
  :pool-size 10}

 :wagoe/cache
 {:adapter   :redis
  :uri       #env REDIS_URL}

 :wagoe/observability
 {:log-adapter  :datadog
  :err-adapter  :sentry
  :dsn          #env SENTRY_DSN}}
routes.clj
;;; Cross-cutting concerns declared alongside the route.

{:path    "/api/admin/orders"
 :methods
 {:post
  {:handler      'handlers/create-order
   :interceptors ['auth/require-admin
                  'audit/log-action
                  'rate-limit/admin
                  'metrics/record-latency]}}}

;;; Service layer — one macro call, all telemetry automatic
(defn create-order [this order-data]
  (service/execute
    :create-order {:order order-data}
    (fn [{:keys [params]}]
      (order-core/prepare
        (:order params)))))

; Automatically instruments: structured logs, metrics,
; Sentry breadcrumbs, PII redaction. No telemetry code needed.

vs the alternatives

Not another toolkit.

Kit, Phoenix, Django, and Rails all require you to assemble and wire the pieces yourself. Wagoe ships FC/IS enforcement, auto-admin UI, multi-tenancy, state machine workflows, full-text search, report generation, PII redaction, and framework-aware AI tooling — built in, consistent, following the same patterns across all 25 libraries.


Measurable ROI at every scale.

Numbers based on comparing Wagoe to assembling a custom Clojure stack from scratch.


Built for every stage.

The ROI compounds. Small teams ship faster. Growing companies scale without chaos. Enterprises govern without mandates.


Up in minutes

From zero to running in three steps.

01
Install the CLI
curl -fsSL https://get.wagoe.org | bash
Requires curl, git, and Babashka (bb). Installs the wagoe command.
02
Scaffold a new project
wagoe new my-app cd my-app
Wires four core modules — core, observability, platform, and user. Add more with wagoe add payments.
03
Start the REPL
source .env clojure -M:repl-clj
HTTP server on :3000, REPL-driven workflow, zero-config SQLite database. wagoe new already generated .env with a real JWT_SECRET.

Join the community.

Follow development on GitHub and chat on Clojurians Slack.

GitHub Clojurians Slack Start Building