Skip to main content

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

OptionTypeDefaultDescription
apiEndpointstringRequiredURL of the local collector
captureConsolebooleantrueCapture console.log/info/warn/error
captureErrorsbooleantrueCapture uncaught errors
captureNetworkbooleantrueCapture fetch/XHR requests
filterDomainsstring[][]Only capture network requests to these domains
excludeDomainsstring[][]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

OptionTypeDefaultDescription
allElementsbooleanfalseAdd source info to all elements (not just interactive ones)
rootDirstringprocess.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

  1. Start your frontend development server
  2. Open your app in the browser
  3. In VS Code, open SF Veritas: Show Console Logs
  4. In your browser console, type: console.log("Test from browser")
  5. The log should appear in the SF Veritas Console panel

Troubleshooting

Logs not appearing

  1. Check CORS: Ensure your local server allows requests from your frontend origin
  2. Check the endpoint: Verify apiEndpoint URL is correct
  3. Check browser console: Look for errors related to the recorder

CORS errors

If you see CORS errors in the browser console:

  1. The local SF Veritas server should handle CORS automatically
  2. Ensure you're using http://localhost:6776 not 127.0.0.1
  3. Check if another service is running on port 6776

Network requests not captured

  1. Verify captureNetwork: true is set
  2. Check if the domain is in excludeDomains
  3. Requests to the SF Veritas endpoint itself are not captured (to prevent loops)

Combining with Backend

When using both frontend and backend instrumentation:

  1. Frontend logs will show with source type "browser"
  2. Backend logs will show with your serviceIdentifier
  3. Use the service filter in the Console to separate them
  4. 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:

FrameworkEnvironment CheckDev CommandResult
Create React Appprocess.env.NODE_ENVnpm start✅ Active
Next.jsprocess.env.NODE_ENVnpm run dev✅ Active
Viteimport.meta.env.DEVnpm run dev✅ Active
AnyAnynpm run build❌ Not bundled
AnyAnyProduction deploy❌ Not loaded

Most frontend frameworks automatically set the appropriate development flag:

  • Create React App: Sets NODE_ENV=development during npm start
  • Next.js: Sets NODE_ENV=development during npm run dev
  • Vite: Sets import.meta.env.DEV=true during npm run dev

Next Steps