> ## Documentation Index
> Fetch the complete documentation index at: https://second.tech/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Get started with web apps

> Add Ark payments to your web app. Create a wallet, generate addresses, and check your balance in minutes.

<Prompt description="Use this prompt to get started quickly." icon="microchip" iconType="solid" actions={["copy", "cursor"]}>
  # Bark SDK: Web

  Build Ark wallet apps with `@secondts/bark`. Ark is a Bitcoin layer 2 protocol for instant, low-fee, self-custodial payments.

  The SDK runs entirely in the browser via WebAssembly, with wallet state persisted to IndexedDB.

  ## Prerequisites

  * A modern browser with WebAssembly and IndexedDB support
  * A secure context: served over **HTTPS** or `localhost` (`crypto.subtle` is unavailable otherwise)
  * For the bundler setup: Node.js 18+ and any bundler that can emit a `.wasm` asset (Vite, webpack, Next, etc.).

  ## Install (Vite)

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
  npm install @secondts/bark
  ```

  Import from the `@secondts/bark/web` subpath, and load the `.wasm` with your bundler's URL import (Vite's `?url`) to pass to `init()`. Your bundler emits it as a hashed asset; the example below shows the full setup.

  The only bundler-specific line is how you get the `.wasm` URL to pass to `init()`:

  * **Vite:** `import wasmUrl from "@secondts/bark/web/bark_ffi_wasm_bg.wasm?url"`
  * **webpack / Next:** `new URL("@secondts/bark/web/bark_ffi_wasm_bg.wasm", import.meta.url)`
  * **Fallback (any):** copy `bark_ffi_wasm_bg.wasm` into your served/public dir and pass its path string.

  ## Install (Vanilla HTML/JS)

  No install step. Import the `./web` subpath directly from a CDN inside a `<script type="module">`.

  ## Create a wallet

  ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import init, { Wallet, generateMnemonic } from "@secondts/bark/web";
  import type { Config, Network } from "@secondts/bark/web";
  // Vite resolves `?url` to the hashed asset URL of the wasm binary.
  import wasmUrl from "@secondts/bark/web/bark_ffi_wasm_bg.wasm?url";

  // Instantiate the wasm module before any binding is called.
  await init({ module_or_path: wasmUrl });

  const mnemonic = generateMnemonic();
  const network: Network = "Signet";
  const config: Config = {
    serverAddress: "https://ark.signet.2nd.dev",
    esploraAddress: "https://esplora.signet.2nd.dev",
    network,
  };
  const wallet = await Wallet.create({
    mnemonic,
    config,
    dbName: "bark-signet",
    forceRescan: false,
  });
  ```

  ## Get address and check balance

  ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const address = await wallet.newAddress();
  await wallet.sync();
  const balance = await wallet.balance();
  console.log(balance.spendableSats, "sats");
  ```

  ## Signet test environment

  * Ark server: [https://ark.signet.2nd.dev](https://ark.signet.2nd.dev)
  * Block explorer (Esplora): [https://esplora.signet.2nd.dev](https://esplora.signet.2nd.dev)
  * Faucet for test bitcoin: [https://signet.2nd.dev/](https://signet.2nd.dev/)
  * Network value: `"Signet"`

  ## Rules

  * Call `await init()` (passing the `.wasm` URL where required) **before** any other binding. Bindings called before instantiation throw.
  * Use `Wallet.create({ ... })` (static method) with a **named-parameter object**, not positional arguments, `WalletCreate()`, or `new Wallet()`. Required fields: `mnemonic`, `config`, `dbName`, `forceRescan`.
  * Use `Wallet.open({ mnemonic, config, dbName })` to reopen an existing wallet by `dbName`.
  * `config` is a plain object. Only `serverAddress` and `network` are required; the rest (`esploraAddress`, `bitcoind*`, fee/sync thresholds, etc.) are optional and may be omitted.
  * `network` is a **string literal** (`"Signet"`, `"Bitcoin"`, `"Testnet"`, `"Regtest"`). There is no runtime enum.
  * Wallet state persists in **IndexedDB**, keyed by `dbName`. There is no filesystem path.
  * Must run in a **secure context** (HTTPS or `localhost`); `crypto.subtle` is required.
  * Wallet operations are async. Always use `await`.
  * Use `"Signet"` for testing. Never use mainnet without user confirmation.
  * Never hardcode mnemonics in production code.
  * Correct terminology: Ark (not ARC), VTXO (not vtxo), on-chain (not onchain), off-chain (not offchain).
  * "Bark" (capitalized) in prose, "bark" (lowercase) for the package name.
</Prompt>

<Tip>
  These examples connect to **signet** so you can test for free. To go live, point the same configuration at Second's mainnet endpoints from [Test on mainnet](/getting-started/bark-cli/mainnet#connection-details) and select the mainnet network.
</Tip>

## Prerequisites

* A modern browser with WebAssembly and IndexedDB support
* A secure context: served over **HTTPS** or `localhost` (`crypto.subtle` is unavailable otherwise)
* For the bundler setup: Node.js 18+ and any bundler that can emit a `.wasm` asset (Vite, webpack, Next, etc.).

## Getting started

<Steps>
  <Step title="Install the SDK">
    <Tabs>
      <Tab title="Vite">
        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        npm install @secondts/bark
        ```

        Import from the `@secondts/bark/web` subpath, and load the `.wasm` with your bundler's URL import (Vite's `?url`) to pass to `init()`. Your bundler emits it as a hashed asset; the example below shows the full setup.

        The only bundler-specific line is how you get the `.wasm` URL to pass to `init()`:

        * **Vite:** `import wasmUrl from "@secondts/bark/web/bark_ffi_wasm_bg.wasm?url"`
        * **webpack / Next:** `new URL("@secondts/bark/web/bark_ffi_wasm_bg.wasm", import.meta.url)`
        * **Fallback (any):** copy `bark_ffi_wasm_bg.wasm` into your served/public dir and pass its path string.
      </Tab>

      <Tab title="Next">
        ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
        npm install @secondts/bark
        ```

        Same install as Vite. See the Create a wallet tab for the Next setup.
      </Tab>

      <Tab title="Vanilla HTML/JS">
        No install step. Import the `./web` subpath directly from a CDN inside a `<script type="module">`:

        ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
        <script type="module">
          import init, { generateMnemonic } from "https://unpkg.com/@secondts/bark/web/bark_ffi_wasm.js";
        </script>
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Create a wallet">
    Generate a BIP39 mnemonic, configure the wallet for signet, and initialize it. The wasm module must be instantiated with `init()` before any binding is called.

    <Tabs>
      <Tab title="Vite">
        ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
        import init, {
          Wallet,
          generateMnemonic,
        } from "@secondts/bark/web";
        import type { Config, Network } from "@secondts/bark/web";
        // Vite resolves `?url` to the hashed asset URL of the wasm binary.
        import wasmUrl from "@secondts/bark/web/bark_ffi_wasm_bg.wasm?url";

        // Instantiate the wasm module before any binding is called.
        await init({ module_or_path: wasmUrl });

        // Generate a new mnemonic
        const mnemonic = generateMnemonic();
        console.log("Mnemonic:", mnemonic);

        // Configure for signet.
        // `Network` is a string-literal union in the bindings (no runtime enum).
        const network: Network = "Signet";
        const config: Config = {
          serverAddress: "https://ark.signet.2nd.dev",
          esploraAddress: "https://esplora.signet.2nd.dev",
          network,
        };

        // Create the wallet. State is persisted to IndexedDB, keyed by `dbName`.
        const wallet = await Wallet.create({
          mnemonic,
          config,
          dbName: "bark-signet",
          forceRescan: false,
        });
        ```
      </Tab>

      <Tab title="Next">
        ```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
        // app/BarkClient.tsx
        "use client";
        import { useEffect } from "react";

        export default function BarkClient() {
          useEffect(() => {
            (async () => {
              // Dynamic import keeps wasm out of the server render graph.
              const { default: init, Wallet, generateMnemonic } = await import("@secondts/bark/web");

              // `?url` is Vite-only; in Next resolve the wasm via import.meta.url.
              const wasmUrl = new URL("@secondts/bark/web/bark_ffi_wasm_bg.wasm", import.meta.url);
              await init({ module_or_path: wasmUrl });

              const mnemonic = generateMnemonic();
              const config = {
                serverAddress: "https://ark.signet.2nd.dev",
                esploraAddress: "https://esplora.signet.2nd.dev",
                network: "Signet" as const,
              };
              const wallet = await Wallet.create({ mnemonic, config, dbName: "bark-signet", forceRescan: false });
              const address = await wallet.newAddress();
              await wallet.sync();
              const balance = await wallet.balance();
              console.log(address, balance.spendableSats, "sats");
            })();
          }, []);

          return <div>see console</div>;
        }
        ```

        <Note>
          bark is browser-only (IndexedDB, `crypto.subtle`). Load it in a `"use client"` component inside `useEffect` so it never runs during SSR. `dynamic(import, { ssr: false })` is not allowed from a Server Component in Next 15 — use the `useEffect` pattern above.
        </Note>
      </Tab>

      <Tab title="Vanilla HTML/JS">
        ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
        <!doctype html>
        <html>
          <body>
            <script type="module">
              import init, {
                Wallet,
                generateMnemonic,
              } from "https://unpkg.com/@secondts/bark/web/bark_ffi_wasm.js";

              // Instantiate the wasm module (auto-resolves the .wasm via import.meta.url).
              await init();

              // Generate a new mnemonic
              const mnemonic = generateMnemonic();
              console.log("Mnemonic:", mnemonic);

              // Configure for signet.
              // `network` is a string literal, not an enum.
              const config = {
                serverAddress: "https://ark.signet.2nd.dev",
                esploraAddress: "https://esplora.signet.2nd.dev",
                network: "Signet",
              };

              // Create the wallet. State is persisted to IndexedDB, keyed by `dbName`.
              const wallet = await Wallet.create({
                mnemonic,
                config,
                dbName: "bark-signet",
                forceRescan: false,
              });
            </script>
          </body>
        </html>
        ```
      </Tab>
    </Tabs>

    <Note>
      Back up the mnemonic securely, and [back up wallet data continuously](/backups). Both are required to restore a wallet. To reopen an existing wallet on later loads, store the mnemonic and call `Wallet.open({ mnemonic, config, dbName })` instead of `Wallet.create`.
    </Note>
  </Step>

  <Step title="Get a receiving address">
    Generate an Ark address to receive funds.

    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const address = await wallet.newAddress();
    console.log("Ark address:", address);
    ```

    Send some signet sats to this address using [the faucet](https://signet.2nd.dev/).
  </Step>

  <Step title="Check your balance">
    Sync the wallet with the Ark server and read your balance.

    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
    await wallet.sync();

    const balance = await wallet.balance();
    console.log("Spendable:", balance.spendableSats, "sats");
    ```
  </Step>
</Steps>

## Next steps

<CardGroup cols={2}>
  <Card title="Source and examples" icon="https://mintcdn.com/second-0659a37d/IZIYL7kfKRS394NE/images/gitlab-icon-outline.svg?fit=max&auto=format&n=IZIYL7kfKRS394NE&q=85&s=31497d40e3e7174b42f13799a0b33eb5" href="https://gitlab.com/ark-bitcoin/bark-ffi-bindings/-/tree/master/wasm" width="192" height="192" data-path="images/gitlab-icon-outline.svg">
    Full Wasm source and example projects on GitLab.
  </Card>

  <Card title="How Ark works" icon="graduation-cap" href="/learn/intro">
    Learn about the protocol powering your wallet.
  </Card>
</CardGroup>
