@vestig/next
v0.8.0
Published
First-class Next.js 15+ integration for vestig logging library. Zero boilerplate, automatic request correlation, full type safety.
Maintainers
Readme
@vestig/next
First-class structured logging for Next.js 15+ applications. Built on top of vestig, this package provides automatic request correlation, middleware integration, and seamless client/server logging.
Features
- Automatic Request Correlation - requestId, traceId, and spanId propagated across all logs
- Middleware Integration - Automatic request/response logging with timing
- Server Components -
getLogger()with Reactcache()for per-request loggers - Route Handlers -
withVestig()wrapper with full context - Server Actions -
vestigAction()for action logging - Client Components -
useLogger()hook with automatic server sync - PII Sanitization - All vestig sanitization presets work seamlessly
- Edge Runtime Compatible - Works in Edge middleware and Vercel Edge Functions
Installation
npm install @vestig/next vestig
# or
bun add @vestig/next vestigQuick Start
1. Add Middleware
// middleware.ts
import { createVestigMiddleware } from '@vestig/next/middleware'
export const middleware = createVestigMiddleware({
level: 'info',
skipPaths: ['/_next', '/favicon.ico'],
})
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}2. Wrap Your Layout
// app/layout.tsx
import { VestigProvider } from '@vestig/next/client'
import { getRequestContext } from '@vestig/next'
export default async function RootLayout({
children,
}: {
children: React.ReactNode
}) {
const ctx = await getRequestContext()
return (
<html>
<body>
<VestigProvider initialContext={ctx} endpoint="/api/vestig" namespace="client">
{children}
</VestigProvider>
</body>
</html>
)
}3. Add the Vestig API Route (Optional)
// app/api/vestig/route.ts
import { createVestigHandler } from '@vestig/next/route'
export const { GET, POST, DELETE } = createVestigHandler({
maxLogs: 500,
enableSSE: true,
})Usage
Server Components
// app/users/page.tsx
import { getLogger, getRequestContext } from '@vestig/next'
export default async function UsersPage() {
const log = await getLogger('users-page')
const ctx = await getRequestContext()
log.info('Rendering users page', { requestId: ctx.requestId })
const users = await fetchUsers()
log.debug('Users fetched', { count: users.length })
return <UserList users={users} />
}Route Handlers
// app/api/users/route.ts
import { withVestig } from '@vestig/next'
export const GET = withVestig(
async (request, { log, ctx, timing }) => {
log.debug('Fetching users from database')
const users = await db.users.findMany()
log.info('Users fetched', {
count: users.length,
duration: `${timing.elapsed().toFixed(2)}ms`,
})
return Response.json({
users,
meta: { requestId: ctx.requestId },
})
},
{ namespace: 'api:users', level: 'debug' }
)Client Components
'use client'
import { useLogger, useCorrelationContext } from '@vestig/next/client'
export default function UserProfile() {
const log = useLogger('user-profile')
const ctx = useCorrelationContext()
useEffect(() => {
log.info('Profile loaded', { requestId: ctx.requestId })
}, [log, ctx.requestId])
const handleClick = () => {
log.info('Button clicked', {
email: '[email protected]', // Auto-sanitized!
})
}
return <button onClick={handleClick}>Click me</button>
}Server Actions
// app/actions/user-actions.ts
'use server'
import { vestigAction } from '@vestig/next'
export const createUser = vestigAction(
async (data: { name: string; email: string }, { log, ctx }) => {
log.debug('Validating user data')
const user = await db.users.create({ data })
log.info('User created', { userId: user.id })
return user
},
{ namespace: 'actions:createUser' }
)API Reference
Middleware
createVestigMiddleware(options)
Create a middleware with custom configuration.
createVestigMiddleware({
level?: 'trace' | 'debug' | 'info' | 'warn' | 'error',
enabled?: boolean,
sanitize?: 'none' | 'minimal' | 'default' | 'gdpr' | 'hipaa' | 'pci-dss',
namespace?: string,
skipPaths?: string[],
timing?: boolean,
requestLogLevel?: LogLevel,
responseLogLevel?: LogLevel,
})Server Components
getLogger(namespace?)
Get a request-scoped logger in Server Components.
const log = await getLogger('my-component')
log.info('Hello world')getRequestContext()
Get the correlation context from the current request.
const ctx = await getRequestContext()
// { requestId, traceId, spanId, ... }Route Handlers
withVestig(handler, options)
Wrap a route handler with automatic logging.
export const GET = withVestig(
async (request, { log, ctx, timing, params }) => {
// Your handler logic
return Response.json({ data })
},
{
namespace?: string,
level?: LogLevel,
sanitize?: SanitizePreset,
logRequest?: boolean,
logResponse?: boolean,
}
)Client Components
useLogger(namespace?)
Get a logger instance in Client Components. No useMemo needed - the hook returns a stable reference.
const log = useLogger('my-component')useCorrelationContext()
Get the correlation context passed from the server.
const ctx = useCorrelationContext()
// { requestId, traceId, spanId }VestigProvider Props
<VestigProvider
initialContext={ctx} // From getRequestContext()
endpoint="/api/vestig" // Where to send client logs
namespace="client" // Base namespace for client logs
level="info" // Minimum log level
sanitize="default" // PII sanitization preset
batchSize={10} // Batch size for HTTP transport
flushInterval={2000} // Flush interval in ms
>Log Levels
All vestig log levels are supported:
trace- Most verbose, for detailed debuggingdebug- Debug informationinfo- General informationwarn- Warning messageserror- Error messages
PII Sanitization
All vestig sanitization presets work automatically:
none- No sanitizationminimal- Passwords onlydefault- Passwords, credit cards, SSNsgdpr- EU GDPR compliancehipaa- Healthcare compliancepci-dss- Payment card compliance
License
MIT
