npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sylphx/sdk

v0.3.2

Published

Sylphx SDK - State-of-the-art platform SDK with pure functions

Readme

@sylphx/sdk

npm version License: MIT TypeScript docs

Auth, billing, analytics, AI, storage, and more — in one SDK.

📖 Full docs: sylphx.com/docs


Installation

npm install @sylphx/sdk
# or
pnpm add @sylphx/sdk
bun add @sylphx/sdk

Quick Start (Next.js)

1. Environment Variables

Two keys from your Platform Console:

# .env.local
SYLPHX_SECRET_KEY=sk_dev_xxxxxxxxxxxxxxxxxxxx        # server-only
NEXT_PUBLIC_SYLPHX_APP_ID=app_dev_xxxxxxxxxxxx        # safe to expose

That's it. No other config needed.

Key formats

  • sk_dev_* / sk_stg_* / sk_prod_* — Secret key (server only, never expose)
  • app_dev_* / app_stg_* / app_prod_* — App ID (safe for client-side)

Get both from Console → Your App → API Keys.


2. Middleware

Handles auth routes (/auth/callback, /auth/signout) and route protection automatically.

// middleware.ts
import { createSylphxMiddleware } from '@sylphx/sdk/nextjs'

export default createSylphxMiddleware({
  publicRoutes: ['/', '/about', '/pricing', '/login'],
})

export const config = {
  matcher: ['/((?!_next|.*\\..*).*)', '/'],
}

No manual /api/auth/* routes needed — the middleware handles everything.


3. Root Layout

Fetch config server-side once, pass to the provider:

// app/layout.tsx
import { getAppConfig } from '@sylphx/sdk/server'
import { SylphxProvider } from '@sylphx/sdk/react'

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const config = await getAppConfig({
    secretKey: process.env.SYLPHX_SECRET_KEY!,
    appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
  })

  return (
    <html>
      <body>
        <SylphxProvider
          config={config}
          appId={process.env.NEXT_PUBLIC_SYLPHX_APP_ID!}
        >
          {children}
        </SylphxProvider>
      </body>
    </html>
  )
}

4. Protect Pages (Server Components)

// app/dashboard/page.tsx
import { currentUser } from '@sylphx/sdk/nextjs'
import { redirect } from 'next/navigation'

export default async function Dashboard() {
  const user = await currentUser()
  if (!user) redirect('/login')

  return <h1>Hello, {user.name}</h1>
}

5. Auth UI (Client Components)

'use client'
import { useUser, SignedIn, SignedOut, UserButton } from '@sylphx/sdk/react'

export default function Header() {
  const { user } = useUser()

  return (
    <header>
      <SignedOut>
        <a href="/login">Sign in</a>
      </SignedOut>
      <SignedIn>
        <span>Hello, {user?.name}</span>
        <UserButton afterSignOutUrl="/" />
      </SignedIn>
    </header>
  )
}

Server-Side

Get Current User

import { auth, currentUser, currentUserId } from '@sylphx/sdk/nextjs'

// Full auth state
const { userId, user, sessionToken } = await auth()

// Just the user object (null if not signed in)
const user = await currentUser()

// Just the user ID
const userId = await currentUserId()

Server API Client

import { createServerClient } from '@sylphx/sdk/server'

const client = createServerClient({
  secretKey: process.env.SYLPHX_SECRET_KEY!,
})

// GET /billing/plans
const plans = await client.GET('/billing/plans')

// POST /analytics/track
await client.POST('/analytics/track', {
  body: { events: [{ event: 'purchase', properties: { amount: 99 } }] },
})

Prefetch App Config

import {
  getAppConfig,    // All config in one call (recommended)
  getPlans,        // Billing plans
  getFeatureFlags, // Feature flag definitions
  getConsentTypes, // GDPR consent config
} from '@sylphx/sdk/server'

const config = await getAppConfig({
  secretKey: process.env.SYLPHX_SECRET_KEY!,
  appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
})
// config.plans, config.featureFlags, config.oauthProviders, config.consentTypes

Verify Webhooks

import { verifyWebhook } from '@sylphx/sdk/server'

export async function POST(request: Request) {
  const body = await request.text()

  const result = await verifyWebhook({
    payload: body,
    signatureHeader: request.headers.get('x-webhook-signature'),
    secret: process.env.SYLPHX_SECRET_KEY!,
  })

  if (!result.valid) {
    return new Response('Unauthorized', { status: 401 })
  }

  const { event, data } = result.payload!
  // handle event...
  return Response.json({ received: true })
}

Or use the handler factory:

import { createWebhookHandler } from '@sylphx/sdk/server'

export const POST = createWebhookHandler({
  secret: process.env.SYLPHX_SECRET_KEY!,
  handlers: {
    'user.created': async (data) => { /* ... */ },
    'subscription.updated': async (data) => { /* ... */ },
  },
})

