How to Use LINEJS in Browser Environments: Complete Setup Guide

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 explicitly states that browser usage is supported by loading the library from 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 directly into the browser scope:

<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:

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 expects get, set, delete, and clear methods. The official example in example/browser/browser-init.js implements a lightweight LocalStorage wrapper:

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:

<!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:

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 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 CDN handles all transpilation and dependency resolution automatically, as documented in the repository's 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, 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →