@sylphx/sdk 0.0.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,9 +5,11 @@
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue?logo=typescript)](https://www.typescriptlang.org/)
6
6
  [![docs](https://img.shields.io/badge/docs-sylphx.com%2Fdocs-green)](https://sylphx.com/docs)
7
7
 
8
- Complete SDK for integrating apps with the Sylphx Platform. Get auth, billing, analytics, AI, storage, and more with minimal setup.
8
+ Auth, billing, analytics, AI, storage, and more in one SDK.
9
9
 
10
- 📖 **Full documentation:** [sylphx.com/docs](https://sylphx.com/docs)
10
+ 📖 **Full docs:** [sylphx.com/docs](https://sylphx.com/docs)
11
+
12
+ ---
11
13
 
12
14
  ## Installation
13
15
 
@@ -15,32 +17,76 @@ Complete SDK for integrating apps with the Sylphx Platform. Get auth, billing, a
15
17
  npm install @sylphx/sdk
16
18
  # or
17
19
  pnpm add @sylphx/sdk
18
- # or
19
20
  bun add @sylphx/sdk
20
21
  ```
21
22
 
23
+ ---
24
+
22
25
  ## Quick Start (Next.js)
23
26
 
24
27
  ### 1. Environment Variables
25
28
 
29
+ Two keys from your [Platform Console](https://sylphx.com/console):
30
+
26
31
  ```bash
27
32
  # .env.local
28
- SYLPHX_APP_ID=your-app-slug
29
- SYLPHX_APP_SECRET=sk_dev_xxxxxxxxxxxx
30
- SYLPHX_PLATFORM_URL=https://sylphx.com
33
+ SYLPHX_SECRET_KEY=sk_dev_xxxxxxxxxxxxxxxxxxxx # server-only
34
+ NEXT_PUBLIC_SYLPHX_APP_ID=app_dev_xxxxxxxxxxxx # safe to expose
31
35
  ```
32
36
 
33
- ### 2. Add Provider to Layout
37
+ That's it. No other config needed.
38
+
39
+ > **Key formats**
40
+ > - `sk_dev_*` / `sk_stg_*` / `sk_prod_*` — Secret key (server only, never expose)
41
+ > - `app_dev_*` / `app_stg_*` / `app_prod_*` — App ID (safe for client-side)
42
+ >
43
+ > Get both from **Console → Your App → API Keys**.
44
+
45
+ ---
46
+
47
+ ### 2. Middleware
48
+
49
+ Handles auth routes (`/auth/callback`, `/auth/signout`) and route protection automatically.
50
+
51
+ ```ts
52
+ // middleware.ts
53
+ import { createSylphxMiddleware } from '@sylphx/sdk/nextjs'
54
+
55
+ export default createSylphxMiddleware({
56
+ publicRoutes: ['/', '/about', '/pricing', '/login'],
57
+ })
58
+
59
+ export const config = {
60
+ matcher: ['/((?!_next|.*\\..*).*)', '/'],
61
+ }
62
+ ```
63
+
64
+ No manual `/api/auth/*` routes needed — the middleware handles everything.
65
+
66
+ ---
67
+
68
+ ### 3. Root Layout
69
+
70
+ Fetch config server-side once, pass to the provider:
34
71
 
35
72
  ```tsx
36
73
  // app/layout.tsx
74
+ import { getAppConfig } from '@sylphx/sdk/server'
37
75
  import { SylphxProvider } from '@sylphx/sdk/react'
38
76
 
39
- export default function RootLayout({ children }) {
77
+ export default async function RootLayout({ children }: { children: React.ReactNode }) {
78
+ const config = await getAppConfig({
79
+ secretKey: process.env.SYLPHX_SECRET_KEY!,
80
+ appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
81
+ })
82
+
40
83
  return (
41
84
  <html>
42
85
  <body>
43
- <SylphxProvider appId={process.env.NEXT_PUBLIC_SYLPHX_APP_ID!}>
86
+ <SylphxProvider
87
+ config={config}
88
+ appId={process.env.NEXT_PUBLIC_SYLPHX_APP_ID!}
89
+ >
44
90
  {children}
45
91
  </SylphxProvider>
46
92
  </body>
@@ -49,384 +95,325 @@ export default function RootLayout({ children }) {
49
95
  }
50
96
  ```
51
97
 
52
- ### 3. Add Middleware
98
+ ---
53
99
 
54
- ```ts
55
- // middleware.ts
56
- import { authMiddleware } from '@sylphx/sdk/nextjs'
100
+ ### 4. Protect Pages (Server Components)
57
101
 
58
- export default authMiddleware({
59
- appId: process.env.SYLPHX_APP_ID!,
60
- publicRoutes: ['/', '/login', '/signup', '/api/auth/callback'],
61
- })
102
+ ```tsx
103
+ // app/dashboard/page.tsx
104
+ import { currentUser } from '@sylphx/sdk/nextjs'
105
+ import { redirect } from 'next/navigation'
62
106
 
63
- export const config = {
64
- matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
107
+ export default async function Dashboard() {
108
+ const user = await currentUser()
109
+ if (!user) redirect('/login')
110
+
111
+ return <h1>Hello, {user.name}</h1>
65
112
  }
66
113
  ```
67
114
 
68
- ### 4. Create Callback Route
69
-
70
- ```ts
71
- // app/api/auth/callback/route.ts
72
- import { handleCallback } from '@sylphx/sdk/nextjs'
73
-
74
- export const GET = handleCallback()
75
- ```
115
+ ---
76
116
 
77
- ### 5. Use the SDK
117
+ ### 5. Auth UI (Client Components)
78
118
 
79
119
  ```tsx
80
- // app/page.tsx
81
120
  'use client'
121
+ import { useUser, SignedIn, SignedOut, UserButton } from '@sylphx/sdk/react'
82
122
 
83
- import { useUser, SignedIn, SignedOut, SignIn, UserButton } from '@sylphx/sdk/react'
84
-
85
- export default function Home() {
123
+ export default function Header() {
86
124
  const { user } = useUser()
87
125
 
88
126
  return (
89
- <div>
127
+ <header>
90
128
  <SignedOut>
91
- <SignIn mode="embedded" afterSignInUrl="/dashboard" />
129
+ <a href="/login">Sign in</a>
92
130
  </SignedOut>
93
-
94
131
  <SignedIn>
95
- <h1>Hello, {user?.name}</h1>
96
- <UserButton />
132
+ <span>Hello, {user?.name}</span>
133
+ <UserButton afterSignOutUrl="/" />
97
134
  </SignedIn>
98
- </div>
135
+ </header>
99
136
  )
100
137
  }
101
138
  ```
102
139
 
103
140
  ---
104
141
 
105
- ## React Hooks
142
+ ## Server-Side
106
143
 
107
- ### Authentication
144
+ ### Get Current User
108
145
 
109
146
  ```tsx
110
- import { useUser, useAuth, useSession } from '@sylphx/sdk/react'
147
+ import { auth, currentUser, currentUserId } from '@sylphx/sdk/nextjs'
111
148
 
112
- // Get current user
113
- const { user, isLoading, isSignedIn } = useUser()
149
+ // Full auth state
150
+ const { userId, user, sessionToken } = await auth()
114
151
 
115
- // Auth actions
116
- const { signIn, signUp, signOut, resetPassword } = useAuth()
152
+ // Just the user object (null if not signed in)
153
+ const user = await currentUser()
117
154
 
118
- // Session management
119
- const { session, refresh } = useSession()
155
+ // Just the user ID
156
+ const userId = await currentUserId()
120
157
  ```
121
158
 
122
- ### Billing
123
-
124
- ```tsx
125
- import { useBilling } from '@sylphx/sdk/react'
159
+ ### Server API Client
126
160
 
127
- const { subscription, isPremium, plans, createCheckout, openPortal } = useBilling()
161
+ ```ts
162
+ import { createServerClient } from '@sylphx/sdk/server'
128
163
 
129
- // Check premium status
130
- if (isPremium) {
131
- // Show premium features
132
- }
164
+ const client = createServerClient({
165
+ secretKey: process.env.SYLPHX_SECRET_KEY!,
166
+ })
133
167
 
134
- // Start checkout (returns URL to redirect to)
135
- const checkoutUrl = await createCheckout('pro', 'monthly')
136
- window.location.href = checkoutUrl
168
+ // GET /billing/plans
169
+ const plans = await client.GET('/billing/plans')
137
170
 
138
- // Open billing portal to manage subscription
139
- await openPortal()
171
+ // POST /analytics/track
172
+ await client.POST('/analytics/track', {
173
+ body: { events: [{ event: 'purchase', properties: { amount: 99 } }] },
174
+ })
140
175
  ```
141
176
 
142
- ### Analytics
143
-
144
- ```tsx
145
- import { useAnalytics } from '@sylphx/sdk/react'
146
-
147
- const { track, identify, pageView } = useAnalytics()
148
-
149
- // Track custom event
150
- track('button_clicked', { buttonId: 'signup' })
177
+ ### Prefetch App Config
151
178
 
152
- // Identify user
153
- identify({ name: 'John', email: 'john@example.com' })
179
+ ```ts
180
+ import {
181
+ getAppConfig, // All config in one call (recommended)
182
+ getPlans, // Billing plans
183
+ getFeatureFlags, // Feature flag definitions
184
+ getConsentTypes, // GDPR consent config
185
+ } from '@sylphx/sdk/server'
186
+
187
+ const config = await getAppConfig({
188
+ secretKey: process.env.SYLPHX_SECRET_KEY!,
189
+ appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
190
+ })
191
+ // config.plans, config.featureFlags, config.oauthProviders, config.consentTypes
154
192
  ```
155
193
 
156
- ### AI
194
+ ### Verify Webhooks
157
195
 
158
- ```tsx
159
- import { useChat, useCompletion, useEmbedding } from '@sylphx/sdk/react'
196
+ ```ts
197
+ import { verifyWebhook } from '@sylphx/sdk/server'
160
198
 
161
- // Chat completion
162
- const { messages, send, isLoading } = useChat({
163
- model: 'anthropic/claude-3.5-sonnet',
164
- })
199
+ export async function POST(request: Request) {
200
+ const body = await request.text()
165
201
 
166
- // Text completion
167
- const { complete, completion, isLoading } = useCompletion()
202
+ const result = await verifyWebhook({
203
+ payload: body,
204
+ signatureHeader: request.headers.get('x-webhook-signature'),
205
+ secret: process.env.SYLPHX_SECRET_KEY!,
206
+ })
168
207
 
169
- // Embeddings
170
- const { embed, embedding } = useEmbedding()
171
- ```
208
+ if (!result.valid) {
209
+ return new Response('Unauthorized', { status: 401 })
210
+ }
172
211
 
173
- ### Database
212
+ const { event, data } = result.payload!
213
+ // handle event...
214
+ return Response.json({ received: true })
215
+ }
216
+ ```
174
217
 
175
- Server-side access to your Sylphx managed Postgres database with full type safety.
218
+ Or use the handler factory:
176
219
 
177
220
  ```ts
178
- import { createSylphx } from '@sylphx/sdk'
179
-
180
- const sylphx = createSylphx({
181
- appId: process.env.SYLPHX_APP_ID!,
182
- appSecret: process.env.SYLPHX_APP_SECRET!,
221
+ import { createWebhookHandler } from '@sylphx/sdk/server'
222
+
223
+ export const POST = createWebhookHandler({
224
+ secret: process.env.SYLPHX_SECRET_KEY!,
225
+ handlers: {
226
+ 'user.created': async (data) => { /* ... */ },
227
+ 'subscription.updated': async (data) => { /* ... */ },
228
+ },
183
229
  })
230
+ ```
184
231
 
185
- // Execute raw SQL (returns typed rows)
186
- const users = await sylphx.database.query<{ id: string; email: string }>(
187
- 'SELECT id, email FROM users WHERE active = true LIMIT $1',
188
- [100],
189
- )
232
+ ### JWT Verification
190
233
 
191
- // Run migrations (idempotent)
192
- await sylphx.database.migrate()
234
+ ```ts
235
+ import { verifyAccessToken } from '@sylphx/sdk/server'
193
236
 
194
- // Get connection string for ORMs (Prisma, Drizzle, etc.)
195
- const connectionUrl = sylphx.database.connectionUrl()
237
+ const payload = await verifyAccessToken(token, {
238
+ secretKey: process.env.SYLPHX_SECRET_KEY!,
239
+ })
240
+ // payload.sub, payload.email, payload.role, payload.app_id
196
241
  ```
197
242
 
198
- > **Tip:** Use the connection URL with your favourite ORM for full type-safety.
199
- > The platform manages connection pooling automatically.
200
-
201
- ### Storage
243
+ ---
202
244
 
203
- ```tsx
204
- import { useStorage } from '@sylphx/sdk/react'
245
+ ## React Hooks
205
246
 
206
- const { upload, uploadAvatar, deleteFile, getUrl, isUploading, progress } = useStorage()
247
+ ### Auth
207
248
 
208
- // Upload avatar (special handling for profile images)
209
- const avatarUrl = await uploadAvatar(file)
249
+ ```tsx
250
+ import { useUser, useAuth } from '@sylphx/sdk/react'
210
251
 
211
- // Upload file with optional path
212
- const fileUrl = await upload(file, { path: 'documents/' })
252
+ const { user, isLoading, isSignedIn } = useUser()
253
+ const { signIn, signUp, signOut, forgotPassword } = useAuth()
213
254
 
214
- // Show progress while uploading
215
- if (isUploading) {
216
- console.log(`Upload progress: ${progress}%`)
217
- }
255
+ await signIn({ email: 'user@example.com', password: '...' })
256
+ await signOut()
218
257
  ```
219
258
 
220
- ### More Hooks
259
+ ### Billing
221
260
 
222
261
  ```tsx
223
- // Feature flags - check if features are enabled
224
- import { useFeatureFlag, useFeatureFlags } from '@sylphx/sdk/react'
225
- const { isEnabled, variant, isLoading } = useFeatureFlag('new-dashboard')
226
- const flags = useFeatureFlags(['dark-mode', 'beta-features'])
227
-
228
- // Error tracking - capture exceptions and breadcrumbs
229
- import { useErrorTracking } from '@sylphx/sdk/react'
230
- const { captureException, addBreadcrumb, setRoute } = useErrorTracking()
231
-
232
- // Referrals - referral program management
233
- import { useReferral } from '@sylphx/sdk/react'
262
+ import { useBilling } from '@sylphx/sdk/react'
234
263
 
235
- // Privacy/consent - GDPR consent management
236
- import { useConsent } from '@sylphx/sdk/react'
264
+ const { subscription, isPremium, plans, createCheckout, openPortal } = useBilling()
237
265
 
238
- // Background jobs - async task management
239
- import { useJobs } from '@sylphx/sdk/react'
266
+ // Check access
267
+ if (!isPremium) return <UpgradePrompt />
240
268
 
241
- // Organizations - multi-tenant support
242
- import { useOrganization } from '@sylphx/sdk/react'
269
+ // Start checkout
270
+ const url = await createCheckout('pro', 'monthly')
271
+ window.location.href = url
243
272
 
244
- // Notifications - in-app notification center
245
- import { useNotifications } from '@sylphx/sdk/react'
273
+ // Manage subscription
274
+ await openPortal()
246
275
  ```
247
276
 
248
- ---
277
+ ### Analytics
249
278
 
250
- ## UI Components
279
+ ```tsx
280
+ import { useAnalytics } from '@sylphx/sdk/react'
251
281
 
252
- ### Auth Components
282
+ const { track, identify, page } = useAnalytics()
253
283
 
254
- ```tsx
255
- import {
256
- SignIn,
257
- SignUp,
258
- UserButton,
259
- ForgotPassword,
260
- ResetPassword,
261
- VerifyEmail,
262
- } from '@sylphx/sdk/react'
263
-
264
- // Embedded sign-in form
265
- <SignIn mode="embedded" afterSignInUrl="/dashboard" />
266
-
267
- // Modal sign-in
268
- <SignIn mode="modal" />
269
-
270
- // User avatar with dropdown menu
271
- <UserButton afterSignOutUrl="/" />
284
+ track('button_clicked', { button: 'upgrade' })
285
+ identify({ name: 'John', email: 'john@example.com' })
272
286
  ```
273
287
 
274
- ### Protected Routes
288
+ ### Feature Flags
275
289
 
276
290
  ```tsx
277
- import { SignedIn, SignedOut, ProtectedRoute, Protect } from '@sylphx/sdk/react'
278
-
279
- // Show only to signed-in users
280
- <SignedIn>
281
- <Dashboard />
282
- </SignedIn>
283
-
284
- // Show only to signed-out users
285
- <SignedOut>
286
- <SignIn mode="embedded" />
287
- </SignedOut>
291
+ import { useFeatureFlag } from '@sylphx/sdk/react'
288
292
 
289
- // Role-based access
290
- <Protect role="admin">
291
- <AdminPanel />
292
- </Protect>
293
+ const { isEnabled } = useFeatureFlag('new-dashboard')
294
+ if (isEnabled) return <NewDashboard />
293
295
  ```
294
296
 
295
- ### Billing Components
297
+ ### AI
296
298
 
297
299
  ```tsx
298
- import { PricingTable, BillingCard, CheckoutButton } from '@sylphx/sdk/react'
300
+ import { useChat, useCompletion } from '@sylphx/sdk/react'
299
301
 
300
- // Show pricing plans
301
- <PricingTable plans={plans} />
302
-
303
- // Current subscription card
304
- <BillingCard />
302
+ const { messages, send, isLoading } = useChat({
303
+ model: 'anthropic/claude-3.5-sonnet',
304
+ })
305
305
 
306
- // Checkout button
307
- <CheckoutButton planSlug="pro" interval="monthly">
308
- Upgrade to Pro
309
- </CheckoutButton>
306
+ await send('What is the meaning of life?')
310
307
  ```
311
308
 
312
- ### Organization Components
309
+ ### Storage
313
310
 
314
311
  ```tsx
315
- import { OrganizationSwitcher, MembersList, InviteMember } from '@sylphx/sdk/react'
316
-
317
- // Switch between orgs
318
- <OrganizationSwitcher />
312
+ import { useStorage } from '@sylphx/sdk/react'
319
313
 
320
- // Show org members
321
- <MembersList />
314
+ const { upload, uploadAvatar, isUploading, progress } = useStorage()
322
315
 
323
- // Invite form
324
- <InviteMember onInvite={(email) => console.log(email)} />
316
+ const url = await upload(file, { path: 'documents/' })
317
+ const avatarUrl = await uploadAvatar(imageFile)
325
318
  ```
326
319
 
327
- ---
328
-
329
- ## Server-Side (Next.js)
330
-
331
- ### Get Current User
320
+ ### More Hooks
332
321
 
333
322
  ```tsx
334
- // In Server Components
335
- import { auth, currentUser } from '@sylphx/sdk/nextjs'
323
+ import { useConsent } from '@sylphx/sdk/react' // GDPR consent
324
+ import { useFeatureFlags } from '@sylphx/sdk/react' // All flags at once
325
+ import { useNotifications } from '@sylphx/sdk/react' // In-app notifications
326
+ import { useReferral } from '@sylphx/sdk/react' // Referral program
327
+ import { useOrganization } from '@sylphx/sdk/react' // Multi-tenant orgs
328
+ import { useJobs } from '@sylphx/sdk/react' // Background jobs
329
+ import { useErrorTracking } from '@sylphx/sdk/react' // Error capture
330
+ ```
336
331
 
337
- export default async function Page() {
338
- const user = await currentUser()
332
+ ---
339
333
 
340
- if (!user) {
341
- redirect('/login')
342
- }
334
+ ## UI Components
343
335
 
344
- return <div>Hello, {user.name}</div>
345
- }
336
+ ### Auth
346
337
 
347
- // With full auth details
348
- export default async function Page() {
349
- const { userId, accessToken } = await auth()
338
+ ```tsx
339
+ import { SignIn, SignUp, UserButton, SignedIn, SignedOut } from '@sylphx/sdk/react'
350
340
 
351
- // Use accessToken for API calls
352
- }
341
+ <SignedOut><SignIn mode="embedded" afterSignInUrl="/dashboard" /></SignedOut>
342
+ <SignedIn><UserButton afterSignOutUrl="/" /></SignedIn>
353
343
  ```
354
344
 
355
- ### Server API Client
345
+ ### Billing
356
346
 
357
347
  ```tsx
