npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@azex/ledger-react

v0.5.1

Published

React UI + data-layer for the [azex-ai/ledger](https://github.com/azex-ai/ledger) double-entry ledger engine. Ships typed hooks (TanStack Query), a router-agnostic sidebar, dashboard widgets, ready-made admin **page** components, and an all-in-one `<Ledge

Readme

@azex/ledger-react

React UI + data-layer for the azex-ai/ledger double-entry ledger engine. Ships typed hooks (TanStack Query), a router-agnostic sidebar, dashboard widgets, ready-made admin page components, and an all-in-one <LedgerAdmin/> shell.

Install

This package is published to the public npm registry — install it directly, no registry config or auth token required:

npm install @azex/ledger-react @tanstack/react-query

Peer deps: react@^19, react-dom@^19, @tanstack/react-query@^5.

Setup

  1. Wrap your app in <LedgerProvider> with the ledger API base URL (and optional API key). It owns a TanStack QueryClient unless you pass your own.

    import { LedgerProvider } from "@azex/ledger-react";
    
    <LedgerProvider config={{ baseUrl: "https://ledger.example.com", apiKey }}>
      {children}
    </LedgerProvider>
  2. Import the stylesheet once at your app root:

    import "@azex/ledger-react/styles.css";
  3. Mount <Toaster/> once so page actions can surface toast feedback. Use the re-exported sonner Toaster (no direct sonner dependency needed):

    import { Toaster } from "@azex/ledger-react";
    
    <Toaster theme="dark" position="bottom-right" />

    If you use <LedgerAdmin/> (below), it mounts its own <Toaster/> — skip this step.

Usage

Option A — <LedgerAdmin/> (zero routing)

The convenience shell renders the sidebar + content area, switches sections via internal state (no URL), and self-mounts <Toaster/>. Chart-bearing pages are lazy-loaded so recharts never enters your initial bundle.

import { LedgerProvider, LedgerAdmin } from "@azex/ledger-react";
import "@azex/ledger-react/styles.css";

export default function Admin() {
  return (
    <LedgerProvider config={{ baseUrl: "https://ledger.example.com" }}>
      <LedgerAdmin />
    </LedgerProvider>
  );
}

Option B — individual pages wired to your router

Import the *Page components and wire them to your host router. Each is a "use client" component. Pages that link out accept an injectable linkComponent (defaults to a plain <a>); JournalDetailPage takes the journal id as a prop (extract it from your route param).

import {
  JournalsPage,
  JournalDetailPage,
  ReservationsPage,
  DepositsPage,
  WithdrawalsPage,
  ClassificationsPage,
  JournalTypesPage,
  TemplatesPage,
  CurrenciesPage,
  ReconciliationPage,
  SnapshotsPage,
} from "@azex/ledger-react";

Chart-bearing pages — import from @azex/ledger-react/charts

DashboardPage and BalancesPage render recharts charts, so they ship from the ./charts subpath to keep recharts out of the root barrel. Import them (and the BalanceTrend widget) from there:

import { DashboardPage, BalancesPage, BalanceTrend } from "@azex/ledger-react/charts";

Server prefetch (RSC) — import from @azex/ledger-react/server

For React Server Components / Route Handlers, prefetch ledger data on the server and hydrate the client hooks with no client-side waterfall. The /server entry has no "use client" directive and is server-only:

Never import @azex/ledger-react/server from a client component. createServerLedgerClient takes the server API key — keeping this entry off the client barrel ensures the server key never reaches the client bundle.

// app/journals/page.tsx (server component)
import { QueryClient, HydrationBoundary, dehydrate } from "@tanstack/react-query";
import { JournalsPage } from "@azex/ledger-react";
import {
  createServerLedgerClient,
  prefetchJournals,
} from "@azex/ledger-react/server";

export default async function Page() {
  const queryClient = new QueryClient();
  const client = createServerLedgerClient({ baseUrl, apiKey }); // server-side key
  await prefetchJournals(queryClient, client, 20);

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <JournalsPage linkComponent={YourLink} />
    </HydrationBoundary>
  );
}

Available prefetch* helpers: prefetchJournals, prefetchEntries, prefetchBalances, prefetchSystemHealth, prefetchSystemBalances, prefetchReservations, prefetchClassifications, prefetchCurrencies, prefetchJournalTypes, prefetchTemplates, prefetchSnapshots. The shared ledgerKeys query-key factory is also exported for advanced cache seeding.

