# Welcome

Welcome to the Lightning Web Standard (**WebLN**). This guide covers how to build a Bitcoin Lightning-driven web application using the WebLN standard.

Bitcoin is a global payment protocol that anyone with Internet access can participate in and contribute to. Hence, Bitcoin Lightning’s use cases are as vast as its user base. However, building them does not need to be complicated. We designed this guide to help anyone get started quickly. We can’t imagine every possible use case, but we can help you to build for them.

You may be interested in reading this guide if you want to build or operate a web application

* that accepts or makes Bitcoin Lightning payments
* that have decentralized identity and authentication

All you need is to interact with a client application such as a browser extension that understands WebLN. It does so by providing a JavaScript API called `window.webln` on every web page you visit. To have a look at what this object looks like, have a look at the [WebLN Reference](/building-lightning-apps/webln-reference) or just type `window.webln` in the Chrome or Firefox DevTools console.

WebLN is a JavaScript interface to the Bitcoin Lightning Network. There are functions to:

* Get information about a user's Bitcoin Lightning node ([`webln.getInfo`](/building-lightning-apps/webln-reference))
* Send a payment ([`webln.sendPayment`](/building-lightning-apps/webln-reference))
* Request an invoice to receive a payment ([`webln.makeInvoice`](/building-lightning-apps/webln-reference))
* Request a signature of an arbitrary message ([`webln.signMessage`](/building-lightning-apps/webln-reference))
* …and [some more](/building-lightning-apps/webln-reference)

When a WebLN provider is installed, any front-end code can get access to all these functions, and interact with the Bitcoin Lightning network. These web applications are called *LApps* (Lightning Apps).


# What is WebLN

### Introduction

WebLN is a set of specifications for Lightning apps and client providers to facilitate communication between web apps and users' Lightning nodes in a secure way. It provides a programmatic, permissioned interface for letting applications ask users to send payments, generate invoices to receive payments, and much more.

![WebLN  Provider functionality](/files/jSeEa4SdaEz8PucTqCAr)

### State of WebLN