358
- import { createSylphx } from '@sylphx/sdk'
348
+ import { PricingTable, CheckoutButton } from '@sylphx/sdk/react'
359
349
 
360
- const sylphx = createSylphx({
361
- appId: process.env.SYLPHX_APP_ID!,
362
- appSecret: process.env.SYLPHX_APP_SECRET!,
363
- })
350
+ <PricingTable plans={plans} />
351
+ <CheckoutButton planSlug="pro" interval="monthly">Upgrade</CheckoutButton>
352
+ ```
364
353
 
365
- // Track events (tRPC-style with full type inference)
366
- await sylphx.analytics.track.mutate({
367
- event: 'purchase_completed',
368
- userId: user.id,
369
- properties: { amount: 99.99 },
370
- })
354
+ ### Route Protection
371
355
 
372
- // Get subscription
373
- const subscription = await sylphx.billing.getSubscription.query()
356
+ ```tsx
357
+ import { Protect } from '@sylphx/sdk/react'
374
358
 
375
- // Check feature flag
376
- const isEnabled = await sylphx.flags.check.query({ key: 'new-feature' })
359
+ <Protect role="admin">
360
+ <AdminPanel />
361
+ </Protect>
377
362
  ```
378
363
 
379
364
  ---
380
365
 
381
- ## API Reference
366
+ ## Pure Functions (Server or Client)
382
367
 
383
- ### `createSylphx(config)`
384
-
385
- Creates a server-side API client with full TypeScript inference.
368
+ For non-React environments or maximum control:
386
369
 
387
370
  ```ts
