Vite + React
Vite + React
Section titled “Vite + React”The Sentori dashboard itself is a Vite + React app and follows this recipe verbatim.
1. Install
Section titled “1. Install”bun add @goliapkg/sentori-react# orpnpm add @goliapkg/sentori-react2. Environment
Section titled “2. Environment”.env.production (or .env.local for dev):
VITE_SENTORI_TOKEN=st_pk_...VITE_SENTORI_RELEASE=myapp@1.2.3VITE_SENTORI_INGEST=https://ingest.sentori.golia.jpVite only exposes VITE_* variables to the browser bundle. Anything
else stays server-side.
3. Wire main.tsx
Section titled “3. Wire main.tsx”import { SentoriErrorBoundary, SentoriProvider } from '@goliapkg/sentori-react'import { StrictMode } from 'react'import { createRoot } from 'react-dom/client'
import App from './App'
const sentoriConfig = { token: import.meta.env.VITE_SENTORI_TOKEN, release: import.meta.env.VITE_SENTORI_RELEASE, environment: import.meta.env.MODE === 'production' ? 'prod' : 'dev', ingestUrl: import.meta.env.VITE_SENTORI_INGEST,}
createRoot(document.getElementById('root')!).render( <StrictMode> <SentoriProvider config={sentoriConfig}> <SentoriErrorBoundary fallback={<DashboardCrashed />}> <App /> </SentoriErrorBoundary> </SentoriProvider> </StrictMode>,)
function DashboardCrashed() { return ( <div role="alert"> <h2>Something went wrong</h2> <p>Refresh the page or contact support if it persists.</p> </div> )}<SentoriProvider> initialises the JS SDK (window error / unhandled
rejection hooks included) and exposes the capture API via context.
<SentoriErrorBoundary> catches anything thrown during render and
forwards it to the same SDK with tags.source = 'react.errorBoundary'.
4. Optional — route breadcrumbs
Section titled “4. Optional — route breadcrumbs”If you use react-router:
import { useSentoriRouter } from '@goliapkg/sentori-react/router'
export function Shell({ children }: { children: React.ReactNode }) { useSentoriRouter() return <>{children}</>}Mount once high in the tree (inside the Router and inside
SentoriProvider). Every pathname change becomes a nav breadcrumb.
5. Source maps
Section titled “5. Source maps”vite.config.ts:
import react from '@vitejs/plugin-react'import { defineConfig } from 'vite'
export default defineConfig({ plugins: [react()], build: { sourcemap: true, },})After bun run build, maps land in dist/assets/*.map. Upload from
CI:
sentori-cli upload sourcemap \ --release "myapp@$(git rev-parse --short HEAD)" \ --token "$SENTORI_TOKEN" \ --ingest-url "$SENTORI_INGEST_URL" \ dist/assets/6. CI example
Section titled “6. CI example”.github/workflows/deploy.yml:
name: Deployon: push: branches: [main]jobs: build-and-upload: runs-on: ubuntu-latest env: VITE_SENTORI_TOKEN: ${{ secrets.SENTORI_TOKEN }} VITE_SENTORI_RELEASE: myapp@${{ github.sha }} VITE_SENTORI_INGEST: https://ingest.sentori.golia.jp SENTORI_TOKEN: ${{ secrets.SENTORI_TOKEN }} SENTORI_INGEST_URL: https://ingest.sentori.golia.jp steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile - run: bun run build - name: Install sentori-cli run: | curl -fsSL https://cdn.sentori.golia.jp/install-cli.sh | bash echo "$HOME/.sentori/bin" >> "$GITHUB_PATH" - name: Upload sourcemaps run: | sentori-cli upload sourcemap \ --release "myapp@${{ github.sha }}" \ dist/assets/ # ... your deploy stepBundle size
Section titled “Bundle size”<SentoriProvider> + <SentoriErrorBoundary> together add about
4 KB gzip on top of an existing React + Vite bundle (measured on the
Sentori dashboard at 336 KB total, gzip 107 KB).