English · 00:33:33
Jan 21, 2026 8:13 AM

A ClojureScript Survival Kit - Nolen

SUMMARY

David Nolen, ClojureScript's lead developer, delivers a talk on surviving modern web development chaos using ClojureScript's simplicity, Google Closure Library, web components, and backend-centric strategies for efficient, lightweight apps.

STATEMENTS

  • ClojureScript enables REPL-driven development with access to JavaScript APIs, allowing inspection of docstrings and argument lists directly in the REPL.
  • ClojureScript is a dialect of Clojure targeting JavaScript runtimes, providing access to Clojure core via CLJS core with minor host and compilation differences.
  • Since 2017, ClojureScript has achieved high fidelity, capable of compiling itself into JavaScript, making it feel like authentic Clojure.
  • ClojureScript integrates with the Google Closure Library, enabling advanced optimizations like dead code elimination for smaller bundles.
  • The Clojure community was an early adopter of React for functional UI programming, transitioning quickly despite initial industry skepticism.
  • Modern JavaScript tooling, including npm and Vite, introduces overwhelming complexity and security issues like supply chain attacks, antithetical to Clojure's simplicity.
  • In a hypothetical software apocalypse without npm or libraries, developers can rely on evergreen browsers, improved CSS features like flexbox and grid, and ClojureScript's core tools.
  • Google Closure Library offers utilities beyond basic DOM manipulation, such as efficient style setting, positioning APIs for popups, and date math with guaranteed optimizations.
  • LLMs surprisingly know about Google Closure Library details, and its source code is approachable with extensive comments, remaining future-proof due to minimal changes.
  • Functional UI programming remains key, but ideas like DOM morphing from HTMX, Rails Turbo, and Phoenix LiveView allow backend-driven SPAs with minimal client-side JavaScript.
  • Pure ClojureScript alternatives like Replicant and Shadow Grove provide React-style reactivity without JavaScript ecosystem baggage, resulting in smaller bundles.
  • Morphing libraries like Morf can achieve React-like diffing with just a few kilobytes via script tags, combined with old libraries like Crate for Hiccup-to-DOM conversion.
  • Web components using light DOM enable reusable custom HTML tags since 2016, compatible with various approaches like React or direct DOM manipulation.
  • At Lightweight Labs, shifting complex logic to the backend with full-page morphing and web components drastically reduces JavaScript execution, memory, and bundle sizes.
  • ClojureScript-centric solutions lead to simpler tooling, fewer dependencies, and smaller bundles, while adapting freely from other communities' ideas.
  • The talk encourages exploring backend-centric web apps combining Clojure's power with modern web technologies, potentially inspiring innovative approaches.

IDEAS

  • REPL integration now extends to JavaScript globals and APIs, allowing disciplined access without prefixes, enhancing ClojureScript's interactivity.
  • ClojureScript's self-compilation milestone in 2017 underscores its maturity, bridging Lisp-like programming with JavaScript's reach without sacrificing core principles.
  • Dead code elimination in Google Closure Compiler turns massive libraries into tiny outputs, like reducing a hello world from megabytes to bytes.
  • Early Clojure adoption of React highlighted functional UI potential, but evolving JS ecosystems now demand alternatives to avoid complexity traps.
  • Imagining a "software zombie apocalypse" reveals reliance on evergreen tech like modern CSS for layouts, reducing JavaScript's burden.
  • Google Closure Library's positioning API solves common UI pains like tooltips without custom code, predating and outperforming native browser features.
  • LLMs' familiarity with obscure libraries like GCL suggests AI can revive forgotten tools, making them accessible for modern projects.
  • Backend-driven DOM morphing builds SPAs with server-side Clojure, using tiny script tags for reconciliation, skeptical of frontend-heavy paradigms.
  • Replicant achieves React-like functionality in 30k compressed, outperforming Vite+React setups, proving pure ClojureScript viability.
  • A 13-year-old Hiccup library Crate still works flawlessly, combined with new morphers, showing web backwards compatibility's power.
  • Web components' light DOM avoids shadow DOM complexity, enabling truly reusable elements across frameworks without feudalism.
  • Virtualizing tables backend-side with Datomic loads rows on-demand during scrolls, morphing full pages for buttery performance.
  • ClojureScript's new "light mode" strips persistent data needs for tactical glue, yielding 10k bundles for web component orchestration.
  • Framework "feudalism" traps components in silos, but custom HTML tags democratize reuse, solving reinvention cycles.
  • Performance graphs reveal React apps' JS dominance (40x painting time), collapsed to negligible in morphing approaches.
  • Community leaders like Thomas Heller explore pure ClojureScript reactivity, inspiring shifts from JS dependency.

