SP

Integrations

Third-Party Service Packages
Repo: solidprofessorhub/integrations Status: Active Audience: All frontend teams
Infrastructure

Integrations Monorepo — Developer Guide

Ticket: SPPLT-19317 | Shared packages for third-party service integrations

Wrap third-party SDKs with SolidProfessor policies. The integrations repo provides @solidprofessorhub/* packages that enforce our configuration standards (PII scrubbing, no tracing, consistent user context) so consuming apps don't need to know the details.

§1 Why This Repo?

1. Purpose

Third-party integrations (Sentry, LaunchDarkly, Segment, etc.) are consumed by multiple apps — Library, platform-access, and future MFEs. They don't belong to any one app's monorepo.

Concern Decision
Ownership boundary Integrations are shared infrastructure, not app-specific code
Publish independence Packages publish to npm; app monorepos use internal workspace deps
Existing pattern Matches auth, http, types, shared-components
§2 Repository Structure

2. Structure

integrations/
├── packages/
│   ├── observability/      → @solidprofessorhub/observability (Sentry)
│   ├── feature-flags/      → @solidprofessorhub/feature-flags (LaunchDarkly)
│   ├── analytics/          → @solidprofessorhub/analytics (Segment)
│   ├── customer-success/   → @solidprofessorhub/customer-success (ChurnZero)
│   └── ...
├── package.json            # workspace root
├── tsconfig.base.json      # shared TS config
├── vitest.config.ts        # test config
└── .github/workflows/
    └── publish.yml         # publish pipeline

2.1 Current Packages

Package Third-Party Status
@solidprofessorhub/observability Sentry Ready
@solidprofessorhub/feature-flags LaunchDarkly Planned
@solidprofessorhub/analytics Segment Planned
@solidprofessorhub/customer-success ChurnZero Planned
§3 Dev Workflow

3. Development Workflow

3.1 The Full Flow

1. Develop locally
2. Open PR
3. CI runs tests
4. Merge to main
5. Publish via Actions

3.2 Local Development

# Clone and setup
git clone https://github.com/solidprofessorhub/integrations.git
cd integrations
npm install

# Work on a specific package
npm run build --workspace=@solidprofessorhub/observability
npm run test --workspace=@solidprofessorhub/observability

# Run full CI check (lint + test + build)
npm run ci

3.3 Publishing

Devs do NOT run npm publish locally.

Use the GitHub Actions workflow instead — it enforces tests and creates an audit trail.

  1. Go to Actions → Publish Package
  2. Click Run workflow
  3. Enter the package name (e.g., observability)
  4. Select version bump: patch | minor | major
  5. Click Run

The workflow automatically:

3.4 Version Bumps

Current You Select Result When to Use
0.0.2 patch 0.0.3 Bug fixes, internal changes
0.0.2 minor 0.1.0 New features (backward compatible)
0.0.2 major 1.0.0 Breaking changes
§4 Using Packages

4. Consuming Packages

4.1 Configure npm

Add to .npmrc in your project:

@solidprofessorhub:registry=https://npm.pkg.github.com

For CI, also add auth (use secrets):

//npm.pkg.github.com/:_authToken=${NPM_TOKEN}

4.2 Install

npm install @solidprofessorhub/observability
npm install @solidprofessorhub/feature-flags
npm install @solidprofessorhub/analytics

4.3 Usage Examples

Observability (Sentry) — Vue 3 + Vite SPA:

import { initObservability } from '@solidprofessorhub/observability'

initObservability({
  dsn: import.meta.env.VITE_SENTRY_DSN,
  environment: import.meta.env.MODE,
  app
})

Observability (Sentry) — Nuxt 4:

// plugins/observability.client.ts
import { initObservability, captureVueError } from '@solidprofessorhub/observability'

export default defineNuxtPlugin((nuxtApp) => {
  initObservability({
    dsn: useRuntimeConfig().public.sentryDsn,
    environment: useRuntimeConfig().public.environment,
    app: nuxtApp.vueApp,
    attachErrorHandler: false  // Preserve Nuxt error handling
  })

  nuxtApp.hook('vue:error', (error, instance, info) => {
    captureVueError(error, instance, info)
  })
})

Feature Flags (LaunchDarkly):

import { initFeatureFlags, useFlag } from '@solidprofessorhub/feature-flags'

initFeatureFlags({
  clientSideId: import.meta.env.VITE_LD_CLIENT_ID,
  user: { key: userId, email, custom: { orgId } }
})

// In components
const showNewCheckout = useFlag('new-checkout-flow', false)

Analytics (Segment):

import { initAnalytics, track, identify } from '@solidprofessorhub/analytics'

initAnalytics({
  writeKey: import.meta.env.VITE_SEGMENT_WRITE_KEY
})

// Track events
track('Course Started', { courseId, courseName })
identify(userId, { email, plan: 'enterprise' })

Customer Success (ChurnZero):

import { initChurnZero, trackEvent, setContact } from '@solidprofessorhub/customer-success'

initChurnZero({
  appKey: import.meta.env.VITE_CHURNZERO_APP_KEY
})

setContact({ accountExternalId: orgId, contactExternalId: userId })
trackEvent('Completed Lesson', { lessonId, courseId })
§5 Policy Enforcement

5. Built-in Policies

Packages encode SolidProfessor policies so consuming apps don't need to know the details:

Package Policy How Enforced
observability No Sentry tracing Omits browserTracingIntegration (Tempo is trace system)
observability PII scrubbing beforeSend hook strips query strings from URLs
observability Filter extension noise denyUrls blocks chrome-extension://
feature-flags Consistent user context Requires user.key on init
analytics No PII in events Validates event properties
customer-success Account-level tracking Requires accountExternalId

Why this matters: Library and platform-access both use Sentry. Without the shared package, each app would need to implement PII scrubbing independently — and one might forget.

§6 Environment Variables

6. Environment Variables Reference

Package Vite Env Var Nuxt Env Var
observability VITE_SENTRY_DSN NUXT_PUBLIC_SENTRY_DSN
feature-flags VITE_LD_CLIENT_ID NUXT_PUBLIC_LD_CLIENT_ID
analytics VITE_SEGMENT_WRITE_KEY NUXT_PUBLIC_SEGMENT_WRITE_KEY
customer-success VITE_CHURNZERO_APP_KEY NUXT_PUBLIC_CHURNZERO_APP_KEY

All secrets should be managed via Doppler and injected at build time.

§7 Related

7. Related Resources