388
- const sylphx = createSylphx({
389
- appId: string, // Your app slug
390
- appSecret: string, // sk_dev_*, sk_stg_*, or sk_prod_*
391
- platformUrl?: string, // Default: https://sylphx.com
392
- accessToken?: string, // User access token (optional)
393
- })
394
- ```
371
+ import { createConfig, signIn, track, getPlans } from '@sylphx/sdk'
395
372
 
396
- > **Note**: `createPlatformAPI` is deprecated. Use `createSylphx` instead.
373
+ const config = createConfig({ secretKey: process.env.SYLPHX_SECRET_KEY! })
397
374
 
398
- **Available Namespaces:**
375
+ // Auth
376
+ const tokens = await signIn(config, { email, password })
377
+ const authedConfig = withToken(config, tokens.accessToken)
399
378
 
400
- All methods use tRPC patterns: `.query()` for reads, `.mutate()` for writes.
379
+ // Analytics
380
+ await track(config, { event: 'purchase', properties: { amount: 99 } })
401
381
 
402
- | Namespace | Methods |
403
- |-----------|---------|
404
- | `auth` | `login`, `register`, `logout`, `verifyMfa`, `forgotPassword`, `resetPassword` |
405
- | `user` | `getProfile`, `updateProfile`, `changePassword`, `getSecuritySettings`, `getLoginHistory`, `deleteAccount` |
406
- | `billing` | `getPlans`, `getSubscription`, `createCheckout`, `createPortalSession`, `cancelSubscription` |
407
- | `analytics` | `track`, `trackBatch`, `identify`, `pageView` |
408
- | `notifications` | `list`, `markRead`, `getUnreadCount`, `getPreferences` |
409
- | `referrals` | `getMyCode`, `redeem`, `getStats` |
410
- | `flags` | `check`, `getAll`, `checkWithDetail`, `getAllWithDetail` |
411
- | `storage` | `getUploadUrl`, `uploadAvatar` |
412
- | `jobs` | `submit`, `getStatus`, `cancel`, `list` |
382
+ // Billing
383
+ const plans = await getPlans(config)
384
+ ```
413
385
 
