
Security News
Ruby's Bundler 4.0.18 Extends Cooldown to bundle lock and bundle cache
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
@nomacms/js-sdk
Advanced tools
JavaScript SDK for NomaCMS API and project end-user auth APIs. https://nomacms.com
JavaScript/TypeScript SDK for NomaCMS API.
npm install @nomacms/js-sdk
import { createClient } from '@nomacms/js-sdk'
const client = createClient({
projectId: 'your-project-uuid',
apiKey: "your-api-key",
})
const project = await client.project.get()
const collections = await client.collections.list()
const postsCollection = await client.collections.get('posts')
projectUserAuth)For password/social login and session APIs, extend the client with storage for access and refresh tokens (example uses localStorage in the browser):
const client = createClient({
projectId: 'your-project-uuid',
apiKey: "your-api-key",
projectUserAuth: {
autoRefresh: true,
tokenStorage: {
getAccessToken: () => localStorage.getItem('noma_user_access') ?? undefined,
setAccessToken: (token) =>
token
? localStorage.setItem('noma_user_access', token)
: localStorage.removeItem('noma_user_access'),
getRefreshToken: () => localStorage.getItem('noma_user_refresh') ?? undefined,
setRefreshToken: (token) =>
token
? localStorage.setItem('noma_user_refresh', token)
: localStorage.removeItem('noma_user_refresh'),
clear: () => {
localStorage.removeItem('noma_user_access')
localStorage.removeItem('noma_user_refresh')
},
},
},
})
import { AuthorizationError } from '@nomacms/js-sdk'
try {
await client.signInWithPassword({
email: 'user@example.com',
password: 'super-secure-password',
})
console.log(client.getSession())
} catch (e) {
if (e instanceof AuthorizationError && e.details && typeof e.details === 'object' && 'verification_token' in e.details) {
const { verification_token } = e.details as { verification_token?: string }
// Use verification_token in your delivery flow, then confirmVerificationEmail({ token }).
}
}
Email verification: The API issues verification_token (sign-up 202 when required, blocked login 403 on AuthorizationError.details, or resendVerificationEmail). Your app owns templates and delivery; confirm with confirmVerificationEmail.
Your app completes OAuth with the provider (e.g. Google) in the browser, then sends the provider id_token to Noma. The backend verifies the JWT and returns the same session shape as password login.
await client.signInWithSocial({
provider: 'google',
id_token: idTokenFromGoogle,
// nonce: '...', // if your OIDC flow used nonce and the id_token includes it
})
Use a server route (Next.js Route Handler, Nuxt server route, etc.) to call this when possible so the id_token is not exposed to untrusted client logging. The Google OAuth client ID used must be allowed in the Noma project / server configuration (aud claim).
const posts = await client.content.list('posts', {
state: 'published',
locale: 'en',
where: { title: { like: 'hello' } },
sort: 'created_at:desc',
paginate: 20,
})
const entry = await client.content.get('posts', 'entry-uuid')
// entry.fields.* — custom field values (not entry.data)
const created = await client.content.create('posts', {
locale: 'en',
state: 'draft',
data: { title: 'My post' },
})
const bulkCreated = await client.content.bulkCreate('posts', {
items: [
{ locale: 'en', state: 'draft', data: { title: 'Bulk 1' } },
{ locale: 'en', state: 'published', data: { title: 'Bulk 2' } },
],
})
List response shape: If you pass paginate, the response body is typically { data: Entry[], meta, links }. If you use limit (without paginate), the API may return a JSON array of entries at the root. Entries always expose custom fields under fields.
Richtext fields in data are markdown strings on create/update. When reading, the API returns either markdown or HTML depending on the field’s editor.outputFormat in the collection schema.
const assets = await client.assets.list({ search: 'hero', type: 'image', paginate: 20 })
const asset = await client.assets.get('asset-uuid')
const byName = await client.assets.getByFilename('hero.jpg')
const uploaded = await client.assets.bulkUpload([fileA, fileB])
await client.assets.bulkUpdateMetadata({
items: [
{ uuid: 'asset-uuid-1', alt_text: 'Hero image', title: 'Homepage hero' },
{ uuid: 'asset-uuid-2', alt_text: 'Gallery image' },
],
})
Asset URLs: url, thumbnail_url, and original_url with optional ?variant=thumbnail or ?variant=original. No Authorization header is required to fetch these files in a browser or CDN; treat shared URLs as capability links, not as row-level ACLs.
createClient(options)
projectId (required): project UUID sent as project-id headerapiKey: dashboard API key from User settings → API keys for content/assets/schema/admin methods.projectUserAuth (optional):
accessTokenrefreshTokenautoRefresh (default true)tokenStorage adaptertimeout (optional, default 30000)client.project.get(params?)client.collections.list()client.collections.get(collectionSlug)client.collections.create(payload)client.collections.update(collectionSlug, payload)client.collections.delete(collectionSlug)client.collections.reorder({ collections: [{ uuid, order }, ...] })client.fields.create(collectionSlug, payload)client.fields.update(collectionSlug, fieldId, payload)client.fields.delete(collectionSlug, fieldId)client.fields.reorder(collectionSlug, { fields: [{ uuid, order }, ...] })client.content.list(collectionSlug, params?)client.content.get(collectionSlug, uuid, params?)client.content.create(collectionSlug, payload)client.content.update(collectionSlug, uuid, payload)client.content.patch(collectionSlug, uuid, payload)client.content.delete(collectionSlug, uuid, force?)client.content.bulkCreate(collectionSlug, payload)client.content.bulkUpdate(collectionSlug, payload)client.content.bulkDelete(collectionSlug, payload)client.content.linkTranslation(collectionSlug, uuid, { translation_entry_uuid }) — merge two entries into one translation group (requires update token ability)client.assets.list(params?)client.assets.get(identifier)client.assets.getByFilename(filename)client.assets.upload(file, metadata?)client.assets.delete(identifier, force?)client.assets.bulkUpload(files)client.assets.bulkUpdateMetadata(payload)client.signUp(payload)client.signInWithPassword(payload)client.signInWithSocial(payload) — { provider, id_token, nonce? }client.refreshSession()client.signOut()client.signOutAll()client.me()client.changePassword(payload)client.resendVerificationEmail(payload) — returns { message, verification_token? } for your delivery flowclient.confirmVerificationEmail(payload)client.listUserApiKeys()client.createUserApiKey(payload)client.revokeUserApiKey(keyId) — manages end-user uak_* keys for the signed-in project user, not dashboard Sanctum tokensclient.getSession()client.getUser()client.onAuthStateChange(callback)All SDK errors extend NomaError.
AuthenticationError (401)AuthorizationError (403)NotFoundError (404)ValidationError (422)RateLimitError (429)ServerError (5xx)NetworkErrorTimeoutErrorExample:
import { AuthorizationError } from '@nomacms/js-sdk'
try {
await client.collections.get('posts')
} catch (error) {
if (error instanceof AuthorizationError) {
console.error('Forbidden by backend:', error.message)
}
}
project-id header.state for content create/update/patch payloads.403 is preserved.fields object for custom values; data is the write payload key only.MIT (see LICENSE).
FAQs
JavaScript SDK for NomaCMS API and project end-user auth APIs. https://nomacms.com
We found that @nomacms/js-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.