Integrations Monorepo — Developer Guide
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. 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. 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. Development Workflow
3.1 The Full Flow
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.
- Go to Actions → Publish Package
- Click Run workflow
- Enter the package name (e.g.,
observability) - Select version bump:
patch|minor|major - Click Run
The workflow automatically:
- Runs tests for the package
- Builds the package
- Bumps the version (you don't type "1.2.3" — just select "patch")
- Publishes to GitHub Packages
- Commits version bump to main
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. 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. 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 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 Resources
- SPPLT-19317 — Scaffold integrations repo
- SPPLT-18766 — ChurnZero extraction
- GitHub: solidprofessorhub/integrations