When NOT to use LemonadeJS
These are the situations where another tool is a better fit. Each is a consequence of deliberate design choices; the relevant chapter is usually one link away.
You need server-side rendering
LemonadeJS v6 renders in the browser. There is no SSR, no streaming HTML, no hydration story. If server-rendered first paint matters, as on content sites where SEO and time-to-first-byte are the business, Next.js, Nuxt, Astro, or SvelteKit address that; LemonadeJS does not. (This site is static Astro with LemonadeJS for interactive islands, and that combination works well; LemonadeJS as the SSR layer does not exist.)
You target something other than the DOM
LemonadeJS renders to the browser DOM only. Other runtime targets (native mobile, canvas, terminal, PDF) are not available. If your product needs one component model across web and native, this is not the right tool.
You depend on ecosystem depth
React’s ecosystem spans hundreds of thousands of packages. LemonadeJS ships 43 first-party blocks and an engine. The contract system makes those blocks unusually verifiable, but if your team’s velocity comes from assembling third-party packages, the ecosystem gap is real and will not close soon.
The same applies to hiring: React familiarity is a widely recognised signal; LemonadeJS is not. A team that staffs against the market should account for this.
You want compile-time optimization
LemonadeJS has no compiler by design; zero build step is the feature. That means it cannot do what Svelte or Solid’s compilers do: analyze your templates ahead of time, eliminate dead branches, or generate the theoretically minimal update code. The runtime is small and updates are fine-grained, but a compiled framework will always have optimizations a runtime-only one structurally cannot. If you are at the scale where that difference is measurable in your product, measure it.
You need portals today
Floating UI (modals, dropdowns, tooltips) renders in place with
position: fixed. Inside an ancestor with transform, filter or
perspective, fixed positioning resolves against that ancestor and the
panel will appear in the wrong place, a CSS platform rule, not a bug, but
React’s createPortal escapes it and LemonadeJS currently does not. A
portal design exists and was deliberately deferred until real-world demand
proves it earns its bytes. If your components must live inside transformed
containers (animation libraries, certain design systems), this is a present
limitation.
You expect framework-managed accessibility
The blocks carry roles, keyboard activation and ARIA where the behavior is unambiguous (dialog semantics and focus trapping in Modal, roving tabindex in tabs, slider semantics in rating, grid semantics in datagrid), but v6 has not had a comprehensive WCAG audit and remediation pass. Libraries like React Aria or Radix exist specifically to own this problem and are years ahead. If WCAG conformance is a launch requirement, audit the blocks you need before committing; the known gaps are tracked in the repository, not hidden.
Costs that come with the design (even when it fits)
These are not missing features; they are the other side of decisions this book defends elsewhere:
- Mutation requires
touch(). State contents are mutable and mutation is silent until you notify. This is the model that makes a one-cell change in a million-row array O(1), and it is also a discipline, with a dev warning (LJS-201) instead of a compiler guarantee behind it. - Keys are scoped per list. An item moving between two lists rebuilds on the other side, the same scoping React and Vue have, stated here so you do not discover it in a kanban board.
- Styles are global by design.
<style>hoisting has no scoping engine; thelm-*prefix convention is the isolation mechanism. Teams wanting enforced style isolation will miss CSS modules or shadow DOM. resource()is a fetch lifecycle, not a data layer. No cache, no deduplication, no retries; React Query and SWR solve a deliberately larger problem. Compose withstore()or bring a data library.- The dev/prod split is per build artifact. Warnings,
trace()andexplain()live in the dev build only. You choose the artifact; there is no runtime flag.
So when is it right?
When the authors of your frontend, human or agent, benefit from a system
small enough to hold entirely in context, components published with
machine-readable contracts, and a verify() step that turns “looks right”
into a pass/fail report. That case is the rest of this book, starting with
why v6 exists.