# How to Use LINEJS in Browser Environments: Complete Setup Guide

> Yes LINEJS fully supports browser environments. Learn how to set up LINEJS in your browser using our complete guide and CDN for easy integration.

- Repository: [Evex  Developers/linejs](https://github.com/evex-dev/linejs)
- Tags: how-to-guide
- Published: 2026-03-01

---

**LINEJS fully supports browser environments by loading the library from a CDN and providing browser-compatible `fetch` and storage implementations.**

LINEJS is a JavaScript client library for the LINE messaging platform maintained in the `evex-dev/linejs` repository. Unlike many Node.js-specific libraries, LINEJS is designed to run on all JavaScript runtimes, including modern web browsers, without requiring a build step or bundler.

## Browser Support and CDN Import

The project documentation in [`README.md`](https://github.com/evex-dev/linejs/blob/main/README.md) explicitly states that browser usage is supported by loading the library from [`esm.sh`](https://github.com/evex-dev/linejs/blob/main/esm.sh). Because LINEJS ships as standard ECMAScript modules, you can import it directly via a CDN without npm install or webpack configuration.

### Importing from esm.sh

Load the library using a standard module script tag. This imports the `Client` class exposed in [`packages/linejs/client/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/mod.ts) directly into the browser scope:

```html
<script type="module">
  import * as LINEJS from "https://esm.sh/jsr/@evex/linejs";
</script>

```

## Required Browser APIs and Shims

Browsers lack Node.js-specific globals, so you must provide two critical dependencies before instantiating the client.

### Fetch Implementation

The HTTP client core requires a `fetch` implementation. Bind the browser's native `window.fetch` to the client instance after construction:

```javascript
client.fetch = window.fetch.bind(window);

```

### Storage Implementation

LINEJS requires a storage backend for authentication tokens and session data. The abstract interface defined in [`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts) expects `get`, `set`, `delete`, and `clear` methods. The official example in [`example/browser/browser-init.js`](https://github.com/evex-dev/linejs/blob/main/example/browser/browser-init.js) implements a lightweight `LocalStorage` wrapper:

```javascript
class BrowserStorage {
  #prefix = "linejs:";
  set(key, value) { localStorage.setItem(this.#prefix + key, JSON.stringify(value)); }
  get(key) {
    try { return JSON.parse(localStorage.getItem(this.#prefix + key) ?? "null"); }
    catch { return undefined; }
  }
  delete(key) { localStorage.removeItem(this.#prefix + key); }
  clear() { localStorage.clear(); }
}

```

## Complete Browser Implementation Example

Below is a self-contained HTML file demonstrating the full setup, including authentication handling and QR code display. This mirrors the reference implementation in [`example/browser/browser-init.js`](https://github.com/evex-dev/linejs/blob/main/example/browser/browser-init.js):

```html
<!DOCTYPE html>
<html>
<head>
  <title>LINEJS in the Browser</title>
</head>
<body></body>
<script type="module">
  // 1️⃣ Load LINEJS from the CDN (the version shown is the current release)
  import * as LINEJS from "https://esm.sh/jsr/@evex/linejs";

  // 2️⃣ Simple wrapper around the browser's localStorage
  class BrowserStorage {
    #prefix = "linejs:";
    set(key, value)   { localStorage.setItem(this.#prefix + key, JSON.stringify(value)); }
    get(key) {
      try { return JSON.parse(localStorage.getItem(this.#prefix + key) ?? "null"); }
      catch { return undefined; }
    }
    delete(key)       { localStorage.removeItem(this.#prefix + key); }
    clear()           { localStorage.clear(); }
  }

  // 3️⃣ Helper for UI logging
  const log = (msg) => {
    const p = document.createElement("p");
    p.textContent = msg;
    document.body.appendChild(p);
  };

  // 4️⃣ Initialise the LINEJS client
  const client = new LINEJS.Client({
    device: "IOSIPAD",          // or any device string you prefer
    storage: new BrowserStorage(),
    endpoint: location.hostname, // optional – overrides default API endpoint
  });

  // Provide the browser's fetch implementation
  client.fetch = window.fetch.bind(window);

  // 5️⃣ Wire up useful events
  client.on("log",      (msg) => console.log("[log]", msg));
  client.on("qrcall",   (url) => {
    const img = document.createElement("img");
    img.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(url)}`;
    document.body.appendChild(img);
  });
  client.on("pincall", (pin) => log(`Enter PIN: ${pin}`));
  client.on("ready",   (user) => log(`Logged in as ${user.displayName} (${user.mid})`));

  // 6️⃣ Authenticate – use a stored token if available, otherwise fall back to credentials
  const savedToken = localStorage.getItem("lastAuthToken") || "";
  if (savedToken) {
    client.login({ authToken: savedToken });
  } else {
    const email = prompt("Email:", "");
    const pw    = prompt("Password:", "");
    client.login({ email, password: pw });
  }

  // Expose for debugging
  window.LINEJS = LINEJS;
  window.client = client;
</script>
</html>

```

## Authentication Flow Events in Browsers

The browser environment requires UI-based authentication flows. The `Client` class emits specific events that you must handle to complete login, as implemented in the core client code:

- **`qrcall`** – Emitted when QR code authentication is required; provides a URL to render as a QR image
- **`pincall`** – Emitted when a PIN code is required for secondary verification  
- **`ready`** – Emitted when authentication succeeds, passing the user object containing `displayName` and `mid`

These events function identically across runtimes, but in browsers you typically render the QR code to an `<img>` element or display the PIN in a modal.

## Key Source Files for Browser Support

The following files define the architecture that enables LINEJS to run natively in browsers:

- **[`packages/linejs/client/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/mod.ts)** – Exports the `Client` class constructor used in both browser and Node.js environments
- **[`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts)** – Defines the abstract storage interface that browser-specific implementations must satisfy
- **[`packages/linejs/base/push/conn.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/push/conn.ts)** – Manages long-polling connections; functions in browsers once `fetch` is supplied
- **[`example/browser/browser-init.js`](https://github.com/evex-dev/linejs/blob/main/example/browser/browser-init.js)** – Official reference implementation demonstrating production-ready browser setup with event handling

## Summary

- **LINEJS runs natively in browsers** by importing from `https://esm.sh/jsr/@evex/linejs` without build tools
- **Bind `window.fetch`** to `client.fetch` immediately after instantiation to enable HTTP requests
- **Implement the storage interface** from [`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts) using `localStorage` or IndexedDB for persistence
- **Handle authentication events** (`qrcall`, `pincall`, `ready`) to manage QR codes and PIN entry in the UI
- **Core API compatibility** means `client.login()`, message sending, and other features work identically to Node.js once the environment shims are provided

## Frequently Asked Questions

### Does LINEJS require a bundler like Webpack or Vite to work in browsers?

No. LINEJS ships as standard ECMAScript modules that you can import directly via CDN using `<script type="module">` tags. The [`esm.sh`](https://github.com/evex-dev/linejs/blob/main/esm.sh) CDN handles all transpilation and dependency resolution automatically, as documented in the repository's [`README.md`](https://github.com/evex-dev/linejs/blob/main/README.md).

### Can I use LINEJS with React or Vue.js in the browser?

Yes. After importing LINEJS from the CDN or your bundler, instantiate the `Client` class inside your framework's initialization logic (such as a React `useEffect` hook or Vue `onMounted` lifecycle). Pass a storage implementation compatible with your state management strategy, and bind `window.fetch` before calling `client.login()`.

### Where are authentication tokens stored when using LINEJS in a browser?

The library does not store tokens automatically in browsers. You must provide a storage implementation such as the `BrowserStorage` class shown in [`example/browser/browser-init.js`](https://github.com/evex-dev/linejs/blob/main/example/browser/browser-init.js), which wraps `localStorage` to persist tokens between sessions. You can also use IndexedDB for larger storage quotas.

### Is the long-polling connection stable in browser environments?

Yes. The connection logic in [`packages/linejs/base/push/conn.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/push/conn.ts) uses standard HTTP requests through the `fetch` API you provide. As long as `client.fetch` is bound to `window.fetch`, the long-polling mechanism works identically to Node.js environments, maintaining the persistent connection required for real-time message reception.