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-sdkEnvironment 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.
Related
- Nuxt and Astro - Same SDK patterns on other frameworks.
- Installation & Setup - Full
createClientoptions and project user auth. - Content API - Headers, abilities, and rate limits.
- Quickstart - Create a project and collection from the dashboard.