Tag your logs with scopes, filter them in real time, and watch them stream into a sleek in-page panel — without touching DevTools.
No dependencies. Framework agnostic. Zero cost in production.
npm install @bajzik/scoped-console
# or
pnpm add @bajzik/scoped-consoleInit once in your entry point:
import { initConsole } from '@bajzik/scoped-console'
initConsole()Then create a logger per file:
import { useLogger } from '@bajzik/scoped-console'
const logger = useLogger('UserProfile')
logger.log('mounted')
logger.info('fetching user', id)
logger.warn('slow response')
logger.error('request failed', err)
logger.debug('raw payload', data)Logs appear in both DevTools and the in-page panel, tagged with the scope name.
// main.js
import { initConsole } from '@bajzik/scoped-console'
initConsole()
new Vue({ render: h => h(App) }).$mount('#app')// OrderView.vue
import { useLogger } from '@bajzik/scoped-console'
const logger = useLogger('OrderView')
export default {
mounted() { logger.log('mounted') },
methods: {
async fetchOrder(id) {
logger.info('fetching', id)
try {
const order = await this.$http.get(`/orders/${id}`)
logger.log('loaded', order)
} catch (err) {
logger.error('failed', err)
}
}
}
}// main.ts
import { initConsole } from '@bajzik/scoped-console'
initConsole()
createApp(App).mount('#app')// UserProfile.vue
import { useLogger } from '@bajzik/scoped-console'
const logger = useLogger('UserProfile')
async function fetchUser(id: string) {
logger.info('fetching', id)
try {
await userStore.fetch(id)
logger.log('done')
} catch (err) {
logger.error('failed', err)
}
}The panel renders at the bottom of the page, full width. It has three sections:
- Scopes — every file that called
useLoggerappears as a tab. Click to toggle. - Levels — filter by
log,info,warn,error,debug. - Output — scrollable log stream. Text is selectable for copying.
The collapsed state shows a small tab in the bottom-right corner with badge counts per level. All state persists to localStorage.
In production builds the library is automatically replaced with no-ops — initConsole and useLogger do nothing and add zero bytes to your bundle. This works automatically in Vite, webpack 5, Rollup, and esbuild via package export conditions. No config needed.
For best results, add the package to devDependencies:
npm install --save-dev @bajzik/scoped-consoleuseLogger('component:UserProfile')
useLogger('store:cart')
useLogger('service:api')initConsole(config?) — initialize. Call before anything else. config.mount defaults to 'body'.
useLogger(scope) — returns a scoped logger with log, info, warn, error, debug methods.
destroyConsole() — restore original console and remove the panel.
If your project uses moduleResolution: node, add to tsconfig.json:
{
"compilerOptions": {
"paths": {
"@bajzik/scoped-console": ["node_modules/@bajzik/scoped-console/dist/development/index.d.ts"]
}
}
}- First stable release
- Collapsed panel now right-aligned instead of full width
- Collapsed panel hides resize handle
- Badge counts now include logs from popped-out scope panels
- Event isolation — clicks inside console panel no longer trigger host app event listeners
- Removed duplicate type definitions — consolidated
LogLevelandScopedLoggertypes - Removed unused
getCallerFilefunction from stack parser - Removed all code comments for cleaner codebase
- Added comprehensive test coverage (76 tests)
- Added npm repository metadata
- Improved stack trace parsing — removed
<anonymous>from internal frame filtering for more accurate source location detection
- Encapsulated panel UI in shadow DOM to prevent style conflicts with host application
- Added line and column tracking to log entries — each log now shows the exact source line and column where it was called
- Enhanced object/array visualization with DevTools-like syntax highlighting — objects and arrays are displayed with colored keys, strings, numbers, and booleans for better readability
- Added file column to log output — shows the source file path where
useLoggerwas called, detected automatically via stack trace parsing - Added scope colors — each scope gets a unique consistent color derived from its name, visible on scope tabs and log entries
- Added resizable columns — drag column dividers to resize time, level, scope and file columns, sizes persist to localStorage
- Production build stubs via package export conditions — zero bundle cost in production builds with no config required in Vite, webpack 5, Rollup, and esbuild
- Replaced
defineScopewithuseLogger— returns a scoped logger object that re-asserts the scope before every call, fixing async timing issues in reactive frameworks
- Initial release — scoped console logging, in-page panel, scope and level filtering, persistent state via localStorage
MIT © Jakub Bajzath