INSIGHTS

  • Embracing ClojureScript's simplicity counters web dev's exponential complexity, prioritizing backwards-compatible tools over fleeting trends.
  • Google Closure Library's underappreciated depth offers ergonomic, optimized solutions for common problems, future-proofed by design.
  • Shifting UI logic backend-ward via morphing simplifies client code, leveraging Clojure's strengths for state management without VDOM overhead.
  • Web components foster true interoperability, breaking framework silos and enabling reusable UI primitives across ecosystems.
  • Modern browsers' advancements in CSS and APIs allow leaning on native capabilities first, minimizing custom JavaScript inventions.
  • Pure ClojureScript reactivity alternatives like Replicant demonstrate smaller, more maintainable apps without JS tooling's baggage.
  • Dom morphing with tiny libraries achieves SPA feel with backend control, ideal for Clojure's full-stack harmony.
  • REPL-driven exploration of JS APIs blurs host boundaries, empowering developers with Clojure's introspection in web contexts.
  • Community control of GCL revival could standardize it, reducing dependency on external libs for vast UI and utility needs.
  • Tactical web components handle interactivity precisely, avoiding overkill frameworks for most use cases.
  • Performance gains from backend virtualization highlight how frontend-heavy apps waste resources on unnecessary computation.
  • Adapting ideas like HTMX to ClojureScript unlocks efficient, production-ready web apps with minimal client footprint.

QUOTES

  • "I don't have to leave my REPL. Um I can like check the doc string or the arg list for some function. Like that's really really really nice."
  • "ClojureScript generates code that's designed to work with the Google Closure um compiler and has advanced optimizations. And the big optimization there is dead code elimination."
  • "We were like it was almost overnight that closure the collage community transitioned to it because it was the only sort of like easy to integrate solution that allowed people to do functional UI programming."
  • "It's simply not going to change. Um, and now most of the tools, like the big tool now is Vite. and like bytes answer this problem is choose your interventure which 10 frameworks of the day do you want to do."
  • "The browser doesn't have like a pos this positioning API. It doesn't matter where it is in the in the page. Google this li this library lets me position it wherever I want."
  • "These components are not reus or only reusable within the context of where they live. And therefore, of course, it makes sense. They keep getting reinvented over and over again."
  • "UI is a function of state. Um the main thing is that a lot of stuff has happened since React. People understand React and the world has moved forward in other communities and I think we can steal some ideas here."
  • "Just the amount of time we're spending in scripting, it's just collapsed. It was like 40 times the time, 40 times more time is spent in scripting than in painting the screen."
  • "Just use closure script um at the same time I'm not being prescriptive for those of you that have invested in like you know react heavy thing or you're doing react native I mean, if it makes sense and you're succeeding, that's awesome."

HABITS

  • Integrate REPL-driven development to inspect functions, docstrings, and JavaScript APIs interactively during coding sessions.
  • Prioritize checking browser-native features and CSS capabilities before implementing custom JavaScript solutions.
  • Use Google Closure Library utilities for common tasks like DOM manipulation and positioning to avoid reinventing ergonomics.
  • Experiment with backend-centric state management for UIs, morphing DOM from server responses to reduce client complexity.
  • Leverage web components for reusable UI elements, defining custom tags with lifecycle hooks for precise interactivity.
  • Profile performance timelines regularly to identify JavaScript bottlenecks and optimize towards minimal scripting.
  • Draw inspiration from community projects like Replicant, adapting proven ideas without full ecosystem adoption.

FACTS

  • ClojureScript has existed for 14 years, achieving self-compilation into JavaScript since 2017.
  • The Clojure community pioneered React adoption in 2013, enabling functional UI via simple script tags initially.
  • Modern CSS now includes nested rules, flexbox, and grid, incorporating features once requiring preprocessors like SASS.
  • Google Closure Library's positioning API has remained unchanged for over five years, proving its stability.
  • A trivial ClojureScript hello world without optimizations would generate three megabytes of JavaScript; with them, it's mere bytes.
  • Replicant-based React-style apps compress to 30k, smaller than Vite+React's 60k plus additional ClojureScript overhead.
  • At Lightweight Labs, backend morphing reduced memory from 3.2-9.8 MB to under 10 MB and scripting time by 40x.

REFERENCES

  • Google Maps (2004 AJAX example).
  • Simple Made Easy (talk by Rich Hickey).
  • Clojure core functions and purely functional data structures.
  • JavaScript APIs like array/indexOf and globals like Date, console.log.
  • Google Closure Library (GCL), including goog.dom, goog.style, goog.positioning, goog.date, accessibility tools, text selection, animation, XSS sanitization.
  • Rich Hickey's ClojureScript presentation at Relevance in New York.
  • React (early script tag integration).
  • Node ecosystem and npm.
  • Shadow-cljs (tool for easier JS integration).
  • Vite (modern bundler with framework choices).
  • Evergreen browsers (post-2013 standards, excluding Safari quirks).
  • Baseline and CanIUse (browser feature compatibility resources).
  • HTMX, Rails Turbo, Phoenix LiveView, Datastar (DOM morphing approaches).
  • Replicant (pure ClojureScript reactivity library).
  • Shadow Grove (Thomas Heller's project).
  • Crate (13-year-old Hiccup-to-DOM library by Chris Granger).
  • Morf (week-old morphing library from Ruby community).
  • Web Components (custom elements since 2016, light DOM).
  • Rum (React wrapper for ClojureScript).
  • Ag-grid (virtualized table component).
  • Datomic (backend database for row loading).
  • Lightweight Labs (workplace, general ledger demo).
  • Anders Murphy's "A Billion Checkboxes" blog post and Hacker News articles.
  • David Yan's talk "A Tale of Two Architectures".

HOW TO APPLY

  • Start by setting up a basic ClojureScript REPL environment to inspect JavaScript globals and APIs, declaring dependencies for tools like Date or console.log without JS prefixes.
  • Inventory available tools: Include ClojureScript core, adjacent libraries for data and testing, and Google Closure Library for DOM access, styling, and positioning to handle UI basics.
  • Assess browser surroundings: Use resources like CanIUse to verify native CSS features like flexbox or grid for layouts, avoiding JavaScript for alignment or nesting.
  • Implement DOM morphing: Load a tiny library like Morf via script tag, combine with Hiccup-to-DOM like Crate, and reconcile server-sent HTML with existing DOM on interactions.
  • Define web components: Create custom elements with lifecycle methods (connectedCallback, disconnectedCallback) for reusability, using light DOM for compatibility with morphing or mutation.
  • Shift logic backend: Render UI as functions of state on the server with Clojure, send full or partial HTML, and morph client-side; virtualize data loads on-demand for large views like tables.
  • Profile and optimize: Record browser timelines during scrolls or interactions, target reducing JavaScript execution below painting time, and enable advanced compilation for dead code elimination.

ONE-SENTENCE TAKEAWAY

Embrace ClojureScript's simplicity and Google Closure tools to build efficient web apps, sidestepping JavaScript ecosystem complexity.

RECOMMENDATIONS

  • Revive and document Google Closure Library on clojurescript.org with examples and updated docs to highlight its UI components and utilities.
  • Experiment with pure ClojureScript reactivity like Replicant for new projects, comparing bundle sizes against React setups.
  • Adopt backend-driven morphing for SPAs, using Clojure for state and tiny script tags for DOM reconciliation to minimize client JavaScript.
  • Prioritize web components for interactive elements like tooltips, leveraging GCL's positioning for robust, framework-agnostic reusability.
  • Profile apps early to shift non-essential logic backend-ward, aiming for scripting times under painting for smoother performance.
  • Explore community inspirations like Anders Murphy's virtualization demos to implement efficient tables without frontend bloat.
  • Integrate REPL access to JS APIs in workflows, declaring globals for better introspection and reducing prefix verbosity.
  • Consider light mode in ClojureScript for tactical client glue, stripping unneeded features to achieve sub-10k bundles.
  • Freely adapt morphing ideas from HTMX or Phoenix LiveView, tailoring to Clojure's full-stack strengths for production apps.

MEMO

David Nolen, the lead developer of ClojureScript, took the stage at Clojure/Conj 2025 in Charlotte, North Carolina, to unveil a "ClojureScript Survival Kit" amid the escalating chaos of modern web development. Drawing parallels to the 2004 AJAX revolution sparked by Google Maps, when JavaScript was a weekend's study, Nolen lamented how today's ecosystem—fraught with npm supply chain attacks, Vite's framework roulette, and gigabyte node_modules—defies a single lifetime's mastery. Yet, he argued, the web's backwards compatibility, much like Clojure's ethos, offers refuge: simpler, smaller, faster tools suffice without chasing the latest fads. For beginners and veterans alike, ClojureScript provides a lifeline, compiling Lisp-like elegance to JavaScript while wielding advanced optimizations from the Google Closure Compiler.

At its core, ClojureScript is a dialect targeting JavaScript runtimes, granting access to Clojure's rich standard library via CLJS core. Nolen highlighted its maturity—self-compiling since 2017—and REPL-driven perks, now extending to JavaScript APIs for docstring peeks and global references without clunky prefixes. Bundled with the oft-overlooked Google Closure Library (GCL), it enables dead code elimination, shrinking libraries to essentials: a thousand functions become one if unused. Nolen demoed GCL's DOM ergonomics—multi-attribute styling sans string hacks—and a positioning API for popups and tooltips, stable for over a decade and outperforming browser natives. These tools, he noted, address gaps the web left unfilled, from accessibility to XSS sanitization, all primed for advanced compilation's efficiency.

The Clojure community, early React pioneers for functional UIs, has endured JavaScript's sprawl but at a cost. Shadow-cljs eased integration, yet complexity lurks: half-gig bundles from "choose your framework" prompts. Envisioning a "software zombie apocalypse" sans npm, Nolen urged taking stock of evergreen assets—modern CSS with nesting and grid, flexbox for alignments once table-bound. Browsers, post-2013, handle optimizations like viewport intersections natively, nudging developers to query CanIUse first. GCL emerges as a goldmine: date math in 2-3K versus bloated alternatives, UI components like Google Docs' editor, all future-proof and LLM-documented.

Pushing functional UI—"UI as a function of state"—Nolen stole from elsewhere: backend-centric morphing à la HTMX or Phoenix LiveView, diffing DOM without VDOM. Demos paired 13-year-old Crate (Hiccup to DOM) with week-old Morf (2-3K morpher) via script tags, yielding React-like reactivity sans framework feudalism. Pure ClojureScript gems like Replicant (30K compressed) and Shadow Grove outpace Vite+React, proving viability. Web components, since 2016's light DOM, birth custom tags with lifecycles, reusable across paradigms—mutate with GCL or morph seamlessly.

At Lightweight Labs, Nolen's team applied this: backend Clojure renders, full-page morphs virtualize tables via Datomic, web components handle hovers and panels. Results stunned—memory plunged 10-20x (3MB to under 10MB), scripting collapsed 40x below painting, bundles to 10K "light mode" glue. No roadblocks emerged; typical React pains like floating elements yielded to one GCL-powered component. This ClojureScript-centric pivot simplifies tooling, dependencies, and semantics, borrowing freely while adapting: jQuery for blogs, React where invested, or post-HTMX innovation.

Nolen's non-prescriptive vision excites: Clojure's backend power plus frontend precision could dazzle, inspiring backend SPAs with modern web flair. Q&A touched GitHub examples (nod to Anders Murphy's billion-checkboxes), Datastar tweaks for abstraction, and snapshot testing compatibility. As applause faded, the message lingered—reclaim control, wield the kit, and thrive in web dev's ruins.

Like this? Create a free account to export to PDF and ePub, and send to Kindle.

Create a free account