WebLN builds on the idea of [web3.js](https://www.npmjs.com/package/web3), a collection of libraries that allow you to interact with a local or remote ethereum node using HTTP, IPC or WebSocket. The WebLN specifications were published in 2018 and since then have continuously improved. In the meantime several Lightning applications and client providers have been built using this standard.


# Benefits of WebLN

WebLN comes with a couple of benefits:

* **Better UX**\
  WebLN allows for programmatic interactions and reduces friction between a Lapp and the user’s wallet. Users don't have to switch context for scanning a QR code to make a payment anymore. Additionally, they can sign a message with one click to prove ownership of a wallet. If a WebLN client supports auto-payments, no prompt is needed and the user is just one click away from sending a payment.
* **Ready and secure**\
  WebLN is a specification that only describes how to interact with a Bitcoin Lightning wallet. There is no need to trust and integrate a third-party library. Over the years WebLN has developed and has been recognized as a standard within the community.
* **Simple implementation**\
  Initialization and execution of WebLN requires not more than some lines of code of JavaScript - a language that is commonly used for creating web apps.
* **Complementary to LNURL**\
  WebLN works well together with [LNURL](https://github.com/fiatjaf/lnurl-rfc), another, more manual standard to make interactions with Lighting easier. If [implemented correctly](/building-lightning-apps/best-practices) WebLN provides a great enhancement of the UX. For users without a WebLN provider installed, LNURL can serve as a fall-back option.


# 👨💻 Getting Started

### Installation

Browsers with WebLN capabilities provide APIs using a global JavaScript variable `window.webln` that can be used to interact with the connected Bitcoin Lightning wallet.&#x20;

{% content-ref url="/pages/PyPNrgZehYH8gbxnJo6v" %}
[WebLN Providers](/ressources/webln-providers)
{% endcontent-ref %}

**You don't need to add any library to your project.**

### Detecting WebLN support

Before you start using WebLN you need to check for browser support by checking if the variable `window.webln` is defined:

```javascript
if (typeof window.webln !== 'undefined') {
  console.log('WebLN is available!');
}
```

{% hint style="warning" %}
`window.webln` might not be available during pageload. See the code example below for proper detection.
{% endhint %}

<details>

<summary>Detect if a WebLN provider is available</summary>

```javascript
async function detectWebLNProvider(timeoutParam) {
  const timeout = timeoutParam ?? 3000;
  const interval = 100;
  let handled = false;

  return new Promise((resolve) => {
    if (window.webln) {
      handleWebLN();
    } else {
      document.addEventListener("webln:ready", handleWebLN, { once: true });
      
      let i = 0;
      const checkInterval = setInterval(function() {
        if (window.webln || i >= timeout/interval) {
          handleWebLN();
          clearInterval(checkInterval);
        }
        i++;
      }, interval);
    }

    function handleWebLN() {
      if (handled) {
        return;
      }
      handled = true;

      document.removeEventListener("webln:ready", handleWebLN);

      if (window.webln) {
        resolve(window.webln);
      } else {
        resolve(null);
      }
    }
  });
}
```

</details>

### Enable WebLN <a href="#connecting-to-metamask" id="connecting-to-metamask"></a>

Before you can work with any of the WebLN APIs you need call the method `enable()` :

```typescript
await window.webln.enable();
```

Depending on the used WebLN provider this will ask the user to connect their Lightning wallet with the website.&#x20;

![The WebLN provider will ask the user for permission to connect with your website.](/files/a0CWBSysFNnyKNcFAFX0)

{% hint style="info" %}
You should only initiate a request in response to direct user action, such as clicking a button.
{% endhint %}

### Using WebLN

Now you are ready to work with the WebLN APIs.&#x20;

```javascript
await window.webln.enable();
await window.webln.sendPayment();
```

Have a look at the the [WebLN Reference](/building-lightning-apps/webln-reference) for detailed explanations and usage examples for the different APIs.

### WebLN Events

WebLN triggers events like `webln:enabled` upon enabling, allowing apps and packages to subscribe and listen to these events.

```javascript
window.addEventListener("webln:enabled", () => {
    console.log("WebLN is enabled!");
});
```

### Error handling

There are different errors that can happen while using the WebLN APIs. Make sure to handle them and let the user know what went wrong.

{% content-ref url="/pages/IcCnXHwSFAbpmNupGqXp" %}
[Error handling](/building-lightning-apps/webln-reference/error-handling)
{% endcontent-ref %}


# WebLN Reference

Explore the different APIs WebLN offers.

Using WebLN API is straightforward. WebLN offers a comprehensive set of APIs designed for building Bitcoin Lightning-driven web applications using the WebLN standard and requires just a few lines of code.

Get started with the WebLN API!

{% content-ref url="/pages/OjZMZsfy2oppQFYjijLb" %}
[webln.enable()](/building-lightning-apps/webln-reference/webln.enable)
{% endcontent-ref %}


# webln.isEnabled()

`webln.isEnabled()` allows you to check if webln is enabled without explicitly enabling it through `webln.enable()` (which may cause a confirmation popup in some providers)

{% hint style="warning" %}
This API may not be available on all [providers](https://www.webln.guide/ressources/webln-providers).&#x20;
{% endhint %}

#### Method&#x20;

```typescript
function isEnabled(): Promise<boolean>;
```

**Example**

```javascript
if(typeof window.webln !== 'undefined' && window.webln.isEnabled) {
    const isEnabled = await window.webln.isEnabled();
    // do something with the value
    console.log(isEnabled)
  }
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/vYvqZgy>" %}


# webln.enable()

To begin interacting with WebLN APIs you'll first need to enable the provider. Calling `webln.enable()` will prompt the user for permission to use the WebLN capabilities of the browser. After that you are free to call any of the other API methods.&#x20;

#### Method&#x20;

```typescript
async function enable(): void;
```

**Example**

```javascript
  if(typeof window.webln !== 'undefined' && window.webln.isEnabled) {
    const isEnabled = await window.webln.isEnabled();
    // do something with the value
    console.log(isEnabled)
    
  }
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/YzYgYKE>" %}


# webln.getInfo()

Get information about the connected node and what WebLN methods it supports.

#### Method

```typescript
async function getInfo(): GetInfoResponse;
```

#### Response

```typescript
interface GetInfoResponse = {
  node: {
    alias: string;
    pubkey: string;
    color?: string;
  },
  // "request.*" methods are not supported by all connectors
  // (see webln.request for more info)
  methods: string[]; // e.g. "makeInvoice", "sendPayment", "request.openchannel", ...
}
```

#### Code Example

```typescript
await webln.enable();
const info = await webln.getInfo();
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/VwyREdo>" %}


# webln.keysend()

Request the user to send a keysend payment. This is a spontaneous payment that does not require an invoice and only needs a destination public key and and amount.

#### Method

```typescript
async keysend(args: KeysendArgs): SendPaymentResponse;
```

#### Parameters

```typescript
interface KeysendArgs {
  destination: string;
  amount: string | number;
  customRecords?: Record<string, string>;
}
```

* `destination`\
  Hex encoded public key of the destination node. This is a string of length 66 that starts either with `02` or `03`.
* `amount`\
  The amount of satoshis you want to send as a stringified integer.
* `customRecords`\
  A `map<string, string>` of records that are appended to the payment. The key should be a stringified integer from the [TLV Registry](https://github.com/satoshisstream/satoshis.stream/blob/main/TLV_registry.md). The value should be an *unencoded*, plain string. \
  \
  The WebLN provider should handle the encoding if necessary. If no custom records are needed, this parameter can be omitted.

#### Response

```typescript
interface SendPaymentResponse {
  preimage: string;
}
```

* `preimage`\
  Note that the `preimage` is not a proof of payment, because unlike a bolt11 payment it is generated by the sender, not by the recipient.

### Code Examples

#### Sending a message

```typescript
await webln.enable();
const result = await webln.keysend({
    destination: "03006fcf3312dae8d068ea297f58e2bd00ec1ffe214b793eda46966b6294a53ce6", 
    amount: "1", 
    customRecords: {
        "34349334": "HELLO AMBOSS"
    }
});
```

{% embed url="<https://codepen.io/getalby/pen/jOYJYzP>" %}

#### 🎧 Podcasting 2.0: Send a boostagram

Manual payments to a podcast or episode and attach your own message.

{% embed url="<https://codepen.io/getalby/pen/PoeezNj>" %}

#### 🎧 Podcasting 2.0: Send a stream payment

Automatic payments while listening to an episode.&#x20;

{% embed url="<https://codepen.io/getalby/pen/QWrrErJ?editors=1011>" %}

### Resources

* [TLV Registry](https://github.com/satoshisstream/satoshis.stream/blob/main/TLV_registry.md)
* [Podcasting 2.0 BLIP](https://github.com/lightning/blips/blob/master/blip-0010.md)
* [Builder's Guide: Sending messages with keysend](https://docs.lightning.engineering/lightning-network-tools/lnd/send-messages-with-keysend)


# webln.makeInvoice()

Request that the user creates an invoice to be used by the web app. This will return a [BOLT-11](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md) invoice. Invoices can be requested in a few forms:

* By specifying an explicit `amount`, the user's provider should enforce that the user generate an invoice with a specific amount
* By specifying a `minimumAmount` and / or `maximumAmount`, the user's provider should enforce that the user generate an invoice with an amount field constrained by that amount
* When an explicit `amount` is *not* set, the user can return an invoice that has no amount specified, allowing the payment maker to send any amount

Note that these constraints are enforced by the client's provider, and therefore should not be completely trusted. If you want to check the fields that come back, or otherwise use the data encoded in the invoice, you'll want to use a library to decode it such as the [bolt11 npm package](https://www.npmjs.com/package/bolt11).

Amounts are denominated in satoshis. For large amounts, it's recommended you use a big number library such as [bn.js](https://www.npmjs.com/package/bn.js) or [big.js](https://www.npmjs.com/package/big.js) as Javascript only supports 32 bit integers.

#### Method

```typescript
async function makeInvoice(args: RequestInvoiceArgs): RequestInvoiceResponse;
```

#### Parameters

```typescript
interface RequestInvoiceArgs {
  amount?: string | number;
  defaultAmount?: string | number;
  minimumAmount?: string | number;
  maximumAmount?: string | number;
  defaultMemo?: string;
}
```

{% hint style="info" %}
All amounts are denominated in sats.
{% endhint %}

#### Response

```typescript
interface RequestInvoiceResponse {
  paymentRequest: string;
}
```

#### Code Example

```typescript
await webln.enable();
const invoice = await webln.makeInvoice({
  amount: 1000,
});
```

#### Demo

{% embed url="<https://codepen.io/getalby/embed/mdpozoV?default-tab=js%2Cresult&theme-id=light>" %}


# webln.sendPayment()

Request that the user sends a payment for an invoice. The application needs to provide a [BOLT-11](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md) invoice. For an invoiceless payment, use [webln.keysend](broken://pages/vWMNoFEaHGHkTPwX0VcQ).

**Method**

```typescript
async function sendPayment(paymentRequest: string): SendPaymentResponse;
```

#### Parameters

```javascript
paymentRequest: string // the invoice you'd like the user to pay (lnbc...)
```

#### Response

```typescript
interface SendPaymentResponse {
  preimage: string;
}
```

#### Example

```typescript
const invoice = "lnbc100...";
const result = await window.webln.sendPayment(invoice);
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/RwxdQNO>" %}


# webln.sendPaymentAsync()

Request that the user sends a payment for an invoice. The application needs to provide a [BOLT-11](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md) invoice. The payment will only be initiated and will not wait for a preimage to be returned. This is useful when paying [HOLD invoices](https://guides.getalby.com/alby-guides/alby-browser-extension/features/hold-payments). There is no guarantee that the payment will be successfully sent to the receiver. It's up to the receiver to check whether or not the invoice has been paid.

{% hint style="warning" %}
This API may not be available on all [providers](https://www.webln.guide/ressources/webln-providers).&#x20;
{% endhint %}

**Method**

```typescript
async function
    sendPaymentAsync(paymentRequest: string): SendPaymentAsyncResponse;
```

#### Parameters

```javascript
paymentRequest: string // the invoice you'd like the user to pay (lnbc...)
```

#### Response

```typescript
interface SendPaymentAsyncResponse {} // no preimage returned!
```

#### Example

```typescript
const invoice = "lnbc100...";
const result = await window.webln.sendPaymentAsync(invoice);
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/KKbJvWy>" %}


# webln.signMessage()

Request that the user signs an arbitrary string message.&#x20;

Signed messages can either be verified server-side using the LND RPC method, or by clients with [webln.verifyMessage](https://webln.dev/#/api/verify-message).

#### Method

```typescript
async function signMessage(message: string): SignMessageResponse;
```

#### Response

```typescript
interface SignMessageResponse {
  message: string;
  signature: string;
}
```

#### Code Example <a href="#demo" id="demo"></a>

```typescript
await webln.enable();
await webln.signMessage("Sample message"); 
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/eYyXQNQ>" %}

**Example in the wild**

<https://amboss.space/> uses `webln.signMessage()`for login. Users sign a message and prove ownership of a lightning node.

&#x20;<img src="/files/ISLoTIPjDhpBGNYxPuQj" alt="" data-size="original">


# webln.verifyMessage()

Opens an external view where the user's client verifies the signature against the raw message, and let's the user know if it was valid. There's no return value, this method is intended purely for the user to verify a signature themselves without having to trust your website.

#### Method

```typescript
function verifyMessage(signature: string, message: string): void;
```

#### Code example <a href="#demo" id="demo"></a>

```typescript
await webln.enable();
await webln.verifyMessage("rbpr1...", "Message"); 
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/vYpPQLG>" %}


# webln.request()

A generic API to leverage the full potential of your connected node. Use any API node provides.

➡️ This API is part of the upcoming [WebBTC](https://webbtc.dev/) spec.&#x20;

{% hint style="warning" %}
The available APIs heavily depend on the connector (LND, CLN, etc) that is used. You can use [`webln.getInfo`](/building-lightning-apps/webln-reference/webln.getinfo) to check for supported methods. (`methods`)&#x20;
{% endhint %}

#### Method

```typescript
async function request(method: string, params: Object): RequestResponse;
```

#### Response

See the API docs of the connector that is currently in use. (e.g. the [LND API](https://api.lightning.community/) or the [CLN API](https://lightning.readthedocs.io/))

#### Code Example (using LND) <a href="#demo" id="demo"></a>

<pre class="language-typescript"><code class="lang-typescript">await webln.enable();

// check if the connected node supports the required methods
<strong>const info = await webln.getInfo();
</strong><strong>if (!info.methods.includes("listpeers")) {
</strong><strong>  alert('Invalid node connection. Please use LND');
</strong><strong>}
</strong>// list all connected peers
await webln.request("listpeers");
// response: 
{ peers: [
  address: "85.128.153.40:9735",
  bytes_recv: "23275891"
  bytes_sent: "519238"
  ... see LND API: https://api.lightning.community/#lnrpc-peer
]}

// connect to a new peer
const pubkey = "02af02be7c7e5cf...";
const host = "152.82.72.42:9735";
await webln.request('connectpeer', { addr: {host, pubkey }, perm: true})
</code></pre>

#### Demos

* [Liquimercado ](https://replit.com/@getalby/liquimercado-core-lightning)(Core Lightning)
* [Liquimercado](https://replit.com/@getalby/liquimercado-lnd) (LND)
* [Boostagram viewer ](https://replit.com/@getalby/boostagram-viewer-LND#src/Home.tsx)(LND)

### Supported connectors

<table><thead><tr><th width="331">Connector</th><th align="center">🐝 Alby</th></tr></thead><tbody><tr><td><a href="https://lightning.readthedocs.io/">Core Lightning</a></td><td align="center">✅</td></tr><tr><td><a href="https://api.lightning.community/">LND</a></td><td align="center">✅</td></tr></tbody></table>


# webln.lnurl()

Request to execute a [LNURL](https://github.com/lnurl/luds) request. The application needs to pass a [LNURL](https://github.com/lnurl/luds/blob/luds/01.md) string which should be provided for example by the application's backend. The lnurl function can also accept a [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md) static identifier (e.g. <username@getalby.com>) instead of a LNURL string.

The method returns a promise which resolves once the LNURL flow is completed. It returns the last response from the LNURL server. For LNURL-pay requests it also contains payment information (preimage, payment hash) and for LNURL-auth requests it contains auth information (message, signature)&#x20;

{% hint style="warning" %}
This API may not be available on all [providers](https://www.webln.guide/ressources/webln-providers).&#x20;
{% endhint %}

#### Method

```typescript
async function lnurl(lnurl: string): LNURLResponse;
```

#### Response

```typescript
type LNURLResponse =
  | {
      status: "OK";
      data?: unknown
    }
  | { status: "ERROR"; reason: string };
```

#### LNURL-pay Response&#x20;

```typescript
type LNURLPayResponse =
  | {
      status: "OK";
      data: { 
        preimage: string, 
        paymentHash: string, 
        paymentRequest: string
      }
    }
  | { status: "ERROR"; reason: string };
```

#### LNURL-auth Response&#x20;

```typescript
type LNURLAuthResponse =
  | {
      status: "OK";
      data: { 
        message: string, 
        signature: string
      }
    }
  | { status: "ERROR"; reason: string };
```

#### Code Example <a href="#demo" id="demo"></a>

```typescript
// const lnurl = (provided by your application backend)
if (!webln.lnurl) { alert('not supported'); }

await webln.enable();
const result = await webln.lnurl(lnurl); // promise resolves once the LNURL process is finished (e.g. a payment is sent or the login is complete)
```

#### Demos

* [Lightsats](http://lightsats.com/) (LNURL-pay, LNURL-withdraw)
* [getAlby.com](https://getalby.com/) (LNURL-auth login via getAlby extension, Lightning address)


# webln.on()

This method specifically allows you to listen for a particular event such as "accountChanged" and execute a callback function when this event occurs.

{% hint style="warning" %}
This API may not be available on all [providers](https://www.webln.guide/ressources/webln-providers).&#x20;
{% endhint %}

#### Method

```typescript
function on(eventName: "accountChanged", listener: () => void): void;
```

#### Code Example <a href="#demo" id="demo"></a>

```typescript
if (!webln.on) { alert('not supported'); }

await webln.enable();
webln.on("accountChanged", accountChangedHandler); // callback is executed once account is changed in provided with multiple accounts

function accountChangedHandler() {
    console.log("Account Changed!");
}
```

#### Demo

{% embed url="<https://codepen.io/getalby/pen/Rwqmodm>" %}


# webln.off()

This particular method enables you to cancel your subscription to an event that was initially set up using the `webln.on()` function. This allows you to stop receiving notifications or triggers when a specific event occurs.

{% hint style="warning" %}
This API may not be available on all [providers](https://www.webln.guide/ressources/webln-providers).&#x20;
{% endhint %}

#### Method

```typescript
function off(eventName: "accountChanged", listener: () => void): void;
```

#### Code Example <a href="#demo" id="demo"></a>

```typescript
if (!webln.on) { alert('not supported'); }

await webln.enable();
// subscribe to the accountChanged event
webln.on("accountChanged", accountChangedHandler); // callback is executed once account is changed in provided with multiple accounts

// use .off() to unsubscribe from the event. 
webln.off("accountChanged", accountChangedHandler);

function accountChangedHandler() {
    console.log("Account Changed!");
}


```


# webln.getBalance()

Fetch the balance of the current account.

{% hint style="warning" %}
This API may not be available on all [providers](https://www.webln.guide/ressources/webln-providers).&#x20;
{% endhint %}

#### Method

```typescript
async function getBalance(): BalanceResponse;
```

#### Response

```typescript
type BalanceResponse = {
    balance: number;
    currency?: "sats" | "EUR" | "USD"
}
```

**Code Example**

```typescript
await webln.enable();
const result = await webln.getBalance();
```

**Demo**

{% embed url="<https://codepen.io/getalby/pen/xxQabJx>" %}


# Error handling

There are different errors that could happen while using the WebLN APIs:

* User denies access to WebLN
* User cancels the process
* Connection errors
* Payment errors&#x20;

When an error happens during a WebLN API call the exception is thrown. Thus it is heavily recommended to handle different kinds of errors and let the user know what went wrong.&#x20;

```javascript
function pay() {
  if(typeof window.webln === 'undefined')
    return;
  
  try {
    await window.webln.enable();
    await window.webln.sendPayment(...);
  }
  catch(err) {
    console.log(error);
  }
}
```


# Libraries and Tools

Available libraries and tools for a quick start.

### Libraries

* [webln-types](https://www.npmjs.com/package/@webbtc/webln-types)\
  Typescript definitions for WebLN
* [flutter\_webln](https://github.com/aniketambore/flutter_webln)\
  Flutter library for WebLN

### Examples

* [webln-demo](https://github.com/bumi/webln-demo): Code examples to build your first lightning web application
* [WebLN Experiments](https://webln.twentyuno.net): Try out different WebLN use cases yourself
* [WebLN Sandbox](https://rolznz.github.io/webln-sandbox): Learn what you can do with WebLN hands-on.&#x20;

### Templates

* [Lightning App Template](https://github.com/reneaaron/lapp-template/): A simple project template to build your ⚡ Lightning Apps on. Authentication, WebLN, QR-Code fallbacks and more! ([Glitch](https://lightning-app-template.glitch.me/))
* [LN App starter](https://github.com/zerealschlauskwab/lnapp-starter): Convenient starter for lightning network driven web apps. Authentication and users are already there. Users can authenticate themselves, deposit and withdraw.

### Tools

* [Lightning Payment Request Decoder](https://lndecode.com/)
* [LNURL Decoder / Encoder](https://lnurl.fiatjaf.com/codec/)

###


# Best Practices

### Inform & ask before you prompt

Most of WebLN's methods will prompt the user to make payments or have them provide information. Before running `window.webln.enable()` or other methods, make sure the user knows what your app does, and why they should allow your calls to run. Popping up a window as soon as they load a page will cause users to reject WebLN requests, or worse yet, bounce from your page. Explicit buttons (e.g. to login) are helpful, but alternatives could be hiding pages behind loaders while requesting the user's provider, or keeping it to sub-pages and having your homepage not require WebLN.

### Prioritize WebLN, offer fallback options

WebLN offers a very convenient way for users to interact with their lightning wallets. Therefore you should always check for WebLN support before showing some fallback options (QR codes, copy invoice, etc).

#### Code Example

```javascript
// check if the browser supports WebLN
if (window.webln) {
    try {
        // if webln is available, ask the user for permission (typically happens only once)
        await window.webln.enable();

        try {
            // if the user gave permission to use webln, initate the payment
            const res = await window.webln.sendPayment(parsed.invoice);
            // the response contains the pre-image of the payment and could be used to verify the payment by comparing the hashes
            console.log(res);
        }
        catch(e) {
            // something went wrong during the payment, inform the user
            showError(e);
        }

    }
    catch(e) {
        // if the user cancels or something goes wrong, we show the modal with the invoice and the QR code (as it is currently)
        showModal();
    }
} else {
    // if webln is not supported we simply show the modal as we currently do
    showModal();
}
```

If a user does not have a compatible client, inform them (e.g. with [Error](/building-lightning-apps/webln-reference/error-handling) messages) and let them know how to get started with a WebLN client. This is also a good time to promote your favorite WebLN provider projects!

For simple use cases such as making payments, you can always just use BOLT-11 links instead of `webln.sendPayment` to have maximum compatibility with all types of Lightning clients.

```html
<a href="lightning:lnbc100...">Pay</a>
```

### **Don't Assume a Particular Client**

Anyone can make a WebLN provider, so don't assume the user is using a particular one, such as Alby or Joule. Try to stay agnostic in your language about the user's client, e.g. instead of saying `Pay`*`with Alby`*, just say `Pay`.


# WebLN Providers

### Desktop (browser extensions)

* [Alby](https://getalby.com/): a versatile open-source browser extension for the bitcoin lightning network
* [Joule](https://lightningjoule.com/): a WebLN-enabled browser extension that uses your own node
* [Kollider](https://kollider.xyz/): a browser extension with stable sats support
* [kwh](https://github.com/fiatjaf/kwh/): A Firefox/Chrome extension for WebLN to your CoreLightning node
* [OneKey](https://onekey.so/): Open-source crypto wallet

### Mobile wallets

* [Blixt Wallet](https://blixtwallet.github.io/): a non-custodial open-source Lightning Wallet with a WebLN browser
* [BlueWallet](https://bluewallet.io/): a mobile wallet with a WebLN browser
* [Breez](https://breez.technology/): a mobile wallet with selected WebLN apps in their marketplace
* [OneKey](https://onekey.so/): Open-source crypto wallet with a WebLN browser

### Mobile

* [Kiwi Browser](https://kiwibrowser.com/) with Chrome extension


# Showcases

### Overview of Lightning applications

[BOLT.FUN](https://makers.bolt.fun/projects) provides a fantastic overview of Lightning applications. Get your client providers ready and send them some sats.

![https://makers.bolt.fun/projects](/files/ndgAggWQdEmDTDrsD90j)


# Tutorials

### Videos

#### Introduction to the WebLN Guide and the Lightning App Template

{% embed url="<https://www.youtube.com/watch?v=E_Ct2JoFYEo>" %}
Presentation of the WebLN Guide and demonstration of the Lightning App Template
{% endembed %}

#### Building Your First Lightning Web App

{% embed url="<https://www.youtube.com/watch?v=FT9MiC5pQh8>" %}
Building your frist Lightning web app
{% endembed %}


# Additional Resources

**Bitcoin and Lightning Network web resources**

The listed links are not related to WebLN. They serve the purpose for interested readers to learn more about Bitcoin and the Lightning Network in general.

* [Bitcoin.org](https://bitcoin.org/en/vocabulary)&#x20;
* [Bitcoin Q + A glossary](https://www.bitcoinqna.com/glossary)&#x20;
* [bolt.fun](https://bolt.fun/)
* [Lightning Node Management](https://www.lightningnode.info/)
* [Mastering the Lightning Network](https://github.com/lnbook/lnbook)&#x20;
* [Seminar for Bitcoin and Lightning protocol](https://github.com/chaincodelabs/seminars)&#x20;

<table data-view="cards"><thead><tr><th align="center"></th></tr></thead><tbody><tr><td align="center">Card 1</td></tr><tr><td align="center">Card 2</td></tr></tbody></table>


# Working Group & Guidelines

### Contribute to the guide&#x20;

The WebLN Guide is written in Gitbook, a collaboration platform. This is where you can comment, propose changes and see what needs to be done. Join our open community and help us improve the Lightning Web Standard (WebLN).&#x20;

### Improve the WebLN standard

There is a working group to merge Bitcoin on- and off-chain standards to facilitate the adoption of Bitcoin. Join the Telegram group and participate in the discussions.

\--> [Bitcoin and Lightning Layer Network Specs](https://web.telegram.org/z/#-1784703682)

and consider creating a GitHub issue [here](https://github.com/joule-labs/webln/issues)

### Content guidelines

The WebLN guide is the work of many authors with different backgrounds, each with their own unique voice and perspective. To help us ensure a consistent written voice throughout the guide, follow these content guidelines.&#x20;

**Know your reader**: This guide is crafted for anyone interested in building an effective Bitcoin application. A large part of this group are developers, but also designers and product managers, and others who actively shape the end-user experience. Consider their perspectives and needs first and avoid going into topics that are not relevant to these readers’ goals.&#x20;

**Speak to the reader:** Address the reader directly. Whenever possible, try using active instead of passive voice. Make the reader a part the conversation by using second-person pronouns like “you, your and yours”. Do not write in first-person and avoid giving predictions and personal opinions.&#x20;

**Use simple language**: Not everyone using this guide is a native English speaker. Make sure you are writing in plain, easy to follow English. If you’re still not sure, try using a readability tool to analyze your text and make recommendations.&#x20;

**Be concise**: Focus on information relevant to the reader. Use direct, clear, concise sentences that are easy to understand. Try to reduce the word count to just the right brevity without being obscure.&#x20;

**Make content scannable**: On the internet, most people scan the content before reading it. Split text into paragraphs, use links, text styling and images to make this easier. Each paragraph should ideally have no more than 3-4 sentences.&#x20;

**Linking**: Linking provides necessary context and helps avoid information repetition. Link to the Glossary, to another page in the guide whenever possible or to a reputable third-party resource. Give tips and get the reader involved: If you are a developer ask yourself where did you struggle most when implementing WebLN and provide tips to help others. Show, don’t tell: When it’s possible, try to provide code examples.&#x20;

**Use the right medium**: Don’t be afraid to try a different medium such as pictures, videos or interactive prototypes if you think it will inform better than text.


# Glossary

**Lightning network**: The Lightning Network extends Bitcoin with payment channels to increase transaction speed and lower costs. It is becoming widely adopted and accepted as the preferred way to scale Bitcoin.

**Payment**: A payment is a transaction that occurs over the Lightning network. Payments are routed through Lightning payment channels and are not recorded in the Bitcoin blockchain.

**Transaction**: A transaction is a transfer of value over the Bitcoin network. While transactions can be complicated, one of the simplest forms of a transaction would be sending bitcoin from one address to another. A transaction is not considered final until it has been included in a valid block by a miner.

**Web3.js**: [web3.js](https://www.npmjs.com/package/web3) is a collection of libraries that allow you to interact with a local or remote ethereum node using HTTP, IPC or WebSocket.

**WebLN provider**: Providers are classes that implement the interface provided in [WebLN Reference](/building-lightning-apps/webln-reference)


