Top Related Projects
Quick Overview
Duct is a data-driven framework for building server-side applications in Clojure. It provides a structured approach to application development, emphasizing modularity, configuration, and extensibility. Duct aims to simplify the process of creating robust and maintainable Clojure applications.
Pros
- Modular architecture that promotes clean, organized code
- Extensive configuration options for flexibility and customization
- Built-in support for common web development tasks (routing, middleware, etc.)
- Strong emphasis on testing and development workflows
Cons
- Steeper learning curve for developers new to Clojure or functional programming
- May be overkill for small, simple projects
- Limited community resources compared to more mainstream frameworks
- Requires understanding of Clojure's unique approach to web development
Code Examples
- Defining a simple route:
(defmethod ig/init-key :duct.handler/root [_ {:keys [routes]}]
(fn [request]
(if-let [handler (routes (:uri request))]
(handler request)
{:status 404, :body "Not Found"})))
- Configuring a database connection:
{:duct.database/sql
{:connection-uri "jdbc:sqlite:db/example.sqlite"}}
- Creating a simple handler:
(defmethod ig/init-key :example.handler/greet [_ _]
(fn [_]
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello, World!"}))
Getting Started
- Add Duct to your project dependencies:
[duct/core "0.8.0"]
- Create a new Duct project using Leiningen:
lein new duct <project-name>
cd <project-name>
- Start the development environment:
lein duct setup
lein repl
- In the REPL, start the system:
(dev)
(go)
Your Duct application is now running and ready for development.
Competitor Comparisons
Micro-framework for data-driven architecture
Pros of Integrant
- Simpler and more flexible design, allowing for easier customization
- Lighter weight with fewer dependencies
- Can be used independently of web frameworks, suitable for various application types
Cons of Integrant
- Less opinionated, requiring more manual configuration
- Fewer built-in integrations and modules compared to Duct
- Steeper learning curve for beginners due to its flexibility
Code Comparison
Integrant configuration:
(def config
{:app/db {:connection-uri "jdbc:sqlite:example.db"}
:app/handler {:db #ig/ref :app/db}
:app/server {:handler #ig/ref :app/handler, :port 8080}})
Duct configuration:
(def config
{:duct.profile/base
{:duct.core/project-ns 'example
:duct.server.http/jetty {:port 8080}
:duct.router/ataraxy
{:routes {[:get "/"] [:example.handler/index]}}}})
Both Integrant and Duct are Clojure libraries for managing application configuration and lifecycle. Integrant offers more flexibility and simplicity, making it suitable for various application types. Duct, built on top of Integrant, provides a more opinionated structure with additional integrations, making it particularly well-suited for web applications. The choice between them depends on the specific project requirements and developer preferences.
A fast data-driven routing library for Clojure/Script
Pros of Reitit
- More flexible and modular routing system
- Better performance for large applications
- Extensive support for data-driven routing
Cons of Reitit
- Steeper learning curve for beginners
- Less opinionated, requiring more configuration
Code Comparison
Reitit routing example:
(def app
(ring/ring-handler
(ring/router
["/api" {:middleware [wrap-formats]}
["/users" {:get get-users
:post create-user}]])))
Duct routing example:
(def routes
(ataraxy/handler
{[:get "/api/users"] [:users/list]
[:post "/api/users"] [:users/create]}))
Summary
Reitit offers a more flexible and performant routing solution, ideal for larger applications with complex routing needs. It provides extensive support for data-driven routing but may have a steeper learning curve.
Duct, on the other hand, provides a more opinionated and structured approach, which can be beneficial for smaller projects or developers new to Clojure web development. It offers a simpler setup process but may be less flexible for complex routing scenarios.
The choice between the two depends on the project's specific requirements, team expertise, and desired level of control over the routing system.
managing Clojure and ClojureScript app state since (reset)
Pros of Mount
- Lightweight and focused solely on configuration management
- Flexible and can be used with any Clojure application or framework
- Simple API with easy-to-understand concepts (states and sources)
Cons of Mount
- Less opinionated, requiring more manual setup for larger applications
- Lacks built-in support for component lifecycle management
- May require additional libraries for full application structure
Code Comparison
Mount:
(mount/defstate db
:start (create-connection config)
:stop (disconnect db))
(mount/start)
Duct:
(defmethod ig/init-key :app/db [_ config]
(create-connection config))
(defmethod ig/halt-key! :app/db [_ db]
(disconnect db))
(ig/init config)
Summary
Mount is a lightweight configuration management library, while Duct is a more comprehensive web application framework. Mount offers simplicity and flexibility, making it suitable for various Clojure projects. Duct provides a more structured approach with built-in component lifecycle management and integration with other libraries.
Choose Mount for simpler projects or when you need a flexible configuration solution. Opt for Duct when building larger web applications that benefit from its opinionated structure and ecosystem integration.
A ClojureScript framework for building user interfaces, leveraging React
Pros of re-frame
- Specifically designed for building single-page applications (SPAs) in ClojureScript
- Provides a clear and opinionated structure for managing application state
- Extensive documentation and a large, active community
Cons of re-frame
- Limited to frontend development, unlike Duct's full-stack capabilities
- Steeper learning curve for developers new to reactive programming concepts
- May be overkill for simple applications or static websites
Code Comparison
re-frame:
(re-frame/reg-event-db
:initialize-db
(fn [_ _]
{:name "re-frame"}))
Duct:
(defmethod ig/init-key :app/routes [_ {:keys [db]}]
[["/" {:get (fn [_] {:status 200 :body "Hello, Duct!"})}]])
Summary
re-frame excels in frontend development for ClojureScript SPAs, offering robust state management and a structured approach. Duct, on the other hand, provides a more comprehensive full-stack solution for Clojure web applications. While re-frame focuses on reactive programming patterns, Duct emphasizes modularity and configuration-driven development. The choice between the two depends on project requirements and whether a full-stack or frontend-specific solution is needed.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Duct
Duct is a highly modular framework for building server-side applications in Clojure using data-driven architecture.
It is similar in scope to Arachne, and is based on Integrant. Duct builds applications around an immutable configuration that acts as a structural blueprint. The configuration can be manipulated and queried to produce sophisticated behavior.
Upgrading
See: UPGRADING.md.
Quick Start
To create a new Duct project with Leiningen:
lein new duct <your project name>
This will create a minimal Duct project. You can extend this by appending profile hints to add extra functionality.
+api
adds API middleware and handlers+ataraxy
adds the Ataraxy router+cljs
adds in ClojureScript compilation and hot-loading+example
adds an example handler+heroku
adds configuration for deploying to Heroku+postgres
adds a PostgreSQL dependency and database component+site
adds site middleware, a favicon, webjars and more+sqlite
adds a SQLite dependency and database component
For example:
lein new duct foobar +site +example
As with all Leiningen templates, Duct will create a new directory with
the same name as your project. For information on how to run and build
your project, refer to the project's README.md
file.
Concepts
The structure of the application is defined by an Integrant configuration map.
In development, Duct uses Stuart Sierra's Reloaded Workflow.
In production, Duct follows the Twelve-Factor App methodology.
Local state is preferred over global state.
Namespaces should group functions by purpose, rather than by layer.
Protocols should be used to wrap external APIs.
Structure
Duct adds a layer of abstraction on top of Integrant. In Integrant, a configuration map is initiated into a running system map.
ââââââââââ ââââââââââ
â config âââ>â system â
ââââââââââ ââââââââââ
In Duct, the configuration is initiated twice. The configuration is first initiated into an intermediate configuration, which in turn is initiated into the system:
ââââââââââ ââââââââââââââââ ââââââââââ
â config âââ>â intermediate âââ>â system â
ââââââââââ ââââââââââââââââ ââââââââââ
In the same way that higher-order functions allow us to abstract common patterns of code, Duct's layered configurations allow us to abstract common patterns of configuration.
Keys in a Duct configuration are expected to initiate into functions that transform a configuration map. There are two broad types: profiles, which merge their value into the configuration, and modules, which provide more complex manipulation.
Documentation
Community
- Google Group
- #duct on Clojurians Slack
File structure
Duct projects are structured as below. Files marked with a * are kept out of version control.
{{project}}
âââ README.md
âââ dev
â  âââ resources
â  â  âââ dev.edn
â  â  âââ local.edn *
â  âââ src
â  âââ dev.clj
â  âââ local.clj *
â  âââ user.clj
âââ profiles.clj
âââ project.clj
âââ resources
â âââ {{project}}
â  âââ config.edn
âââ src
â  âââ duct_hierarchy.edn
â  âââ {{project}}
â  âââ main.clj
âââ test
âââ {{project}}
License
Copyright © 2021 James Reeves
Distributed under the MIT license.
Top Related Projects
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot