Frontend Setup: JavaScript/TypeScript
This guide walks you through instrumenting a frontend application with the SF Veritas Recorder SDK.
Installation
Install the Recorder package:
npm install @sailfish-ai/recorder
Or with yarn:
yarn add @sailfish-ai/recorder
Basic Setup
Add the following to your application's entry point (e.g., index.tsx, main.tsx). The key is to wrap the initialization in an environment check so it only runs during local development:
// Initialize SF Veritas Recorder ONLY in development mode
if (process.env.NODE_ENV === 'development') {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
});
});
}
// Your application code continues below...
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(<App />);
Vanilla JavaScript
// Initialize only in development
if (process.env.NODE_ENV === 'development') {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
});
});
}
// Your application code...
console.log('Application started'); // This will appear in SF Veritas
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
apiEndpoint | string | Required | URL of the local collector |
captureConsole | boolean | true | Capture console.log/info/warn/error |
captureErrors | boolean | true | Capture uncaught errors |
captureNetwork | boolean | true | Capture fetch/XHR requests |
filterDomains | string[] | [] | Only capture network requests to these domains |
excludeDomains | string[] | [] | Exclude network requests to these domains |
Advanced Configuration
Domain Filtering
Filter network request capture by domain:
if (process.env.NODE_ENV === 'development') {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
// Only capture requests to your API
filterDomains: ['api.example.com', 'localhost:3001'],
// Exclude third-party services
excludeDomains: ['analytics.google.com', 'sentry.io'],
});
});
}
Source File Tracking
To map UI components back to their source files, add the Babel plugin to your build configuration. This is required for coverage analysis and component tracing to work properly.
Vite
// vite.config.ts
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
react({
babel: {
plugins: [
['@sailfish-ai/recorder/babel-plugin', { allElements: true }],
],
},
}),
],
});
Next.js
// babel.config.js
module.exports = {
presets: ['next/babel'],
plugins:
process.env.NODE_ENV === 'development'
? [['@sailfish-ai/recorder/babel-plugin', { allElements: true }]]
: [],
};
Plugin Options
| Option | Type | Default | Description |
|---|---|---|---|
allElements | boolean | false | Add source info to all elements (not just interactive ones) |
rootDir | string | process.cwd() | Root directory to strip from file paths |
Framework Examples
Create React App
// src/index.tsx
// Initialize SF Veritas only in development
if (process.env.NODE_ENV === 'development') {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
});
});
}
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Next.js (App Router)
// app/layout.tsx
'use client';
import { useEffect } from 'react';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
});
});
}
}, []);
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Next.js (Pages Router)
// pages/_app.tsx
import { useEffect } from 'react';
import type { AppProps } from 'next/app';
function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
});
});
}
}, []);
return <Component {...pageProps} />;
}
export default MyApp;
Vite
// src/main.tsx
// Vite uses import.meta.env.DEV for development detection
if (import.meta.env.DEV) {
import('@sailfish-ai/recorder').then(({ initRecorder }) => {
initRecorder({
apiEndpoint: 'http://localhost:6776/graphql/',
captureConsole: true,
captureErrors: true,
captureNetwork: true,
});
});
}
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Verifying the Setup
- Start your frontend development server
- Open your app in the browser
- In VS Code, open
SF Veritas: Show Console Logs - In your browser console, type:
console.log("Test from browser") - The log should appear in the SF Veritas Console panel
Troubleshooting
Logs not appearing
- Check CORS: Ensure your local server allows requests from your frontend origin
- Check the endpoint: Verify
apiEndpointURL is correct - Check browser console: Look for errors related to the recorder
CORS errors
If you see CORS errors in the browser console:
- The local SF Veritas server should handle CORS automatically
- Ensure you're using
http://localhost:6776not127.0.0.1 - Check if another service is running on port 6776
Network requests not captured
- Verify
captureNetwork: trueis set - Check if the domain is in
excludeDomains - Requests to the SF Veritas endpoint itself are not captured (to prevent loops)
Combining with Backend
When using both frontend and backend instrumentation:
- Frontend logs will show with source type "browser"
- Backend logs will show with your
serviceIdentifier - Use the service filter in the Console to separate them
- Network requests from frontend to backend will be visible
Frontend (browser) ──────▶ Backend (user-service) ──────▶ Database
│ │
│ console.log │ console.log
▼ ▼
┌─────────────────────────────────────┐
│ SF Veritas Console │
│ [browser] Button clicked │
│ [user-service] Handling request │
│ [user-service] Query executed │
└─────────────────────────────────────┘
How It Works
The environment variable controls when SF Veritas Recorder is active:
| Framework | Environment Check | Dev Command | Result |
|---|---|---|---|
| Create React App | process.env.NODE_ENV | npm start | ✅ Active |
| Next.js | process.env.NODE_ENV | npm run dev | ✅ Active |
| Vite | import.meta.env.DEV | npm run dev | ✅ Active |
| Any | Any | npm run build | ❌ Not bundled |
| Any | Any | Production deploy | ❌ Not loaded |
Most frontend frameworks automatically set the appropriate development flag:
- Create React App: Sets
NODE_ENV=developmentduringnpm start - Next.js: Sets
NODE_ENV=developmentduringnpm run dev - Vite: Sets
import.meta.env.DEV=trueduringnpm run dev