HeroUI skin — @azex/ledger-react/heroui

Building on HeroUI v3 instead of the default shadcn-style components? The same admin surface (provider, <LedgerAdmin/>, all pages) ships as a second skin on the ./heroui subpath, backed by the identical headless core:

import { LedgerAdmin, LedgerProvider } from "@azex/ledger-react/heroui";

Host contract: @heroui/react + @heroui/styles installed (optional peer — consumers of the default skin never need it), Tailwind v4 configured, and one stylesheet import for the skin's layout classes:

/* globals.css */
@import "tailwindcss";
@import "@heroui/styles";
@import "@azex/ledger-react/heroui.css";

Theme (light/dark, palette) is owned by the host's HeroUI setup — the skin renders with whatever theme the surrounding app defines.

Headless — @azex/ledger-react/headless

The UI-free core both skins build on (typed client + provider + every TanStack Query hook) is importable directly for hosts that bring their own components:

import { LedgerProvider, useJournals } from "@azex/ledger-react/headless";

End-user wallet — @azex/ledger-react/wallet

The holder-scoped wallet surface for YOUR users (not operators): balances (available / pending / on hold), translated transaction history, refund markers. Read-only by design — top-up / cash-out flows stay in the host product and slot in via actions.

import { WalletPanel, WalletProvider } from "@azex/ledger-react/wallet";

<WalletProvider config={{ baseUrl: "/api/v1", getToken: fetchWalletToken }}>
  <WalletPanel actions={<TopUpButton />} kindLabels={{ deposit_confirm: "Top up" }} />
</WalletProvider>;

getToken returns a holder token your backend mints (HTTP POST /holder-tokens or in-process server.MintHolderToken); it is called lazily and once more after a 401. Omit it behind a same-origin BFF. Components: WalletPanel, WalletBalances, WalletBalanceCard, TransactionList. HeroUI variant at @azex/ledger-react/wallet/heroui, UI-free core (client + hooks) at @azex/ledger-react/wallet/headless.

Theming

The Provider (and <LedgerAdmin/>) render a <div className="ledger-root"> wrapper. All design tokens are scoped under .ledger-root so importing the stylesheet never leaks tokens into your host app — and the stylesheet is self-contained: it ships its own .ledger-root-scoped preflight (fonts, resets, table borders), so it renders correctly even in a host with no Tailwind setup at all.

Default appearance is system (follows the OS via prefers-color-scheme); pass appearance: "dark" or "light" to force a variant:

<LedgerProvider config={{ baseUrl, appearance: "dark" }}>

Re-theme by overriding the CSS custom properties:

.ledger-root {
  --primary: oklch(0.6 0.2 250);
  --radius: 0.5rem;
}

Or pass per-instance overrides inline via the provider theme prop (applied as inline style on the .ledger-root div):

<LedgerProvider config={{ baseUrl, theme: { "--primary": "oklch(0.6 0.2 250)" } }}>

Reference integration

The web/ app in azex-ai/ledger is the working reference integration — it consumes this package as its only ledger UI/data source (dogfood) and demonstrates both the client provider setup and the /server RSC prefetch pattern with a Next.js linkComponent adapter.

Exports

  • Root (@azex/ledger-react)LedgerProvider, useLedgerClient, createLedgerClient, all hooks (useJournals, useBalances, useReservations, …), Sidebar, LEDGER_NAV_ITEMS, HealthCards, RecentJournals, StatusBadge, the 11 non-chart *Page components, LedgerAdmin, and Toaster.
  • @azex/ledger-react/chartsDashboardPage, BalancesPage, BalanceTrend (recharts-backed).
  • @azex/ledger-react/server (server-only) — createServerLedgerClient, the prefetch* helpers, and ledgerKeys. No "use client" directive; never import from a client component.
  • @azex/ledger-react/styles.css — bundled Tailwind styles.

The complete API reference (per-hook signatures, endpoints, component props, prefetch helpers, query-key factory) lives in the repo at docs/frontend.md.

Releasing

Publishing is tag-driven (CI workflow ledger-react-publish.yml). The tag version must match package.json — CI fails fast otherwise.

  1. Bump version in web/packages/ledger-react/package.json.

  2. Commit the bump.

  3. Tag and push:

    git tag ledger-react-v<version>   # e.g. ledger-react-v0.1.0
    git push --tags

The workflow re-runs the full verify gate (typecheck, test, build, artifact assertions), asserts the tag matches package.json, then publishes to GitHub Packages.