---
title: "Getting Started with LemonadeJS v6"
description: "Install LemonadeJS step by step: one script tag or npm, one file, open the browser. Dev and production builds, and your first reactive component."
source: https://lemonadejs.com/docs/getting-started/
---

# Getting started with LemonadeJS

Getting started with LemonadeJS is four steps from nothing to a working
reactive component. The first three
need no tooling at all; step four is the npm path for bundled projects.

## 1. Install

Pick one. The script tag is not a demo mode: it is a production path.

**Option A, a script tag.** No package manager, no build:

<!--static-->
```html
<script src="https://cdn.jsdelivr.net/npm/lemonadejs@6/dist/lemonade.min.js"></script>
```

**Option B, npm.** For bundlers and TypeScript projects:

```bash
npm install lemonadejs
```

## 2. Create one file

Save this as `index.html`. It is the entire application: no compiler, no
CLI, no scaffold. The result panel above the code is this exact file
running on this page.

```html
<!doctype html>
<html>
<body>
    <div id="app"></div>
    <script src="https://cdn.jsdelivr.net/npm/lemonadejs@6/dist/lemonade.min.js"></script>
    <script>
    const { html, mount } = lemonade;

    const Counter = (props, { state }) => {
        const count = state(0);
        return html`<div>
            <h1>${count}</h1>
            <button onclick="${() => count.value++}">+1</button>
        </div>`;
    };

    mount(Counter, document.getElementById('app'));
    </script>
</body>
</html>
```

## 3. Open it in a browser

Double-click the file, or serve the folder:

```bash
npx serve .
```

You should see a number and a button, and the number goes up when you
click. That is a reactive state, an event, and a mounted component: the
three primitives you will use every day.

- `state(0)` creates a reactive box; `${count}` in the template is live
  ([State](/docs/state/)).
- `onclick="${() => ...}"`: events are always functions, never strings
  ([Events](/docs/events/)).
- `mount()` returns `{ el, unmount }`; unmounting disposes everything
  ([Lifecycle](/docs/lifecycle/)).

## 4. Or use npm

The same component as a module. TypeScript declarations ship in the
package:

```typescript
import { html, mount, type Component } from 'lemonadejs';

const Counter: Component = (props, { state }) => {
    const count = state(0);
    return html`<div>
        <p>${count}</p>
        <button onclick="${() => count.value++}">+1</button>
    </div>`;
};

mount(Counter, document.getElementById('app'));
```

The package's exports map serves the dev build (warnings on) under the
`development` condition and the stripped production build otherwise.
webpack and Vite set that condition from their mode automatically; with
raw esbuild, pass it yourself in development:

```bash
npx esbuild src/app.ts --bundle --outfile=dist/app.js                 # production
npx esbuild src/app.ts --bundle --conditions=development --watch ...  # development
```

## Dev build vs production

**One file, two builds.** `dist/lemonade.min.js` is the production IIFE
(global `lemonade`, all dev-only code eliminated, so production pays
zero). During development load `dist/lemonade.dev.js` instead: the same
API plus every warning and check (`LJS-*` codes, `explain()`).

<!--static-->
```html
<!-- development: warnings and checks on -->
<script src="https://cdn.jsdelivr.net/npm/lemonadejs@6/dist/lemonade.dev.js"></script>
```

With the dev build loaded, mistakes answer back: mutate without
`touch()` and `LJS-201` tells you; misspell a registered component and
`LJS-104` names it; write `onClick` and `LJS-305` corrects the casing.
Ship the silent, smaller production build.

The complete API fits in one machine-readable file, which states *"if
something is not here, it does not exist."* Paste it into any agent:

<a href="/llms.txt" class="button primary">llms.txt: the API in ~2k tokens</a>

## Where to go next

Read [Templates](/docs/templates/) first: four rules govern every
`${...}`, and everything else follows from them. [State](/docs/state/),
[Events](/docs/events/), [Two-way binding](/docs/two-way-binding/) and
[Components](/docs/components/) are the daily working set;
[Lifecycle](/docs/lifecycle/) and [Destroy](/docs/destroy/) cover how
things mount and, provably, die. When a component becomes a product,
[Contracts](/docs/contracts/) is the publishing layer,
[Tests](/docs/tests/) is the proof, and [React](/docs/react/) and
[Web components](/docs/web-components/) are the doors it ships through.