JWT Verification

import { verifyAccessToken } from '@sylphx/sdk/server'

const payload = await verifyAccessToken(token, {
  secretKey: process.env.SYLPHX_SECRET_KEY!,
})
// payload.sub, payload.email, payload.role, payload.app_id

React Hooks

Auth

import { useUser, useAuth } from '@sylphx/sdk/react'

const { user, isLoading, isSignedIn } = useUser()
const { signIn, signUp, signOut, forgotPassword } = useAuth()

await signIn({ email: '[email protected]', password: '...' })
await signOut()

Billing

import { useBilling } from '@sylphx/sdk/react'

const { subscription, isPremium, plans, createCheckout, openPortal } = useBilling()

// Check access
if (!isPremium) return <UpgradePrompt />

// Start checkout
const url = await createCheckout('pro', 'monthly')
window.location.href = url

// Manage subscription
await openPortal()

Analytics

import { useAnalytics } from '@sylphx/sdk/react'

const { track, identify, page } = useAnalytics()

track('button_clicked', { button: 'upgrade' })
identify({ name: 'John', email: '[email protected]' })

Feature Flags

import { useFeatureFlag } from '@sylphx/sdk/react'

const { isEnabled } = useFeatureFlag('new-dashboard')
if (isEnabled) return <NewDashboard />

AI

import { useChat, useCompletion } from '@sylphx/sdk/react'

const { messages, send, isLoading } = useChat({
  model: 'anthropic/claude-3.5-sonnet',
})

await send('What is the meaning of life?')

Storage

import { useStorage } from '@sylphx/sdk/react'

const { upload, uploadAvatar, isUploading, progress } = useStorage()

const url = await upload(file, { path: 'documents/' })
const avatarUrl = await uploadAvatar(imageFile)

More Hooks

import { useConsent }       from '@sylphx/sdk/react' // GDPR consent
import { useFeatureFlags }  from '@sylphx/sdk/react' // All flags at once
import { useNotifications } from '@sylphx/sdk/react' // In-app notifications
import { useReferral }      from '@sylphx/sdk/react' // Referral program
import { useOrganization }  from '@sylphx/sdk/react' // Multi-tenant orgs
import { useJobs }          from '@sylphx/sdk/react' // Background jobs
import { useErrorTracking } from '@sylphx/sdk/react' // Error capture

UI Components

Auth

import { SignIn, SignUp, UserButton, SignedIn, SignedOut } from '@sylphx/sdk/react'

<SignedOut><SignIn mode="embedded" afterSignInUrl="/dashboard" /></SignedOut>
<SignedIn><UserButton afterSignOutUrl="/" /></SignedIn>

Billing

import { PricingTable, CheckoutButton } from '@sylphx/sdk/react'

<PricingTable plans={plans} />
<CheckoutButton planSlug="pro" interval="monthly">Upgrade</CheckoutButton>

Route Protection

import { Protect } from '@sylphx/sdk/react'

<Protect role="admin">
  <AdminPanel />
</Protect>

Pure Functions (Server or Client)

For non-React environments or maximum control:

import { createConfig, signIn, track, getPlans } from '@sylphx/sdk'

const config = createConfig({ secretKey: process.env.SYLPHX_SECRET_KEY! })

// Auth
const tokens = await signIn(config, { email, password })
const authedConfig = withToken(config, tokens.accessToken)

// Analytics
await track(config, { event: 'purchase', properties: { amount: 99 } })

// Billing
const plans = await getPlans(config)

Entry Points

| Import path | Use for | |---|---| | @sylphx/sdk | Pure functions (server or client, no React) | | @sylphx/sdk/react | React hooks, components, SylphxProvider | | @sylphx/sdk/server | JWT verification, webhook verification, server client | | @sylphx/sdk/nextjs | createSylphxMiddleware, auth(), currentUser() |


TypeScript

All types are fully inferred. Import them directly:

import type { User, Plan, Subscription, AppConfig } from '@sylphx/sdk'
import type { AuthResult } from '@sylphx/sdk/nextjs'

Self-Hosting

If you're running your own Sylphx Platform deployment:

# .env.local — only needed for self-hosting
SYLPHX_PLATFORM_URL=https://platform.your-domain.com

You will not need this if you're using the hosted platform at sylphx.com.