day8/re-frame: a ClojureScript SPA framework where events are causal and views are reactive
A ClojureScript framework for building user interfaces, leveraging React
At a glance
- What is it?
- re-frame is a data-oriented ClojureScript framework built on Reagent and React, aimed at teams that want a single event pipeline instead of colocated queries and component lifecycle hooks. It is MIT licensed, and the repository's last push was on 2026-05-05.
- Who is it for?
- Adopt re-frame if your team already writes ClojureScript and wants one event pipeline rather than per-component state. Do not adopt it if you need a plain JavaScript or TypeScript stack, or if you expect the framework to manage server data fetching for you, because the README describes React as the V in MVC and nothing more.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 149 days ago.
- What is it written in?
- Mainly Clojure, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem re-frame solves: state and cause in a single-page app
Most UI frameworks put the cause of a change inside the component. A query lives next to the view that reads it, a lifecycle hook runs when the component mounts, and state ends up spread across the tree. re-frame takes the opposite road. The README states plainly that in re-frame events are causal and views are purely reactive, and that this differs from the currently-pervasive idea that views should be causal. The audience follows from that choice: teams building single-page applications in ClojureScript, where the app state is a value and every change to it arrives as data through one channel. The README describes the focus as high programmer productivity and scaling up to larger single-page applications, and says the framework has been used by small startups and by companies with over 500 developers, with production applications at 40K lines of code and beyond. Those are the project's own claims about its users, not measured benchmarks. The practical consequence is that a new engineer reads one file to learn how the app changes state, instead of tracing subscriptions through a component tree.
How the event and subscription pipeline works
The architecture visible in the README is a registry plus a queue. You register handlers with reg-event-db, reg-event-fx, or reg-event-ctx, and derived values with reg-sub. Effects are registered with reg-fx. A dispatch puts an event onto the pipeline; the handler for that event computes the next application state; subscriptions recompute derived values from that state; and the views that subscribed re-render. React sits at the bottom as the renderer, reached through Reagent, and the README is explicit that re-frame only needs React to be the V in MVC and no more. That is the whole shape. The interesting detail is what the framework does not do: it does not let a view trigger a change directly. A click dispatches an event, and the state transition is a pure function you can call in a test without a DOM. The README frames the lineage as a Lisp advantage, quoting Alan Kay's description of Lisp as Maxwell's equations of software and Paul Graham on Lisp as a competitive advantage. That is positioning rather than mechanism, but it explains why the API is registries and maps rather than classes and decorators.
Installing re-frame and wiring a first event
re-frame is published on Clojars, and the README points to the Clojars page for full dependency information. The repository carries deps.edn and shadow-cljs.edn at the top level, so a tools.deps or shadow-cljs project is the expected shape. The README does not print a deps.edn dependency coordinate, so the one thing to copy from the project page itself is the Clojars coordinate shown as the current version badge. What the README does give is the choice of API surface, and that decision affects every namespace that registers a handler. re-frame.core is the stable function API, and the README states that reg-event-db, reg-event-fx, reg-event-ctx, reg-sub, reg-fx and the dispatch and subscribe family are defns, so map, apply, reg-event-db, apply reg-sub and partial reg-fx all work as written:
;; function API — no source-meta
(:require [re-frame.core :as rf])
;; macro API — same call shape, source-meta captured
(:require [re-frame.macros :as rf])For call-site {:file :line} metadata in development and devtools, the README says to alias re-frame.macros instead. The call shape is identical, source metadata is captured at expansion time, and it is eliminated by dead code elimination in production ClojureScript. Once the namespace is required, an event handler and a subscription are registered under ids you choose, and a view that subscribed to the subscription id re-renders after a dispatch of the event id. The README does not walk through that registration in the excerpt, so the examples/ directories (flow, simple, todomvc) are the place to see a working app rather than a snippet.
Limits of the framework, and when it is the wrong tool
The README does not document rollback, and it does not describe an upgrade procedure beyond pointing at the Clojars page. That silence matters more than it looks. re-frame is defined by registries that are global by default, so two libraries that both register :app/loading will collide, and the framework gives you no namespace enforcement out of the box. The reactive model also means a view cannot own local ephemeral state in the ordinary React sense; if you want a dropdown's open flag to live and die with the component, you are working against the design rather than with it. The README's own framing rules out a second category of adopter: teams that want views to be causal. If your mental model is colocated queries and component lifecycle hooks, re-frame will feel like it is taking the controls away. And if your stack is JavaScript or TypeScript, the ClojureScript requirement is not a detail you can work around, because the registries, the event vectors and the subscription layer are all Clojure data. The README notes that re-frame has outlasted multiple generations of JavaScript churn, which is a stability argument, not a portability one.
re-frame compared with Reagent alone
The comparison people actually search for is re-frame versus Reagent, and the two are not rivals at the same level. Reagent is the React wrapper: it gives you components as ClojureScript functions and atoms as reactive state. re-frame is built on top of Reagent and adds the layer above it, the event queue, the handler registries and the subscription graph. Choosing Reagent alone means each component decides how it reads and writes state, and the coordination lives in your conventions. Choosing re-frame means state transitions go through registered handlers, and derived values go through registered subscriptions, so the coordination lives in the framework. The cost is ceremony: a single counter needs an event id, a handler, a subscription id and a subscription function. The benefit appears at scale, where a 40K-line application has one place to look when a value is wrong. If your app is a handful of screens with no shared state, Reagent alone is less machinery for the same result. If several parts of the app must agree on the same derived value, the subscription registry is doing work you would otherwise write by hand.
Maintenance status, licence and the upgrade question
The repository is not archived, and the last push was on 2026-05-05, which is recent enough that describing it as actively developed is fair on the evidence given. The release cadence shows three versions in April 2026: v1.4.5 on 2026-04-12, v1.4.6 on 2026-04-29, and v1.4.7 later the same day as v1.4.6. The 1.4.6 release added programmatic diagnostics, documented under Debugging and Instrumentation: source-meta macros, trace tag schema validation, per-dispatch epoch callbacks, dry-run dispatch with effect overrides, and subscription cache lookups. Those are devtools-facing features, which is a reasonable signal about where the project spends effort. On licensing, re-frame is MIT licensed, and the licence text is in license.txt at the repository root. MIT is permissive: it allows commercial use and modification with the copyright notice retained. That is a description of the licence, not legal advice, and the README does not address what happens to applications that depend on it. On upgrade cost, the README is silent about migration between versions, so the honest position is that you should read CHANGELOG.md and the Debugging guide before moving a production app from one 1.4.x release to the next.
Editorial conclusion
Adopt re-frame if your team already writes ClojureScript and wants one event pipeline rather than per-component state. Do not adopt it if you need a plain JavaScript or TypeScript stack, or if you expect the framework to manage server data fetching for you, because the README describes React as the V in MVC and nothing more. Before committing, verify three things in the documentation: whether the function API in re-frame.core or the macro API in re-frame.macros fits your call sites, how the 1.4.6+ programmatic diagnostics behave under your build, and which of the examples/ directories (flow, simple, todomvc) matches the shape of your app. The MIT licence in license.txt is permissive, but the README does not discuss rollback or upgrade procedure, so treat version pinning as your own responsibility.
Frequently asked questions
What is re-frame?
re-frame is a ClojureScript framework for building user interfaces, with a data-oriented, functional design and a focus on single-page applications. It uses React through Reagent, but only as the V in MVC.
Is it re-frame or reframe?
The project writes its name as re-frame, with a hyphen, in the README, the repository name day8/re-frame and the documentation URL. The unhyphenated form is a different word in ordinary English and does not refer to this framework.
How does re-frame compare with Reagent?
Reagent is the React wrapper that re-frame is built on, and re-frame adds the event, handler and subscription registries above it. The README states that re-frame needs React to be the V in MVC and no more, while events are causal and views are purely reactive.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/day8-re-frame)