@nexushub/client
v0.3.5
Published
The God-Tier NexusHub SDK
Downloads
1,458
Readme
NexusHub Client SDK
The God-Tier Headless CMS SDK — Everything you need to build blazing-fast websites with real-time content, analytics, and authentication.
✨ Features
🚀 Performance First
- Multi-layer caching: Memory → LocalStorage → Remote with LRU eviction
- Request optimization: Batching, deduplication, exponential backoff
- Smart preloading: Automatic content prediction and prefetching
- < 5ms cache hits, < 100ms cold starts
📊 Built-in Analytics Engine
- Real-time tracking: Page views, clicks, form submissions
- Web Vitals: Core Web Vitals with RUM (Real User Monitoring)
- Session management: 30-minute sessions with automatic renewal
- User identification: Anonymous → Known user handshake
- E-commerce ready: Track purchases, cart events, conversions
🔐 Authentication System
- Full auth flow: Register, login, logout, social login (Google)
- Protected routes: React hooks for auth state
- Session persistence: HttpOnly cookies for security
- Role-based access: User roles and permissions
📁 Content Engine
- Type-safe content: Full TypeScript support with generics
- Advanced querying: Filter, sort, paginate, search, include
- Real-time updates: WebSocket/SSE subscriptions
- Collection support: Dynamic content with rich relationships
- Singleton pages: Static content with smart caching
🛠 Developer Experience
- Zero-config setup: Auto-detects environment variables
- Local development: Offline mode with local cache
- CLI tool: Pull, seed, deploy, and manage content
- Debug mode: Detailed logs and performance metrics
- Hot reload: Instant updates during development
🚀 Quick Start
1. Installation
npm install @nexushub/client
# or
yarn add @nexushub/client
# or
pnpm add @nexushub/client2. Environment Setup
Create .env.local in your project root:
# Required
NEXT_PUBLIC_NEXUS_ID=your_project_id_here
NEXT_PUBLIC_NEXUS_KEY=your_api_key_here
# Optional (defaults to https://api.nexushub.com/v1)
NEXT_PUBLIC_NEXUS_API_URL=https://api.nexushub.com/v13. Wrap Your App (Next.js/React)
// app/layout.tsx (Next.js App Router)
import { NexusProvider } from '@nexushub/client'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<NexusProvider>
{children}
</NexusProvider>
</body>
</html>
)
}4. Use Content Anywhere
// app/page.tsx
import { nexus } from '@nexushub/client'
export default async function HomePage() {
const homePage = await nexus.getPage('home')
const blogPosts = await nexus.content.getCollection('blog_posts', {
page: 1,
limit: 10,
sort: 'createdAt',
order: 'desc',
filter: { published: true }
})
return (
<main>
<h1>{homePage.title}</h1>
<p>{homePage.content}</p>
<h2>Latest Posts</h2>
<ul>
{blogPosts.items.map(post => (
<li key={post.id}>
<h3>{post.title}</h3>
<p>{post.excerpt}</p>
</li>
))}
</ul>
</main>
)
}📖 Documentation
Table of Contents
- Configuration
- Content Fetching
- Authentication
- Analytics
- Caching
- CLI Tool
- API Reference
- Examples
- Troubleshooting
🔧 Configuration
Auto Configuration (Recommended)
// Uses environment variables automatically
const client = nexus // Singleton instanceManual Configuration
import { createNexusClient } from '@nexushub/client'
const client = createNexusClient({
projectId: 'your-project-id',
apiKey: 'your-api-key',
apiUrl: 'https://api.nexushub.com/v1', // Optional
debug: true, // Enable debug logging
cacheStrategy: 'memory', // 'memory' | 'localStorage' | 'none'
revalidateTime: 60, // Cache revalidation in seconds
timeout: 10000, // Request timeout in ms
retries: 3, // Number of retry attempts
})React Configuration
// app/NexusWrapper.tsx
'use client'
import { NexusProvider } from '@nexushub/client'
export function NexusWrapper({ children }: { children: React.ReactNode }) {
return (
<NexusProvider projectId="optional-override-id">
{children}
</NexusProvider>
)
}📁 Content Fetching
Get a Single Page
// Basic usage
const page = await nexus.getPage('home')
// With options
const page = await nexus.getPage('about', {
revalidate: 300, // Revalidate every 5 minutes
tags: ['page:about'], // Cache tags for invalidation
forceRefresh: false, // Bypass cache
includeMetadata: true, // Include cache metadata
})Get Collections
// Get all items from a collection
const posts = await nexus.content.getCollection('blog_posts')
// Advanced querying
const products = await nexus.content.getCollection('products', {
page: 1,
limit: 20,
sort: 'price',
order: 'asc',
filter: {
category: 'electronics',
price: { $lt: 1000 },
inStock: true
},
search: 'wireless headphones',
fields: ['id', 'name', 'price', 'image'],
include: ['category', 'reviews'],
})Get a Single Item
const product = await nexus.content.getItem('products', 'prod_12345', {
include: ['category', 'reviews', 'variants'],
tags: ['product:prod_12345'],
})Search Across Collections
const results = await nexus.content.search('wireless', {
collections: ['products', 'articles'],
fields: ['title', 'description', 'content'],
limit: 50,
})Get Global Settings
const globals = await nexus.content.getGlobals({
include: ['navigation', 'footer', 'social_links'],
revalidate: 3600, // Cache for 1 hour
})🔐 Authentication
Setup Auth Provider
// app/auth/layout.tsx
'use client'
import { useNexusAuth } from '@nexushub/client'
export default function AuthLayout({ children }) {
const { user, isLoading, isAuthenticated } = useNexusAuth()
if (isLoading) return <div>Loading...</div>
return (
<div>
{isAuthenticated ? (
<div>
<p>Welcome, {user.name}!</p>
{children}
</div>
) : (
<LoginForm />
)}
</div>
)
}Login/Register Forms
'use client'
import { useNexusAuth } from '@nexushub/client'
import { useState } from 'react'
export function LoginForm() {
const { login, register, loginWithGoogle } = useNexusAuth()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleLogin = async () => {
try {
await login({ email, password })
// Redirect or show success
} catch (error) {
console.error('Login failed:', error)
}
}
const handleGoogleLogin = () => {
loginWithGoogle()
}
return (
<div>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button onClick={handleLogin}>Login</button>
<button onClick={handleGoogleLogin}>Login with Google</button>
</div>
)
}Protected Routes Hook
'use client'
import { useNexusAuth } from '@nexushub/client'
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
export function useRequireAuth(redirectTo = '/login') {
const { user, isLoading, isAuthenticated } = useNexusAuth()
const router = useRouter()
useEffect(() => {
if (!isLoading && !isAuthenticated) {
router.push(redirectTo)
}
}, [isLoading, isAuthenticated, router, redirectTo])
return { user, isLoading }
}
// Usage
export default function DashboardPage() {
const { user, isLoading } = useRequireAuth('/login')
if (isLoading) return <div>Loading...</div>
return (
<div>
<h1>Dashboard</h1>
<p>Welcome, {user.name}!</p>
</div>
)
}📊 Analytics
Automatic Tracking
Analytics starts automatically when you wrap your app with NexusProvider. It tracks:
- Page views and route changes
- Click events (links, buttons)
- Form submissions
- Web Vitals (CLS, LCP, FID, INP)
- Performance metrics
- Error tracking
Manual Event Tracking
import { nexus } from '@nexushub/client'
// Get analytics instance (automatically initialized)
const analytics = nexus['analytics'] // Internal access
// Or track custom events
analytics.track('button_clicked', {
button_id: 'cta-primary',
page: '/home',
timestamp: new Date().toISOString()
})
// Track purchases
analytics.trackPurchase({
order_id: 'ORD_12345',
total: 99.99,
currency: 'USD',
items: [
{ id: 'prod_1', name: 'Product 1', price: 49.99, quantity: 2 }
]
})
// Identify users (link anonymous to known)
await analytics.identify('user_123', {
name: 'John Doe',
email: '[email protected]',
plan: 'premium'
})Web Vitals Monitoring
Automatically tracks Core Web Vitals with detailed breakdowns:
// You can access vitals data through the analytics engine
const sessionId = analytics.getSessionId()
console.log('Session:', sessionId)Disable Analytics
// If you need to disable analytics (GDPR compliance)
<NexusProvider disableAnalytics>
{children}
</NexusProvider>💾 Caching System
Cache Strategies
// 1. Memory Cache (Default - Fastest)
const client = createNexusClient({
cacheStrategy: 'memory', // In-memory cache, cleared on page refresh
revalidateTime: 60 // Seconds
})
// 2. LocalStorage Cache (Persistent)
const client = createNexusClient({
cacheStrategy: 'localStorage', // Persists across sessions
revalidateTime: 300 // 5 minutes
})
// 3. No Cache (Always Fresh)
const client = createNexusClient({
cacheStrategy: 'none' // Always fetch from network
})Cache Invalidation
// Invalidate by tags
nexus.content.invalidateCache(['page:home', 'collection:blog_posts'])
// Clear all cache
nexus.content.clearCache()
// Manual cache control
const page = await nexus.getPage('home', {
forceRefresh: true, // Skip cache
revalidate: 0 // No revalidation
})
// Get cache statistics
const stats = nexus.content.getCacheStats()
console.log(stats)
/*
{
memory: {
size: 15,
hits: 124,
misses: 12,
hitRate: 0.91,
evictions: 3
},
browser: { size: 24567 },
local: { loaded: true }
}
*/Cache Tags
Auto-generated tags for smart invalidation:
// Content gets tagged automatically:
// - `nexus_project_${projectId}`
// - `content_${slug}`
// - `collection_${collectionId}`
// - `item_${itemId}`
// - `nexus_global_config`
// You can add custom tags:
const page = await nexus.getPage('home', {
tags: ['homepage', 'featured']
})
// Later, invalidate all homepage content:
nexus.content.invalidateCache(['homepage'])🛠️ CLI Tool
Installation
# If installed globally
npm install -g @nexushub/client
# Or use npx
npx @nexushub/client <command>Available Commands
# Initialize project structure
npx nexus init
# Pull content from NexusHub to local cache
npx nexus pull --api-key YOUR_KEY --project-id YOUR_ID
# Seed content from local files to NexusHub
npx nexus seed --input .nexus/seed
# Trigger deployment
npx nexus deploy --environment production
# Check project status
npx nexus status
# Force overwrite local cache
npx nexus pull --forceProject Structure
.nexus/
├── cache.json # Local cache (gitignored)
├── seed/ # Seed data for content
│ ├── pages.json # Static pages
│ ├── collections/ # Dynamic collections
│ │ ├── blog_posts.json
│ │ └── products.json
│ └── globals.json # Global settings
└── README.mdEnvironment Variables for CLI
# .env.local (for CLI)
NEXUS_API_KEY=your_api_key_here
NEXUS_PROJECT_ID=your_project_id_here
NEXUS_API_URL=https://api.nexushub.com/v1📚 API Reference
NexusClient
Constructor
new NexusClient(config?: Partial<NexusConfig>)Methods
getPage<T>(slug: string, options?): Get singleton pagegetConfig(): Get current configcontent: ContentEngine instanceanalytics: AnalyticsEngine instance (internal)
ContentEngine
Core Methods
// Content fetching
getPage<T>(slug: string, options?): Promise<T>
getCollection<T>(collectionId: string, query?, options?): Promise<CollectionResponse<T>>
getItem<T>(collectionId: string, itemId: string, options?): Promise<T>
getGlobals<T>(options?): Promise<T>
// Search
search<T>(query: string, options?): Promise<{ results: T[], total: number }>
// Cache management
invalidateCache(tags: string[]): void
clearCache(): void
getCacheStats(): CacheStats
// Real-time
subscribeToUpdates(callback): () => void
prefetch(urls: string[]): Promise<void>useNexusAuth() Hook
Returns
{
user: SiteUser | null,
isLoading: boolean,
error: Error | null,
isAuthenticated: boolean,
// Methods
login: (credentials: LoginCredentials) => Promise<void>,
register: (credentials: RegisterCredentials) => Promise<void>,
logout: () => Promise<void>,
loginWithGoogle: () => void,
updateProfile: (data: Partial<SiteUser>) => Promise<void>
}Types
interface NexusConfig {
projectId: string;
apiUrl: string;
apiKey?: string;
debug?: boolean;
cacheStrategy?: 'memory' | 'localStorage' | 'none';
revalidateTime?: number;
timeout?: number;
retries?: number;
}
interface ContentResponse<T = any> {
id: string;
type: string;
data: T;
meta: {
version: number;
updatedAt: string;
locale?: string;
cacheStatus: 'hit' | 'miss' | 'stale';
};
}
interface CollectionResponse<T = any> {
items: T[];
total: number;
page: number;
limit: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
meta?: {
fetchedAt: string;
cacheStatus: string;
filters?: Record<string, any>;
};
}🚦 Examples
Next.js App Router
// app/layout.tsx
import { NexusProvider } from '@nexushub/client'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<NexusProvider>
{children}
</NexusProvider>
</body>
</html>
)
}
// app/blog/page.tsx
import { nexus } from '@nexushub/client'
export default async function BlogPage() {
const posts = await nexus.content.getCollection('blog_posts', {
page: 1,
limit: 10,
sort: 'publishedAt',
order: 'desc',
filter: { status: 'published' }
})
return (
<div>
<h1>Blog</h1>
{posts.items.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
)
}Next.js Pages Router
// pages/_app.tsx
import { NexusProvider } from '@nexushub/client'
function MyApp({ Component, pageProps }) {
return (
<NexusProvider>
<Component {...pageProps} />
</NexusProvider>
)
}
// pages/index.tsx
import { nexus } from '@nexushub/client'
export async function getServerSideProps() {
const page = await nexus.getPage('home')
return { props: { page } }
}
export default function Home({ page }) {
return (
<div>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: page.content }} />
</div>
)
}React (No Framework)
// index.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { NexusProvider } from '@nexushub/client'
import App from './App'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<NexusProvider projectId="your-project-id">
<App />
</NexusProvider>
</React.StrictMode>
)
// App.tsx
import { nexus, useNexusAuth } from '@nexushub/client'
import { useEffect, useState } from 'react'
function App() {
const [page, setPage] = useState(null)
const { user, login } = useNexusAuth()
useEffect(() => {
nexus.getPage('home').then(setPage)
}, [])
if (!page) return <div>Loading...</div>
return (
<div>
<h1>{page.title}</h1>
<p>{page.content}</p>
</div>
)
}E-commerce Example
// components/ProductList.tsx
import { nexus } from '@nexushub/client'
export async function ProductList({ category }) {
const products = await nexus.content.getCollection('products', {
filter: { category },
sort: 'createdAt',
order: 'desc',
include: ['variants', 'reviews']
})
const handlePurchase = (product) => {
// Track purchase in analytics
nexus['analytics'].trackPurchase({
order_id: `temp_${Date.now()}`,
total: product.price,
currency: 'USD',
items: [{
id: product.id,
name: product.name,
price: product.price,
quantity: 1
}]
})
}
return (
<div className="grid grid-cols-4 gap-4">
{products.items.map(product => (
<div key={product.id} className="border p-4">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p>${product.price}</p>
<button
onClick={() => handlePurchase(product)}
className="bg-blue-500 text-white px-4 py-2"
>
Add to Cart
</button>
</div>
))}
</div>
)
}🐛 Troubleshooting
Common Issues
1. "Missing projectId" Error
# Check your environment variables
echo $NEXT_PUBLIC_NEXUS_ID
# Ensure .env.local exists
ls -la .env.local
# Restart dev server after changing env vars
npm run dev2. Cache Not Updating
// Force refresh
await nexus.getPage('home', { forceRefresh: true })
// Clear all cache
nexus.content.clearCache()
// Check cache stats
console.log(nexus.content.getCacheStats())3. Analytics Not Tracking
// Check if analytics is enabled
const client = createNexusClient({ debug: true })
// Verify in console logs
// Should see: "[NexusHub] Analytics started"4. Authentication Issues
// Check CORS settings in NexusHub dashboard
// Ensure your domain is whitelisted
// Verify HttpOnly cookies are supported
// Some ad blockers may interfere5. TypeScript Errors
// If you get "Property 'content' does not exist"
// Make sure you're using the correct import:
import { nexus } from '@nexushub/client' // Correct
import nexus from '@nexushub/client' // WrongDebug Mode
Enable debug logging to see detailed information:
const client = createNexusClient({
debug: true,
cacheStrategy: 'memory'
})
// Check console for:
// - Cache hits/misses
// - Network requests
// - Performance metrics
// - Analytics eventsPerformance Monitoring
// Get performance metrics
const stats = nexus.content.getCacheStats()
console.log('Cache Hit Rate:', stats.memory.hitRate)
// Monitor Web Vitals in analytics dashboard
// Visit: https://dashboard.nexushub.com/analytics🔧 Advanced Configuration
Custom Cache Implementation
import { MemoryCache, BrowserCache } from '@nexushub/client'
// Extend existing cache
class CustomMemoryCache extends MemoryCache {
constructor(options) {
super({ ...options, maxSize: 2000 })
}
set(key, data, options) {
// Add custom logic
console.log(`Caching: ${key}`)
super.set(key, data, options)
}
}
// Use in your app
const customCache = new CustomMemoryCache({ ttl: 60000 })Middleware & Interceptors
// Request/Response interceptors
const client = createNexusClient({
interceptors: {
request: (config) => {
// Add custom headers
config.headers['X-Custom-Header'] = 'value'
return config
},
response: (response) => {
// Transform response
return response.data
},
error: (error) => {
// Custom error handling
console.error('Request failed:', error)
throw error
}
}
})Multiple Projects
import { createNexusClient } from '@nexushub/client'
const mainClient = createNexusClient({
projectId: 'main-project',
apiKey: 'main-key'
})
const secondaryClient = createNexusClient({
projectId: 'secondary-project',
apiKey: 'secondary-key',
apiUrl: 'https://api-2.nexushub.com/v1'
})
// Use both clients in your app
const [mainPage, secondaryPage] = await Promise.all([
mainClient.getPage('home'),
secondaryClient.getPage('home')
])📈 Performance Benchmarks
Cache Performance:
├── Memory Cache: 0.1ms - 1ms
├── LocalStorage: 1ms - 5ms
└── Network: 50ms - 300ms
Bundle Size:
├── Core SDK: 15kb gzipped
├── With Analytics: 28kb gzipped
└── Full Package: 35kb gzipped
Memory Usage:
├── Memory Cache: ~5MB max
├── LocalStorage: ~5MB max
└── Browser Memory: ~10MB typical🤝 Contributing
We welcome contributions! Here's how to get started:
- Fork the repository
- Clone your fork
git clone https://github.com/your-username/nexushub-client-sdk.git
cd nexushub-client-sdk/packages/client-sdk- Install dependencies
npm install- Run tests
npm test
npm run test:coverage- Make changes and test
npm run dev # Watch mode
npm run build- Submit a Pull Request
Development Scripts
# Build
npm run build
# Development (watch mode)
npm run dev
# Type checking
npm run type-check
# Linting
npm run lint
# Testing
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
npm run test:debug # Verbose output📄 License
MIT License - see LICENSE file for details.
🔗 Links
🏆 Support
- Community Support: GitHub Discussions
- Priority Support: Available for enterprise plans
- Bug Reports: GitHub Issues
- Feature Requests: Submit via GitHub Issues
