Quoting, But for Modules

In LISP, the boundary between code and data is deliberately thin. Prefix an expression with a quote, and the evaluator hands you back the raw syntax instead of a computed value:

(+ 2 2)

That returns 4.

Add a quote, and the same form no longer executes:

'(+ 2 2)

What you get instead is the unevaluated list, (+ 2 2), which is itself a valid piece of LISP code. Quoting is just a first-class way of saying "don't run this—give me the code so I can do something with it later." You can always round-trip it back through the evaluator:

(eval '(+ 2 2))

And it evaluates to 4 again.

Servers Generate Programs

Web development is a similar exercise, just with more moving parts. A web server's job is to produce another program—an HTML and JavaScript client—and ship it across the network. Generating and transmitting code for later execution is conceptually close to quoting.

JavaScript has no such primitive. You cannot put a quote in front of a function body and treat it purely as inert data. Wrapping code in a string literal technically treats it as a value, but you lose syntax highlighting, static analysis, and any real ergonomics. Nobody wants to write application logic inside string literals.

What if you could quote an entire module instead?

React's Module-Level Quote

React Server Components (RSC) applies this idea to a practical problem: referencing client code from server code without accidentally executing it. The 'use client' directive lets a server module import a client module as a passive reference, not a live function:

'use client'
 
export function onClick() {
  alert('Hi.');
}

This mirrors LISP quoting in spirit—marking a piece of code as data rather than something to run locally—but with a key difference. In RSC, the resulting reference is opaque. You cannot introspect, transform, or manipulate the underlying code.

When server code imports onClick from a client module, it does not receive a callable function. It receives a serialized reference such as '/js/chunk123.js#onClick', an identifier that describes how to load the actual implementation. Unlike LISP, this transformation is baked into the build pipeline—the bundler handles the quoting at compile time.

That reference eventually lands on the client as a <script>, where the real onClick function is instantiated and can be dispatched as an event handler.

Composition Across Execution Environments

What this enables is a modular system for stitching together behaviors that run in different places. Server components wrap and orchestrate client components—and the composition can nest in both directions, so long as composition happens from the server context. Code outside the "quote" deals with server-only concerns like database access, while code inside the "quote" carries interactive state and runs in the browser.

Because all orchestration originates on the server, the server-only code executes within a single request/response roundtrip, and the resulting client tree is progressively streamed. This is considerably less powerful than full quoting—React dictates the evaluation stages, and there is no metaprogramming layer for transforming the code itself.

LISP has a longer tradition of composing code across contexts, including newer ideas like Electric. Mapping those prior approaches onto JavaScript's constraints would be valuable, but RSC already demonstrates that the core principle transfers: treat code as data at module boundaries, and let the compiler manage the handoff.