xiaohongshu
xiaohongshu
axiom
Implements structured logging and observability with Axiom for serverless applications. Use when adding logging, tracing, and Web Vitals monitoring to Next.js and Vercel applications.
Full skill instructions
Observability platform for logs, metrics, and traces. Native Vercel integration with structured logging for Next.js applications.
npm install @axiomhq/js @axiomhq/logging @axiomhq/nextjs @axiomhq/react
// lib/axiom/client.ts
import { Axiom } from '@axiomhq/js';
export const axiom = new Axiom({
token: process.env.AXIOM_TOKEN!,
orgId: process.env.AXIOM_ORG_ID,
});
// lib/axiom/logger.ts
import { Logger, ConsoleTransport, AxiomJSTransport } from '@axiomhq/logging';
import { nextJsFormatters } from '@axiomhq/nextjs';
import { axiom } from './client';
export const logger = new Logger({
transports: [
new AxiomJSTransport({
axiom,
dataset: process.env.AXIOM_DATASET!,
}),
new ConsoleTransport(),
],
formatters: nextJsFormatters,
});
// lib/axiom/route.ts
import { createAxiomRouteHandler } from '@axiomhq/nextjs';
import { axiom } from './client';
import { logger } from './logger';
export const axiomRouteHandler = createAxiomRouteHandler({
axiom,
logger,
dataset: process.env.AXIOM_DATASET!,
});
// app/api/axiom/route.ts
import { axiomRouteHandler } from '@/lib/axiom/route';
export const POST = axiomRouteHandler;
// app/page.tsx
import { logger } from '@/lib/axiom/logger';
export default async function Page() {
logger.info('Page rendered', { page: 'home' });
try {
const data = await fetchData();
logger.debug('Data fetched', { count: data.length });
return <div>{/* render */}</div>;
} catch (error) {
logger.error('Failed to fetch data', { error });
throw error;
} finally {
await logger.flush();
}
}
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { logger } from '@/lib/axiom/logger';
export async function POST(request: NextRequest) {
const body = await request.json();
logger.info('Creating user', {
email: body.email,
source: request.headers.get('referer'),
});
try {
const user = await createUser(body);
logger.info('User created', { userId: user.id });
return NextResponse.json(user);
} catch (error) {
logger.error('User creation failed', {
error: error instanceof Error ? error.message : 'Unknown error',
email: body.email,
});
return NextResponse.json({ error: 'Failed' }, { status: 500 });
} finally {
await logger.flush();
}
}
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { logger } from '@/lib/axiom/logger';
export async function middleware(request: NextRequest) {
const start = Date.now();
logger.info('Request started', {
path: request.nextUrl.pathname,
method: request.method,
});
const response = NextResponse.next();
logger.info('Request completed', {
path: request.nextUrl.pathname,
duration: Date.now() - start,
});
await logger.flush();
return response;
}
// app/providers.tsx
'use client';
import { AxiomWebVitals } from '@axiomhq/react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<>
<AxiomWebVitals />
{children}
</>
);
}
Send logs through your API to avoid exposing tokens:
// lib/axiom/client-logger.ts
class ClientLogger {
private queue: Array<{ level: string; message: string; data?: object }> = [];
log(level: string, message: string, data?: object) {
this.queue.push({ level, message, data });
}
info(message: string, data?: object) {
this.log('info', message, data);
}
error(message: string, data?: object) {
this.log('error', message, data);
}
async flush() {
if (this.queue.length === 0) return;
const logs = [...this.queue];
this.queue = [];
await fetch('/api/axiom', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ logs }),
});
}
}
export const clientLogger = new ClientLogger();
'use client';
import { useEffect } from 'react';
import { clientLogger } from '@/lib/axiom/client-logger';
export function TrackableButton() {
const handleClick = () => {
clientLogger.info('Button clicked', { buttonId: 'cta' });
clientLogger.flush();
};
useEffect(() => {
clientLogger.info('Component mounted');
return () => {
clientLogger.info('Component unmounted');
clientLogger.flush();
};
}, []);
return <button onClick={handleClick}>Click me</button>;
}
Automatic Core Web Vitals tracking:
// app/layout.tsx
import { AxiomWebVitals } from '@axiomhq/react';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<AxiomWebVitals />
{children}
</body>
</html>
);
}
The older next-axiom package is still supported:
npm install next-axiom
// next.config.js
const { withAxiom } = require('next-axiom');
module.exports = withAxiom({
// your next config
});
import { Logger } from 'next-axiom';
export default async function Page() {
const log = new Logger();
log.info('Page rendered');
await log.flush();
return <div>Content</div>;
}
'use client';
import { useLogger } from 'next-axiom';
export function ClientComponent() {
const log = useLogger();
const handleClick = () => {
log.info('Button clicked');
};
return <button onClick={handleClick}>Click</button>;
}
function createRequestLogger(request: NextRequest) {
return {
info: (message: string, data?: object) => {
logger.info(message, {
...data,
requestId: request.headers.get('x-request-id'),
path: request.nextUrl.pathname,
method: request.method,
userAgent: request.headers.get('user-agent'),
});
},
error: (message: string, data?: object) => {
logger.error(message, {
...data,
requestId: request.headers.get('x-request-id'),
path: request.nextUrl.pathname,
});
},
};
}
async function withTiming<T>(
name: string,
fn: () => Promise<T>
): Promise<T> {
const start = Date.now();
try {
const result = await fn();
logger.info(`${name} completed`, {
duration: Date.now() - start,
success: true,
});
return result;
} catch (error) {
logger.error(`${name} failed`, {
duration: Date.now() - start,
error: error instanceof Error ? error.message : 'Unknown',
});
throw error;
}
}
// Usage
const users = await withTiming('fetchUsers', () => db.user.findMany());
function logError(error: unknown, context?: object) {
if (error instanceof Error) {
logger.error(error.message, {
...context,
name: error.name,
stack: error.stack,
cause: error.cause,
});
} else {
logger.error('Unknown error', {
...context,
error: String(error),
});
}
}
Enable the Axiom integration in Vercel for automatic log drains:
console.log, console.error, etc. are automatically sentAXIOM_TOKEN=xaat-xxxxxxxx
AXIOM_ORG_ID=your-org-id
AXIOM_DATASET=your-dataset
# For next-axiom
NEXT_PUBLIC_AXIOM_INGEST_ENDPOINT=https://api.axiom.co/v1/datasets/your-dataset/ingest
// Recent errors
dataset
| where level == "error"
| order by _time desc
| limit 100
// Request latency by path
dataset
| where message == "Request completed"
| summarize avg(duration), p95(duration), count() by path
| order by count_ desc
// Errors by type
dataset
| where level == "error"
| summarize count() by ['error.name']
| order by count_ desc
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience