Logit
Logit is a flexible, zero-dependency logging utility designed for both browser and Node.js environments. It provides a powerful set of features including log levels, custom themes, remote logging, and scoped loggers, all while maintaining a tiny footprint.
Screenshot

What Problem Does Logit Solve?
Console logging is great for development but lacks structure for production apps. You need log levels, namespacing, remote logging, and environment-specific filtering—all without adding complexity or dependencies.
Without Logit:
// Unstructured, hard to filter, no remote logging
console.log('[API] User login:', user);
console.warn('[API] High memory usage:', usage);
// No way to disable logs in production
if (process.env.NODE_ENV !== 'production') {
console.log('Debug info');
}
// Manual remote logging setup
fetch('/api/logs', {
method: 'POST',
body: JSON.stringify({ level: 'error', message: error.message }),
});With Logit:
// Structured, filterable, styled output
import { Logit } from '@vielzeug/logit';
Logit.setPrefix('API');
Logit.info('User login:', user);
Logit.warn('High memory usage:', usage);
// Automatically respects log level
Logit.setLogLevel('warn'); // Debug/info logs now silent
// Automatic remote logging
Logit.setRemote({
handler: (type, ...args) => {
if (type === 'error') {
fetch('/api/logs', {
method: 'POST',
body: JSON.stringify({ type, args }),
});
}
},
logLevel: 'error',
});Comparison with Alternatives
| Feature | Logit | Winston | Pino | Console |
|---|---|---|---|---|
| TypeScript Support | ✅ First-class | ✅ Good | ✅ Good | ⚠️ Basic |
| Browser Support | ✅ Native | ❌ | ❌ | ✅ |
| Namespacing | ✅ Built-in | ⚠️ Manual | ⚠️ Child | ❌ |
| Remote Logging | ✅ Built-in | ✅ Transports | ✅ Streams | ❌ |
| Bundle Size (gzip) | 1.9 KB | ~50KB+ | ~12KB | 0KB |
| Node.js Support | ✅ | ✅ | ✅ | ✅ |
| Dependencies | 0 | 15+ | 5+ | N/A |
| Colored Output | ✅ Auto | ✅ | ✅ | ⚠️ Manual |
When to Use Logit
✅ Use Logit when you:
- Need isomorphic logging (browser + Node.js) with styled output
- Want namespace/prefix support for different modules
- Require remote logging capabilities
- Need log level filtering for production vs development
- Want zero dependencies for security and minimal bundle size
- Build full-stack TypeScript applications
- Need visual themes and customizable output formats
❌ Consider alternatives when you:
- Only need Node.js logging with file rotation (use Winston/Pino)
- Need advanced log rotation and file management
- Require high-throughput server logging (use Pino)
- Simple console.log is sufficient for your use case
🚀 Key Features
- Log Levels: Standard levels (debug, info, success, warn, error, trace, table) with filtering
- Isomorphic: Seamlessly works in both Browser (with CSS styling) and Node.js
- Namespacing: Add prefixes to logs to identify the source
- Remote Logging: Built-in support for sending logs to remote endpoints
- Themes & Variants: Customizable visual output (text, icon, symbol variants)
- Advanced Utilities: Built-in support for timing, grouping, tables, and assertions
- Environment Detection: Automatic production/development indicators
- Zero Dependencies: Lightweight, fast, and secure
- Type-safe: Full TypeScript support with proper type definitions
🏁 Quick Start
Installation
pnpm add @vielzeug/logitnpm install @vielzeug/logityarn add @vielzeug/logitBasic Usage
import { Logit } from '@vielzeug/logit';
// Standard log levels
Logit.debug('Debugging information', { userId: '123' });
Logit.info('System initialized');
Logit.success('Operation completed successfully');
Logit.warn('Memory usage high', { usage: '85%' });
Logit.error('Failed to fetch data', new Error('Network error'));
// Add namespace for different modules
Logit.setPrefix('API');
Logit.info('Request started', { url: '/users' });
// Change to database context
Logit.setPrefix('Database');
Logit.info('Connection established');
// Control log level globally
Logit.setLogLevel('warn'); // Only warn and error will show
// Advanced features
Logit.table([
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
]);
Logit.time('operation');
// ... do work ...
Logit.timeEnd('operation');Real-World Example: Full-Stack App
import { Logit } from '@vielzeug/logit';
// Configure for production
if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') {
Logit.setLogLevel('warn');
// Send errors to remote logging service
Logit.setRemote({
handler: async (type, ...args) => {
if (type === 'error') {
await fetch('/api/logs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
timestamp: new Date().toISOString(),
level: type,
prefix: Logit.getPrefix(),
args: args.map((arg) => (arg instanceof Error ? { message: arg.message, stack: arg.stack } : arg)),
}),
});
}
},
logLevel: 'error',
});
}
// Configure display options
Logit.initialise({
variant: 'symbol',
timestamp: true,
environment: true,
namespace: 'MyApp',
});
// Use throughout your application
Logit.setPrefix('Auth');
Logit.info('User logged in', { userId: user.id });
Logit.setPrefix('API');
Logit.warn('Rate limit approaching', { remaining: 10 });
Logit.setPrefix('Cache');
Logit.error('Cache connection failed', new Error('Redis timeout'));Framework Integration: React
import { Logit } from '@vielzeug/logit';
import { useEffect } from 'react';
function UserProfile({ userId }: { userId: string }) {
useEffect(() => {
Logit.setPrefix('UserProfile');
Logit.debug('Component mounted', { userId });
return () => {
Logit.debug('Component unmounted', { userId });
};
}, [userId]);
const handleClick = () => {
try {
// ... do something
Logit.setPrefix('UserProfile');
Logit.info('Button clicked', { userId });
} catch (error) {
Logit.setPrefix('UserProfile');
Logit.error('Action failed', error);
}
};
return <button onClick={handleClick}>Click me</button>;
}Framework Integration: Express
import express from 'express';
import { Logit } from '@vielzeug/logit';
const app = express();
Logit.setPrefix('Server');
// Request logging middleware
app.use((req, res, next) => {
Logit.setPrefix(`${req.method} ${req.path}`);
Logit.info('Request started', {
method: req.method,
path: req.path,
ip: req.ip,
});
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
Logit.setPrefix(`${req.method} ${req.path}`);
if (res.statusCode >= 400) {
Logit.error('Request failed', {
status: res.statusCode,
duration: `${duration}ms`,
});
} else {
Logit.info('Request completed', {
status: res.statusCode,
duration: `${duration}ms`,
});
}
});
next();
});
app.listen(3000, () => {
Logit.setPrefix('Server');
Logit.info('Server started', { port: 3000 });
});📚 Documentation
- Usage Guide: Installation, global configuration, and scoped loggers
- API Reference: Complete list of methods, levels, and handler options
- Examples: Patterns for remote logging, custom themes, and more
❓ FAQ
Is Logit production-ready?
Yes! Logit is used in production applications and has comprehensive test coverage.
How do I disable logs in production?
if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') {
Logit.setLogLevel('error'); // Only show errors
// or
Logit.setLogLevel('off'); // Disable all logs
}Can I send logs to multiple destinations?
The setRemote handler can call multiple services:
Logit.setRemote({
handler: async (type, ...args) => {
// Send to multiple destinations
await Promise.all([sendToSentry(type, args), sendToCloudWatch(type, args), writeToFile(type, args)]);
},
logLevel: 'error',
});How do I format log output?
Logit automatically formats output based on environment (browser CSS vs Node.js). Customize with variants:
Logit.setVariant('symbol');
// Output: 🅳, 🅸, 🅂, 🆆, 🅴Logit.setVariant('icon');
// Output: ☕, ℹ, ✔, ⚠, ✘Logit.setVariant('text');
// Output: DEBUG, INFO, SUCCESS, WARN, ERRORDoes Logit affect performance?
Minimal impact. When log level filters out messages, they're skipped before processing. For production, use setLogLevel('warn') or 'error'.
Can I use structured logging?
Yes! Pass objects as additional arguments:
Logit.info('User action', { userId: '123', action: 'login', duration: 250 });🐛 Troubleshooting
Logs not showing in browser
Problem
Console is empty.
Solution
Check log level:
// Make sure level allows your logs through
Logit.setLogLevel('debug'); // Show all logs
// Or check current level
console.log(Logit.getLevel());Colors not showing in browser
Problem
Logs appear plain in browser console.
Solution
Ensure you're using a modern browser. Most browsers support CSS styling in console.log. Check browser compatibility.
Remote handler not being called
Problem
Remote handler doesn't execute.
Solution
Ensure handler is set correctly and log level matches:
Logit.setRemote({
handler: async (type, ...args) => {
try {
console.log('Handler called:', type, args);
await sendToServer(type, args);
} catch (error) {
console.error('Failed to send log:', error);
}
},
logLevel: 'error', // Must match or be lower than the log type
});logLevel: 'error' // Must match or be lower than the log type });
TypeScript types not working
Problem: Types not properly inferred.
Solution: Import types explicitly:
import { Logit, type LogitOptions, type LogitType } from '@vielzeug/logit';
const options: LogitOptions = {
logLevel: 'info',
variant: 'symbol',
};
Logit.initialise(options);Namespace/prefix not showing
Problem: Logs don't show the namespace.
Solution: Ensure you've set a prefix:
Logit.setPrefix('MyModule');
Logit.info('This will show with [MyModule] prefix');🤝 Contributing
Found a bug or want to contribute? Check our GitHub repository.
📄 License
MIT © Helmuth Duarte
🔗 Useful Links
Tip: Logit is part of the Vielzeug ecosystem, which includes utilities for storage, HTTP clients, permissions, and more.