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

@a.nemreen/loggo

v0.1.3

Published

Beautiful console.log in development. Silent in production.

Readme


Why loggo?

Frontend apps fill up with temporary console.log calls. Before release you either:

  • hunt them down by hand
  • fight lint rules
  • wrap every call in if (import.meta.env.DEV)
  • or ship noisy (sometimes sensitive) output to users' consoles

loggo is a drop-in replacement: styled DevTools output while you build, and a silent noop build in production — so debug clutter never reaches the browser console.

Arguments are forwarded to native console.*. Objects stay expandable, DOM nodes stay inspectable, errors keep their stacks. Nothing is JSON.stringify'd.


Install

npm install @a.nemreen/loggo
pnpm add @a.nemreen/loggo
yarn add @a.nemreen/loggo
bun add @a.nemreen/loggo

Requirements: a modern bundler that honors package exports conditions (Vite, Webpack 5, Next.js, Rollup, esbuild, Parcel, and similar). Browser-first — not a Node/server logger.


Quick start

import { log } from '@a.nemreen/loggo';

log('Application initialized');
log('Current user:', user);
log('Selected element:', document.querySelector('#app'));

log.debug('Cache state:', cache);
log.info('User loaded:', user);
log.warn('Token expires soon');
log.error('Request failed:', error);

Open DevTools. In development you get timestamps and level badges. In a production build you get nothing.


How to use

1. Replace console.log

// before
console.log('user', user);

// after
import { log } from '@a.nemreen/loggo';
log('user', user);

log(...) and log.log(...) are the same.

2. Use levels when it helps

| Method | Console method | Badge | |---------------|----------------|-------| | log.debug() | console.debug | DEBUG | | log() / log.log() | console.log | LOG | | log.info() | console.info | INFO | | log.warn() | console.warn | WARN | | log.error() | console.error | ERROR |

log.debug('verbose detail', payload);
log.info('something happened', data);
log.warn('be careful', context);
log.error('it broke', error);

2b. Full console surface

Every common DevTools helper is mirrored and silent in production:

| Method | Native | |--------|--------| | log.dir() / log.dirxml() | inspect object / DOM tree | | log.table() | tabular data | | log.group() / log.groupCollapsed() / log.groupEnd() | collapsible groups | | log.time() / log.timeLog() / log.timeEnd() | timers | | log.count() / log.countReset() | counters | | log.assert() | log only when condition is false | | log.trace() | stack trace | | log.clear() | clear console | | log.timeStamp() / log.profile() / log.profileEnd() | performance markers |

log.table(users, ['id', 'name']);
log.group('checkout');
log.time('pay');
log.count('retry');
log.timeEnd('pay');
log.groupEnd();
log.assert(total > 0, 'total must be positive', { total });
log.trace('how did we get here?', ctx);

3. Name loggers per module

import { createLoggo } from '@a.nemreen/loggo';

const apiLog = createLoggo({ name: 'API' });
const authLog = createLoggo({ name: 'Auth' });

apiLog('Request started', { method: 'GET', path: '/users' });
apiLog.info('Response received', response);
authLog.warn('Session almost expired');
apiLog.error('Request failed', error);

Example DevTools output:

12:14:02 › API  LOG
  Request started  {…}

12:14:03 › API  INFO
  Response received  {…}

12:14:05 › Auth WARN
  Session almost expired

12:14:06 › API  ERROR
  Request failed  Error: …

4. Pass any value — keep DevTools native

log('primitives', 'hello', 123, true, null);
log('object', { id: 1, nested: { ok: true } });
log('array', [1, 2, 3]);
log('function', (x) => x * 2);
log('dom', document.querySelector('#app'));
log('error', new Error('boom'));

const circular = { label: 'node' };
circular.self = circular;
log('circular', circular); // safe — not JSON.stringified

5. Framework notes

Vite / Vitest — mode maps to development / production export conditions automatically.

