Noma

Next.js

Next.js

Use the JavaScript SDK from server-side code in Next.js so your personal access token and Project ID never ship to the browser. This page covers App Router patterns (Next.js 13+); the same ideas apply to the Pages Router with getServerSideProps or Route Handlers instead of Server Components.

Install

npm install @nomacms/js-sdk

Environment variables

Add credentials to .env.local (or your deployment environment). Do not prefix these with NEXT_PUBLIC_—that would expose them in client bundles.

NOMA_PROJECT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
NOMA_API_KEY=noma_...

Restart the dev server after changing env files.

Keep CMS credentials on the server

Never expose NOMA_API_KEY to the browser. Use Server Components, Route Handlers, or a backend proxy—see Installation & Setup. Use a key created while the same workspace is selected in the dashboard as the project you’re calling.

Create a server-only client helper

Centralize createClient so Server Components and Route Handlers stay consistent:

// lib/noma.ts
import { createClient } from "@nomacms/js-sdk"
 
export function getNomaServerClient() {
  const projectId = process.env.NOMA_PROJECT_ID
  const apiKey = process.env.NOMA_API_KEY
 
  if (!projectId || !apiKey) {
    throw new Error("Missing NOMA_PROJECT_ID or NOMA_API_KEY")
  }
 
  return createClient({
    projectId,
    apiKey,
  })
}

Fetch content in a Server Component

Call the SDK directly in async Server Components. Data is fetched on the server per request (or according to your caching configuration).

// app/posts/page.tsx
import { getNomaServerClient } from "@/lib/noma"
 
export default async function PostsPage() {
  const noma = getNomaServerClient()
  const result = await noma.content.list("posts", {
    state: "published",
    paginate: 12,
    sort: "created_at:desc",
  })
 
  const posts = "data" in result ? result.data : result
 
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.uuid}>
          <a href={`/posts/${post.uuid}`}>{String(post.fields?.title ?? post.uuid)}</a>
        </li>
      ))}
    </ul>
  )
}

Entry shapes are documented in Content. Adjust posts and field names to match your collection.

Dynamic routes

Use the segment param to load one entry:

// app/posts/[id]/page.tsx
import { notFound } from "next/navigation"
import { getNomaServerClient } from "@/lib/noma"
 
type Props = { params: Promise<{ id: string }> }
 
export default async function PostPage({ params }: Props) {
  const { id } = await params
  const noma = getNomaServerClient()
 
  try {
    const post = await noma.content.get("posts", id, { state: "published" })
    return (
      <article>
        <h1>{String(post.fields?.title ?? "")}</h1>
        {/* Render rich text / other fields from post.fields */}
      </article>
    )
  } catch {
    notFound()
  }
}

Route Handlers (API routes)

Use a Route Handler when you need a JSON API for the client, webhooks, or to keep sensitive logic on the server.

// app/api/posts/route.ts
import { NextResponse } from "next/server"
import { getNomaServerClient } from "@/lib/noma"
 
export async function GET() {
  const noma = getNomaServerClient()
  const result = await noma.content.list("posts", { state: "published", paginate: 20 })
  return NextResponse.json(result)
}

Prefer Server Components when you only need HTML—fewer moving parts and no extra HTTP hop.

Runtime: Node.js

The SDK uses HTTP from Node-friendly dependencies. Use the default Node.js runtime for Route Handlers that call Noma unless you have verified compatibility with the Edge runtime.

Caching and revalidation

Server Component fetches participate in Next.js caching. To refresh content after deploys or CMS updates, use revalidation (revalidate export, revalidatePath, or revalidateTag) where it fits your update model.

End users (project auth)

If your app signs in end users via Noma Project Auth, keep OAuth id_token exchange and token storage in Route Handlers or server actions—see the SDK README patterns and Sign Up & Sign In. Do not send provider tokens through client-only logs.

  • Nuxt and Astro - Same SDK patterns on other frameworks.
  • Installation & Setup - Full createClient options and project user auth.
  • Content API - Headers, abilities, and rate limits.
  • Quickstart - Create a project and collection from the dashboard.

Search documentation

Find guides and reference pages