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

@vishwesh_5544/t2-logger-ui

v0.3.0

Published

React components for browsing logs written by @vishwesh_5544/t2-logger.

Readme

@vishwesh_5544/t2-logger-ui

React components for browsing logs written by @vishwesh_5544/t2-logger — a full-page viewer and a slide-in sidebar, both talking to the createLogRouter endpoints over plain fetch.

Refresh is manual by design. There is no polling and no WebSocket.

Install

npm install @vishwesh_5544/t2-logger-ui
npm install react react-dom lucide-react   # peer dependencies

Usage

import { LogViewer, LogSidebar } from '@vishwesh_5544/t2-logger-ui';
import '@vishwesh_5544/t2-logger-ui/style.css';

<LogViewer apiBaseUrl="/api/logs" defaultFilters={{ level: 'error' }} />

apiBaseUrl points at whatever path your Express app mounts the router on — with app.use('/api', createLogRouter(...)) that is /api/logs. The component also calls {apiBaseUrl}/meta to populate the service dropdown.

LogViewer

| Prop | Type | Default | Notes | | ---------------- | ---------------------- | --------------- | ------------------------------ | | apiBaseUrl | string | — | Required | | defaultFilters | QueryFilters | {} | Applied to the first request | | pageSize | number | 25 | | | className | string | — | Merged onto the root element | | headers | object or function | — | Sent with every request | | credentials | RequestCredentials | 'same-origin' | Passed to fetch |

Authentication

The log endpoints expose everything your app logs, so you will usually want them behind auth. Protect the router with your existing middleware, then hand the same token to the component — no new auth concept required:

// Static token
<LogViewer apiBaseUrl="/api/logs" headers={{ Authorization: `Bearer ${token}` }} />

// Function form — re-read before every request, so rotation and refresh work
<LogViewer
  apiBaseUrl="/api/logs"
  headers={() => ({ Authorization: `Bearer ${localStorage.getItem('token')}` })}
/>

// Async, if the token must be renewed first
<LogViewer apiBaseUrl="/api/logs" headers={async () => ({ Authorization: `Bearer ${await getToken()}` })} />

For cookie-based auth on a different origin, set credentials="include" (the server must also send Access-Control-Allow-Credentials). Same-origin cookies are sent automatically.

A 401 surfaces through the normal error state with a retry button — it never throws.

Includes a filter bar (level multi-select, service dropdown, debounced search, date range, refresh button), a table with colour-coded level badges and expandable rows showing meta and error.stack, a copy-as-JSON button, and prev/next pagination. Loading, empty and error states are handled internally; the error state offers a retry.

LogSidebar

<LogSidebar
  apiBaseUrl="/api/logs"
  trigger={<button>View logs</button>}
  defaultFilters={{ level: 'error' }}
  side="right"
/>

| Prop | Type | Default | | ---------------- | -------------------- | --------------- | | apiBaseUrl | string | — | | trigger | React.ReactNode | — | | defaultFilters | QueryFilters | {} | | pageSize | number | 25 | | side | 'left' \| 'right' | 'right' | | headers | object or function | — | | credentials | RequestCredentials | 'same-origin' |

Renders trigger as-is and opens a slide-in panel containing a LogViewer when it is clicked. Open state is internal — no state management required. The backdrop and the close button both dismiss it.

Styling

The stylesheet is built with Tailwind v4 and must be imported once:

import '@vishwesh_5544/t2-logger-ui/style.css';

This stylesheet never touches your app's own elements. It ships Tailwind's theme tokens and the utilities these components use — and deliberately not Preflight, the global * / html / body reset. A component library that shipped Preflight would restyle its host (see CHANGELOG 0.3.0). The only non-utility rules are scoped under .vw-logger-ui and written with :where(), so they carry zero specificity and lose to any class the host applies.

Every exported component's root element carries a vw-logger-ui class, which you can use to scope overrides from the host application:

.vw-logger-ui table { font-size: 13px; }

If your app already uses Tailwind v4

You can skip style.css entirely and let your own Tailwind build generate the utilities by pointing it at this package's compiled output:

@import "tailwindcss";
@source "../node_modules/@vishwesh_5544/t2-logger-ui/dist/*.js";

That produces a single Tailwind output for the whole page instead of two, and keeps the bundle a little smaller. Either approach works — importing style.css is fine too.

Types

LogEntry, LogLevel, LogMeta, PaginatedLogs and QueryFilters are re-exported for convenience:

import type { LogEntry, QueryFilters } from '@vishwesh_5544/t2-logger-ui';

Tests

yarn workspace @vishwesh_5544/t2-logger-ui test

Component tests run against msw-mocked HTTP — no Express server and no MongoDB needed. That layer is covered by the core package's tests instead.

License

MIT