Next.js (App or Pages) — client components and browser bundles resolve the matching build. Prefer loggo for client-side debug logs; use your server logger or monitoring for the backend.

Create React App / Webpack 5 — production builds resolve the silent entry.

SSR caveat: if a resolver does not understand export conditions, the default is silent (fail closed). That is intentional.


Landing & demo

Interactive landing: boot line, typewriter code, CRT sample stream, and live DevTools cases.

Live: https://nemreen.info/loggo

Local:

npm install
npm run demo

Open http://localhost:4173/demo/.

cPanel deploy

npm run build:site

Upload the contents of site/ (or unzip loggo-cpanel.zip) into public_html/loggo/ so index.html is at public_html/loggo/index.html.

| Section | What you get | |---------|----------------| | Hero | Logo stamp-in + typed // dev logs. prod silent. // | | Install / usage | Typewriter shell + app.ts snippets | | Live console | Looping CRT-style sample output | | Try samples | Real @a.nemreen/loggo calls in your DevTools | | Named / before-after | API logger example + migration contrast |


How production silence works

loggo ships two builds:

| Condition | Entry | Behavior | |-----------|--------|----------| | development | styled logger | timestamps + badges + native args | | production | noop logger | every method is () => {} | | default (fallback) | noop logger | silent if conditions are unknown |

Bundlers pick the entry by build mode. Production apps import the noop file directly — no per-call if (isProd) checks, and no reliance on dead-code elimination to strip the pretty path.

All levels are silent in production, including warn and error. Real production errors belong in Sentry (or similar) — not in the user's console via loggo.


API

export type LogFn = (...args: unknown[]) => void;

export interface Loggo {
  (...args: unknown[]): void;
  debug: LogFn;
  log: LogFn;
  info: LogFn;
  warn: LogFn;
  error: LogFn;
  dir: (item?: unknown, options?: Record<string, unknown>) => void;
  dirxml: LogFn;
  table: (data?: unknown, columns?: string[]) => void;
  group: LogFn;
  groupCollapsed: LogFn;
  groupEnd: () => void;
  time: (label?: string) => void;
  timeLog: (label?: string, ...data: unknown[]) => void;
  timeEnd: (label?: string) => void;
  count: (label?: string) => void;
  countReset: (label?: string) => void;
  assert: (condition?: boolean, ...data: unknown[]) => void;
  trace: LogFn;
  clear: () => void;
  timeStamp: (label?: string) => void;
  profile: (label?: string) => void;
  profileEnd: (label?: string) => void;
}

export interface LoggoOptions {
  /** Shown beside the level badge; also scopes time/count labels */
  name?: string;
}

/** Shared default logger */
export declare const log: Loggo;

/** Create a named (or extra) logger instance */
export declare function createLoggo(options?: LoggoOptions): Loggo;

Styled level lines use a blank line above the badge and put arguments on the next line so DevTools output stays readable instead of cramped.


What it replaces / what it doesn't

Replaces

console.log(...)
console.info(...)
console.warn(...)
console.error(...)
console.debug(...)
console.table(...)
console.dir(...)
console.group(...)
console.time(...)
// …and the rest of the console helpers mirrored on `log`
if (import.meta.env.DEV) {
  console.log(...);
}

Does not replace

  • Sentry / Datadog / browser monitoring
  • Pino / Winston / backend logging
  • Analytics or audit trails
  • Shipping logs to a server

Security

Helps prevent accidental exposure of debugging data through the production browser console.

It does not guarantee that secrets or personal data never reach the client. loggo only silences its own console output. It cannot protect values already present in frontend code, API responses, storage, or network traffic.


Browser support

Designed for modern Chromium, Firefox, and Safari DevTools. Uses console.* with %c styling and Intl.DateTimeFormat. No polyfills. No runtime dependencies.


Project scripts

npm run build   # emit dist (dev + prod + types)
npm run demo    # build + serve interactive demo

Links