@axcode/axcloud-sdk
v0.1.4
Published
SDK for building websites with AxCloud CMS and member management
Maintainers
Readme
@axcode/axcloud-sdk
SDK for building websites with AxCloud CMS and member management.
Installation
npm install @axcode/axcloud-sdkVersion Tags
The SDK is published with two tags for different environments:
| Tag | Purpose | Stability | Install |
|-----|---------|-----------|---------|
| latest | Production | Stable, tested | npm install @axcode/axcloud-sdk |
| next | Development/Staging | Preview, may have breaking changes | npm install @axcode/axcloud-sdk@next |
Recommended setup:
// Production project (package.json)
{
"dependencies": {
"@axcode/axcloud-sdk": "^0.1.0"
}
}
// Development/Staging project (package.json)
{
"dependencies": {
"@axcode/axcloud-sdk": "next"
}
}This allows you to test new SDK features in your staging environment before they reach production.
Quick Start
1. Wrap your app with AxCloudProvider
import { AxCloudProvider } from '@axcode/axcloud-sdk'
function App() {
return (
<AxCloudProvider
orgId="org_ba81807b" // Your organization ID
apiUrl="https://api.axcloud.app"
apiKey="pk_live_..." // Public API key from Settings → API Keys
auth0={{
domain: "auth.axcloud.app",
clientId: "your-client-id",
redirectUri: window.location.origin
}}
>
<Router>
<Routes />
</Router>
</AxCloudProvider>
)
}2. Fetch content
import { useNews } from '@axcode/axcloud-sdk'
function NewsPage() {
const { data: news, isLoading, isError } = useNews()
if (isLoading) return <Spinner />
if (isError) return <Error />
return (
<ul>
{news.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
)
}Content visibility: When the user is authenticated,
useNews,useContent('pages'), anduseContent('events')automatically fetch public + internal + members-only content based on the user's organization membership. For anonymous users, only public content is returned.
3. Add authentication
import { useAuth, LoginButton, LogoutButton, ProtectedRoute } from '@axcode/axcloud-sdk'
function Header() {
const { isAuthenticated, user } = useAuth()
return (
<header>
{isAuthenticated ? (
<>
<span>Welcome, {user.name}</span>
<LogoutButton />
</>
) : (
<LoginButton>Sign In</LoginButton>
)}
</header>
)
}
function MemberArea() {
return (
<ProtectedRoute>
<MemberContent />
</ProtectedRoute>
)
}4. Use sections
import { useMySection } from '@axcode/axcloud-sdk'
function MySectionPage() {
const { section, members, isLoading } = useMySection()
if (isLoading) return <Spinner />
if (!section) return <p>You are not assigned to a section</p>
return (
<div>
<h1>{section.name}</h1>
<h2>Members ({members.length})</h2>
<ul>
{members.map(m => <li key={m.id}>{m.name}</li>)}
</ul>
</div>
)
}4b. Filter content by section
import { useNews, useMySection } from '@axcode/axcloud-sdk'
function SectionNews() {
const { sectionId } = useMySection()
// Fetch news for user's section only
const { data: sectionNews } = useNews({ sectionId })
// Or fetch all organization news
const { data: allNews } = useNews()
return (
<div>
<h2>Section News</h2>
{sectionNews.map(item => <NewsCard key={item.id} item={item} />)}
<h2>All Organization News</h2>
{allNews.map(item => <NewsCard key={item.id} item={item} />)}
</div>
)
}5. Fetch organization branding and media
import { useBranding, useLogo, useMedia } from '@axcode/axcloud-sdk'
function Header() {
const { logoUrl, branding, organizationName } = useBranding()
return (
<header style={{ backgroundColor: branding?.primaryColor }}>
{logoUrl && <img src={logoUrl} alt={organizationName} />}
<h1>{organizationName}</h1>
</header>
)
}
// Or just the logo
function Logo() {
const { logoUrl, isLoading } = useLogo()
if (isLoading) return <Skeleton />
return logoUrl ? <img src={logoUrl} alt="Logo" /> : <DefaultLogo />
}
// Fetch specific media file
function HeroImage() {
const { mediaUrl } = useMedia('hero-banner.jpg')
return mediaUrl ? <img src={mediaUrl} alt="Hero" /> : null
}Note: Media URLs are signed S3 URLs that expire after 1 hour. The SDK automatically refreshes them before expiry (staleTime: 30 min).
6. Gate features by module
import { ModuleGate, useOrg } from '@axcode/axcloud-sdk'
function Dashboard() {
const { hasModule } = useOrg()
return (
<div>
<NewsSection />
<ModuleGate module="training" fallback={<UpgradePrompt />}>
<TrainingSection />
</ModuleGate>
{hasModule('ai') && <AIChatWidget />}
</div>
)
}API Reference
Provider
| Component | Description |
|-----------|-------------|
| AxCloudProvider | Main provider that combines Auth0, React Query, and SDK context |
Hooks
| Hook | Description |
|------|-------------|
| useAuth() | Login/logout with Auth0 Universal Login |
| useUser() | Fetch current user with role and permissions |
| useOrg() | Fetch organization info and check modules |
| useNews(options?) | Fetch news articles. Returns public + internal + members content when authenticated. |
| useContent(type, options?) | Fetch any content type. For pages and events, returns member content when authenticated. |
| useMySection() | Fetch current user's section with members |
| useSections() | Fetch all organization sections |
| useBranding() | Fetch organization branding (logo, colors) |
| useLogo() | Fetch organization logo URL |
| useMedia(mediaId) | Fetch specific media file URL |
| useAvatar(userId) | Fetch user avatar URL |
| useMediaList(type) | List media files |
Content Query Options
interface ContentQueryOptions {
page?: number // Page number (default: 1)
pageSize?: number // Items per page (default: 20)
status?: 'draft' | 'published' | 'archived'
visibility?: 'public' | 'members' | 'section'
sectionId?: string // Filter by specific section
search?: string // Search in title/content
sortBy?: string // Sort field (default: 'createdAt')
sortOrder?: 'asc' | 'desc'
}Components
| Component | Description |
|-----------|-------------|
| <LoginButton> | Trigger Auth0 login |
| <LogoutButton> | Trigger logout |
| <ProtectedRoute> | Require authentication to view content |
| <ModuleGate> | Conditionally render based on enabled modules |
Advanced Usage
Custom API calls
import { useAuth } from '@axcode/axcloud-sdk'
function MyComponent() {
const { getAccessToken } = useAuth()
const fetchCustomData = async () => {
const token = await getAccessToken()
const response = await fetch('/api/custom', {
headers: { Authorization: `Bearer ${token}` }
})
return response.json()
}
}Access the underlying Auth0 client
const { getAuth0Client } = useAuth()
const auth0 = getAuth0Client()
// Full Auth0 API available
await auth0.getAccessTokenSilently()
await auth0.getIdTokenClaims()Security Model
API Key vs Authentication Token
The SDK uses two types of credentials:
API Key (
apiKeyprop): A public identifier for your organization- Safe to include in client-side code
- Used for public content endpoints
- Backend validates and rate-limits based on API key
- Without a valid API key, requests return 401
Authentication Token (via Auth0): A secret JWT token
- Automatically managed by the SDK
- Required for member-only content and user data
- Never exposed in client code
What the API Key Protects
| Without API Key | With API Key | With Auth Token | |-----------------|--------------|-----------------| | Nothing | Public news/content | Member content | | | Organization branding | User profile | | | Public media | Linked accounts | | | | Admin functions |
Endpoint Security
| Endpoint Type | Authentication | Example |
|--------------|---------------|---------|
| Public content | API key (x-api-key header) | /content/public/{orgId}/news |
| Member content | JWT Bearer token | /content/members/{orgId}/news |
| User data | JWT Bearer token | /api/users/me |
| Admin | JWT Bearer token + role | /api/admin/forms/submissions |
Error Handling
import { useNews, isAxCloudError } from '@axcode/axcloud-sdk'
function NewsPage() {
const { data, error, isError } = useNews()
if (isError) {
if (isAxCloudError(error)) {
switch (error.code) {
case 'UNAUTHORIZED':
return <LoginPrompt />
case 'NOT_FOUND':
return <NotFound />
default:
return <Error message={error.message} />
}
}
return <Error message="Something went wrong" />
}
return <NewsList items={data} />
}License
UNLICENSED - Internal use only. Contact Axcode AB for access.
