Guides
Next.js Guide
App Router patterns for using Sazito SDK in both client and server contexts.
Runtime model
- Use
app/libfor shared SDK setup. - Use Client Components for browser interactions and token lifecycle.
- Use Server Components for read-heavy rendering.
- Use Server Actions for authenticated mutations.
1. Shared SDK files
// app/lib/sazito-client.ts
import { createSazitoClient } from '@sazito/client-sdk';
export const sazitoClient = createSazitoClient({
domain: process.env.NEXT_PUBLIC_SAZITO_DOMAIN!,
timeout: 15000,
});// app/lib/sazito-server.ts
import { createSazitoClient } from '@sazito/client-sdk';
export function getSazitoServerClient() {
return createSazitoClient({
domain: process.env.SAZITO_STORE_DOMAIN!,
timeout: 15000,
});
}2. Server Component example (parallel reads)
// app/[lang]/(store)/page.tsx
import { getSazitoServerClient } from '@/app/lib/sazito-server';
export default async function StorePage() {
const client = getSazitoServerClient();
const [productsRes, categoriesRes] = await Promise.all([
client.products.list({ page: 1, pageSize: 12, sort: 'newest' }),
client.categories.list({ page: 1, pageSize: 50 }),
]);
if (productsRes.error || categoriesRes.error) {
return <p>Failed to load storefront data.</p>;
}
return (
<section>
<h1>Storefront</h1>
<p>Products: {productsRes.data?.items.length ?? 0}</p>
<p>Categories: {categoriesRes.data?.categories.length ?? 0}</p>
</section>
);
}3. Client Component example (interactive query)
// app/[lang]/(store)/search-box.tsx
'use client';
import { useState } from 'react';
import { sazitoClient } from '@/app/lib/sazito-client';
export function SearchBox() {
const [query, setQuery] = useState('');
const [results, setResults] = useState<any[]>([]);
const [error, setError] = useState<string | null>(null);
async function runSearch() {
setError(null);
const res = await sazitoClient.search.query(query, { page: 1, pageSize: 10 }, { timeout: 8000 });
if (res.error) {
setError(res.error.message);
return;
}
setResults(res.data?.products.items ?? []);
}
return (
<div>
<input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search products" />
<button onClick={runSearch}>Search</button>
{error ? <p>{error}</p> : null}
<ul>{results.map((item) => <li key={item.url}>{item.name}</li>)}</ul>
</div>
);
}4. Authenticated Server Action example
// app/[lang]/account/wallet/actions.ts
'use server';
import { cookies } from 'next/headers';
import { getSazitoServerClient } from '@/app/lib/sazito-server';
export async function getWalletBalanceAction() {
const token = (await cookies()).get('user_id_token')?.value;
const client = getSazitoServerClient();
const res = await client.wallet.getBalance({
headers: token ? { Authorization: token } : undefined,
cache: false,
});
if (res.error) {
throw new Error(res.error.message);
}
return res.data;
}5. Usage in a Server Component
// app/[lang]/account/wallet/page.tsx
import { getWalletBalanceAction } from './actions';
export default async function WalletPage() {
const wallet = await getWalletBalanceAction();
return <pre>{JSON.stringify(wallet, null, 2)}</pre>;
}6. Checklist
- Keep
NEXT_PUBLIC_SAZITO_DOMAINfor browser code andSAZITO_STORE_DOMAINfor server code. - Use Server Components for initial page payload and SEO-critical data.
- Use Server Actions for authenticated writes and sensitive flows.
- Always branch on
res.errorbefore usingres.data.