Liking cljdoc? Tell your friends :D

Why Boundary?

Boundary exists to make Clojure web applications feel deliberate instead of improvised.

The problem Boundary solves

Clojure is excellent for reliable systems, but the ecosystem leaves a lot of assembly work to every new project. Teams end up wiring together Ring, Reitit, next.jdbc, Malli, Integrant, auth libraries, and a few more moving parts before they can start building. Then they reinvent the same things again: authentication, pagination, validation, admin screens, module layout, and test structure.

Boundary packages those decisions into one coherent framework, so you do not have to rebuild the same foundation every time. The rule is to keep the Functional Core / Imperative Shell pattern visible everywhere, not just in the README.

For developers: 22 composable libraries

Use just boundary-core for validation utilities in an existing app, or compose the full stack with JWT + MFA auth, auto-generated CRUD UIs, background jobs, multi-tenancy, real-time WebSockets, and more.

Every library follows the same FC/IS structure, so a Boundary codebase feels familiar fast.

Ship faster with the scaffolder

bb scaffold ai "product module with name, price, stock"

The scaffolder generates production-ready modules in seconds. The admin UI can build CRUD screens from your schema, observability is built in, and declarative interceptors keep the plumbing out of your way.

Zero lock-in

Each library is a standard deps.edn dependency. Swap what doesn’t fit. If you do not need multi-tenancy, skip boundary-tenant. If you prefer a different cache backend, implement the cache port you need.

The FC/IS guarantee

Boundary enforces a clean separation between pure code and code that touches the outside world:

libs/{library}/src/boundary/{library}/
├── core/       ← Pure functions only. No I/O, no logging, no exceptions.
├── shell/      ← I/O, validation, persistence, HTTP, services.
├── ports.clj   ← Protocol definitions (interfaces).
└── schema.clj  ← Malli validation schemas.

That gives you business logic that is:

  • Fast to test — no mocks needed for core functions

  • Easy to reason about — given the same input, always the same output

  • Safe to refactor — the type system and tests catch regressions immediately

Compared to alternatives

PropertyBoundaryPedestalLuminus

Enforces FC/IS

Yes

No

No

Scaffolder

Yes (AI-assisted)

No

Partial

Admin UI

Auto-generated

No

No

Library granularity

22 independent libs

Monolithic

Template-based

Multi-tenancy

Built-in

No

No

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close