414
386
  ---
415
387
 
416
388
  ## Entry Points
417
389
 
418
- | Import | Use For |
419
- |--------|---------|
420
- | `@sylphx/sdk` | Server-side API client |
421
- | `@sylphx/sdk/react` | React hooks, components, provider |
422
- | `@sylphx/sdk/nextjs` | Next.js middleware, auth helpers |
390
+ | Import path | Use for |
391
+ |---|---|
392
+ | `@sylphx/sdk` | Pure functions (server or client, no React) |
393
+ | `@sylphx/sdk/react` | React hooks, components, `SylphxProvider` |
394
+ | `@sylphx/sdk/server` | JWT verification, webhook verification, server client |
395
+ | `@sylphx/sdk/nextjs` | `createSylphxMiddleware`, `auth()`, `currentUser()` |
423
396
 
424
397
  ---
425
398
 
426
399
  ## TypeScript
427
400
 
428
- Full type support included. No additional packages needed.
401
+ All types are fully inferred. Import them directly:
429
402
 
430
- ```tsx
431
- import type { User, Plan, Subscription } from '@sylphx/sdk'
403
+ ```ts
404
+ import type { User, Plan, Subscription, AppConfig } from '@sylphx/sdk'
405
+ import type { AuthResult } from '@sylphx/sdk/nextjs'
432
406
  ```
407
+
408
+ ---
409
+
410
+ ## Self-Hosting
411
+
412
+ If you're running your own Sylphx Platform deployment:
413
+
414
+ ```bash
415
+ # .env.local — only needed for self-hosting
416
+ SYLPHX_PLATFORM_URL=https://platform.your-domain.com
417
+ ```
418
+
419
+ You will not need this if you're using the hosted platform at [sylphx.com](https://sylphx.com).