Philosophy
Why Clojure? Why Rakiba? This page explains the thinking behind the technology choices and design philosophy that make Rakiba the optimal foundation for modern web development.
Why Clojure? Why Now?
LLMs have finite context windows. Clojure is the most expressive language that exists.
This isn’t opinion - it’s math. When your AI assistant has 100k tokens to work with, every line of boilerplate is cognitive waste. Clojure’s power-to-noise ratio is unmatched:
;; 3 lines that would be 30+ in most languages
(->> users
(filter :active)
(map #(select-keys % [:id :name :email])))
This snippet filters a collection for active users and extracts just the fields you need. In Java, this would require streams, lambdas, and a DTO class. In JavaScript, you’d need multiple method chains and explicit destructuring. In Clojure, the code is the intent.
But expressiveness is only half the equation.
The Fastest Feedback Loop Possible
Clojure’s REPL isn’t a command line - it’s a live connection to your running application. Change a function, evaluate it, see the result. No restart. No rebuild. No waiting.
For AI-assisted development, this changes everything:
- LLM writes code -> evaluate in REPL -> sub-second feedback
- See the actual result -> iterate -> evaluate again
- Experiment freely -> no penalty for exploration
Compare this to the traditional workflow: write code -> rebuild -> restart server -> navigate to page -> check result -> repeat.
The REPL collapses a 30-second cycle into 300 milliseconds.
When you’re iterating with an AI assistant, this speed multiplier compounds. What would be dozens of slow edit-compile-test cycles becomes a rapid conversation where you can explore solutions, test hypotheses, and refine approaches in real-time.
Performance That Doesn’t Compromise
“But dynamic languages are slow.”
No. Check the benchmarks. Clojure on the JVM competes with Go, Rust, and C++. Rakiba hits 90k+ requests/second with http-kit on an 8-core VPS. The JVM’s JIT compiler has had 25 years of optimization by some of the best engineers on the planet.
You get:
- Expressiveness for rapid development
- Performance for production scale
- The REPL for the fastest possible feedback loop
Most frameworks force you to choose between developer experience and runtime performance. With Clojure, you don’t have to compromise.
Why Rakiba Exists
The best way to build web applications is Clojure. Full stop.
But the Clojure ecosystem is fragmented. Should you use Jetty or http-kit? Reagent or Fulcro? How do you wire it all together? Every project reinvents the same infrastructure.
The Problem
Starting a new Clojure web project means making dozens of decisions before writing a single line of business logic:
- Which HTTP server? (Jetty, http-kit, Undertow, Aleph, Immutant)
- Which frontend framework? (Reagent, Re-frame, UIx, Fulcro)
- Which state management? (Mount, Component, Integrant)
- How to structure routes, middleware, configuration?
- How to set up hot reloading, testing, deployment?
Then you wire it all together, create build scripts, configure shadow-cljs, set up SASS compilation… and you haven’t even started building your actual application yet.
The Solution
Rakiba is an opinionated-but-configurable foundation:
- Pick your server, frontend, and features from a menu
- Get a production-ready setup in minutes
- Framework code stays updatable; your code stays yours
The goal: remove every barrier between “I have an idea” and “it’s running in production.”
Like Doom Emacs provides a powerful, pre-configured Emacs distribution while preserving full customizability, Rakiba provides a powerful, pre-configured Clojure web stack while letting you swap any component.
Core Principles
Rakiba follows the Doom Emacs philosophy:
-
Configurable, not opinionated
Choose your stack via config. Want http-kit instead of Jetty? UIx instead of Re-frame? Change one line inrakiba.edn. The framework adapts to your preferences, not the other way around. -
Modular
Enable only what you need. Building an API-only backend? Skip the frontend entirely. Don’t need authentication? Don’t enable it. Every feature is opt-in. -
Updatable
Framework updates don’t break your code. Rakiba maintains a clear separation between “lib space” (framework code we manage) and “user space” (your application code). Runbb syncto get updates without losing your work. -
Fast
Performance is a feature, not an afterthought. From startup time to request throughput, every default is tuned for speed. No unnecessary abstractions, no hidden overhead. -
Observable
Beautiful logging, easy debugging. Telemere provides structured, colorized logs out of the box. When something goes wrong, you can see exactly what happened.
Built for AI-Assisted Development
Rakiba is designed from the ground up for the age of LLM-assisted coding:
-
Minimal boilerplate
Less code for the AI to read and write. When your context window is limited, signal-to-noise ratio matters. Clojure’s expressiveness means more logic fits in less space. -
REPL-first workflow
Sub-second feedback loops for rapid iteration. The AI can evaluate code, see results, and refine its approach without waiting for builds or restarts. -
Structured project layout
Predictable locations help AI navigate. Routes go here. Components go there. Configuration lives in one place. Consistency accelerates understanding. -
AI workflow integration
Built-in support for specification -> planning -> execution. Theai/directory contains guides, prompts, and workflow definitions that help AI assistants understand the codebase and work effectively within it.
The future of software development is human-AI collaboration. Clojure + REPL + Rakiba is the optimal stack for that future.
The Nature of Lisp
From Slava Akhmechet’s “The Nature of Lisp”
All source code is a tree. Compilers parse it into an Abstract Syntax Tree. XML is also a tree. So any code can be written as XML - and XML can be executed as code. Apache Ant proved this: those build files aren’t configuration, they’re a programming language.
Lisp’s parentheses are just a less verbose way to write that same tree:
;; XML: <copy><todir>../new</todir><fileset><dir>src</dir></fileset></copy>
;; Lisp:
(copy (todir "../new") (fileset (dir "src")))
The parentheses aren’t weird syntax. They’re the point. Code is data. Data is code. The distinction was always fake.
This unlocks something no other language has: macros that receive code as data, transform it with the full power of the language, and return new code. You can generate code at compile time using loops, conditionals, database queries - anything.
What This Looks Like in Practice
Every data format you work with is secretly a mini-language. SQL. HTML. JSON schemas. In most languages, you embed these as strings - error-prone, no tooling, impossible to compose. In Clojure, they’re just data:
;; HTML as data - compose it, generate it, transform it
[:div {:class "alert"}
[:h1 "Warning"]
[:p "Something went wrong"]]
;; SQL as data - no string concatenation, no injection
{:select [:name :email]
:from [:users]
:where [:= :active true]}
;; Schemas as data - validate, generate docs, derive UI
[:map
[:name :string]
[:age [:int {:min 0}]]]
These aren’t special DSL libraries with custom parsers. They’re plain Clojure vectors and maps. You manipulate them with regular functions. Store them in databases. Send them over the wire. Generate them programmatically.
The boundary between “code” and “data” and “configuration” dissolves. It was never real.
The Logical Endpoint
Every language keeps rediscovering pieces of this:
- Java added lambdas
- C# added LINQ
- JavaScript added template literals
- Rust added proc macros
They’re all reaching toward the same destination Lisp reached in 1958: programs that write programs.
There is no more powerful abstraction. It’s the asymptote. Clojure gives you this power plus the JVM ecosystem, immutable data structures, and a REPL that makes iteration instant.
Next Steps
- Getting Started - Set up your first project
- Configuration - Customize your stack
- Commands - Learn the available tasks