mirror of
https://github.com/complexcaresolutions/frontend.blogwoman.de.git
synced 2026-03-17 16:14:00 +00:00
feat: migrate API layer to @c2s/payload-contracts
- Add @c2s/payload-contracts as shared API client dependency - Create src/lib/cms.ts with tenant-configured PayloadClient instance - Replace manual fetch logic in api.ts with contracts client calls - Add transpilePackages config for TypeScript source imports - Local types preserved for component compatibility (bridge pattern) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ba54d7a85d
commit
2500b8b16f
5 changed files with 167 additions and 274 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
transpilePackages: ["@c2s/payload-contracts"],
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
"next": "16.0.10",
|
||||
"react": "19.2.1",
|
||||
"react-dom": "19.2.1",
|
||||
"tailwind-merge": "^3.4.0"
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"@c2s/payload-contracts": "github:complexcaresolutions/payload-contracts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
'@c2s/payload-contracts':
|
||||
specifier: github:complexcaresolutions/payload-contracts
|
||||
version: git+https://git@github.com:complexcaresolutions/payload-contracts.git#64847594b2150bfdce09a7bd7f54ad2f52d6f2b7(react@19.2.1)
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
|
|
@ -122,6 +125,15 @@ packages:
|
|||
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@c2s/payload-contracts@git+https://git@github.com:complexcaresolutions/payload-contracts.git#64847594b2150bfdce09a7bd7f54ad2f52d6f2b7':
|
||||
resolution: {commit: 64847594b2150bfdce09a7bd7f54ad2f52d6f2b7, repo: git@github.com:complexcaresolutions/payload-contracts.git, type: git}
|
||||
version: 1.0.0
|
||||
peerDependencies:
|
||||
react: ^19.0.0
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
|
||||
'@emnapi/core@1.7.1':
|
||||
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
|
||||
|
||||
|
|
@ -2021,6 +2033,10 @@ snapshots:
|
|||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.28.5
|
||||
|
||||
'@c2s/payload-contracts@git+https://git@github.com:complexcaresolutions/payload-contracts.git#64847594b2150bfdce09a7bd7f54ad2f52d6f2b7(react@19.2.1)':
|
||||
optionalDependencies:
|
||||
react: 19.2.1
|
||||
|
||||
'@emnapi/core@1.7.1':
|
||||
dependencies:
|
||||
'@emnapi/wasi-threads': 1.1.0
|
||||
|
|
|
|||
385
src/lib/api.ts
385
src/lib/api.ts
|
|
@ -1,80 +1,36 @@
|
|||
/**
|
||||
* Payload CMS API functions — powered by @c2s/payload-contracts
|
||||
*
|
||||
* Uses the shared API client for transport (tenant isolation, fetch caching)
|
||||
* but returns data typed with local interfaces for component compatibility.
|
||||
*
|
||||
* The local types use simplified interfaces (e.g. id: string, meta instead of seo)
|
||||
* while the contracts use the real CMS types. We use 'as unknown as' to bridge.
|
||||
*/
|
||||
import { cms } from "./cms"
|
||||
import type {
|
||||
Page,
|
||||
Post,
|
||||
Navigation,
|
||||
SiteSettings,
|
||||
Favorite,
|
||||
Series,
|
||||
Testimonial,
|
||||
FAQ,
|
||||
SeoSettings,
|
||||
PaginatedResponse,
|
||||
FavoriteCategory,
|
||||
FavoriteBadge,
|
||||
} from './types'
|
||||
SiteSettings,
|
||||
} from "./types"
|
||||
|
||||
const PAYLOAD_URL = process.env.NEXT_PUBLIC_PAYLOAD_URL || 'https://cms.c2sgmbh.de'
|
||||
const TENANT_ID = process.env.NEXT_PUBLIC_TENANT_ID || '9'
|
||||
|
||||
// Shared empty paginated response for error fallbacks
|
||||
const emptyPaginatedResponse = { docs: [], totalDocs: 0, limit: 10, totalPages: 0, page: 1, pagingCounter: 1, hasPrevPage: false, hasNextPage: false, prevPage: null, nextPage: null }
|
||||
|
||||
interface FetchOptions {
|
||||
revalidate?: number | false
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
async function fetchAPI<T>(
|
||||
endpoint: string,
|
||||
options: FetchOptions & { defaultValue?: T } = {}
|
||||
): Promise<T> {
|
||||
const { revalidate = 60, tags, defaultValue } = options
|
||||
|
||||
try {
|
||||
const res = await fetch(`${PAYLOAD_URL}${endpoint}`, {
|
||||
next: {
|
||||
revalidate,
|
||||
tags,
|
||||
},
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
console.error(`API error: ${res.status} ${res.statusText} for ${endpoint}`)
|
||||
if (defaultValue !== undefined) {
|
||||
return defaultValue
|
||||
}
|
||||
throw new Error(`API error: ${res.status} ${res.statusText}`)
|
||||
}
|
||||
|
||||
return res.json()
|
||||
} catch (error) {
|
||||
console.error(`Fetch error for ${endpoint}:`, error)
|
||||
if (defaultValue !== undefined) {
|
||||
return defaultValue
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
const PAYLOAD_URL = process.env.NEXT_PUBLIC_PAYLOAD_URL || "https://cms.c2sgmbh.de"
|
||||
const TENANT_ID = process.env.NEXT_PUBLIC_TENANT_ID || "9"
|
||||
|
||||
// Pages
|
||||
export async function getPage(
|
||||
slug: string,
|
||||
locale = 'de'
|
||||
): Promise<Page | null> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[slug][equals]': slug,
|
||||
'where[status][equals]': 'published',
|
||||
locale,
|
||||
depth: '2',
|
||||
export async function getPage(slug: string, locale = "de"): Promise<Page | null> {
|
||||
const result = await cms.pages.getPage(slug, {
|
||||
locale: locale as "de" | "en",
|
||||
depth: 2,
|
||||
})
|
||||
|
||||
const data = await fetchAPI<PaginatedResponse<Page>>(
|
||||
`/api/pages?${params}`,
|
||||
{ tags: [`page-${slug}`] }
|
||||
)
|
||||
|
||||
return data.docs[0] || null
|
||||
return result as unknown as Page | null
|
||||
}
|
||||
|
||||
export async function getPages(options: {
|
||||
|
|
@ -82,41 +38,26 @@ export async function getPages(options: {
|
|||
page?: number
|
||||
locale?: string
|
||||
} = {}): Promise<PaginatedResponse<Page>> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[status][equals]': 'published',
|
||||
limit: String(options.limit || 100),
|
||||
page: String(options.page || 1),
|
||||
locale: options.locale || 'de',
|
||||
depth: '1',
|
||||
const result = await cms.pages.getPages({
|
||||
limit: options.limit || 100,
|
||||
page: options.page || 1,
|
||||
locale: (options.locale || "de") as "de" | "en",
|
||||
depth: 1,
|
||||
})
|
||||
|
||||
return fetchAPI<PaginatedResponse<Page>>(`/api/pages?${params}`)
|
||||
return result as unknown as PaginatedResponse<Page>
|
||||
}
|
||||
|
||||
// Posts
|
||||
export async function getPost(
|
||||
slug: string,
|
||||
locale = 'de'
|
||||
): Promise<Post | null> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[slug][equals]': slug,
|
||||
'where[status][equals]': 'published',
|
||||
locale,
|
||||
depth: '2',
|
||||
export async function getPost(slug: string, locale = "de"): Promise<Post | null> {
|
||||
const result = await cms.posts.getPost(slug, {
|
||||
locale: locale as "de" | "en",
|
||||
depth: 2,
|
||||
})
|
||||
|
||||
const data = await fetchAPI<PaginatedResponse<Post>>(
|
||||
`/api/posts?${params}`,
|
||||
{ tags: [`post-${slug}`] }
|
||||
)
|
||||
|
||||
return data.docs[0] || null
|
||||
return result as unknown as Post | null
|
||||
}
|
||||
|
||||
export async function getPosts(options: {
|
||||
type?: 'blog' | 'news' | 'press' | 'announcement'
|
||||
type?: string
|
||||
category?: string
|
||||
series?: string
|
||||
limit?: number
|
||||
|
|
@ -124,83 +65,53 @@ export async function getPosts(options: {
|
|||
locale?: string
|
||||
featured?: boolean
|
||||
} = {}): Promise<PaginatedResponse<Post>> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[status][equals]': 'published',
|
||||
sort: '-publishedAt',
|
||||
limit: String(options.limit || 10),
|
||||
page: String(options.page || 1),
|
||||
locale: options.locale || 'de',
|
||||
depth: '1',
|
||||
try {
|
||||
const where: Record<string, unknown> = {}
|
||||
if (options.featured) where["isFeatured][equals"] = "true"
|
||||
|
||||
const result = await cms.posts.getPosts({
|
||||
type: options.type,
|
||||
category: options.category,
|
||||
series: options.series,
|
||||
limit: options.limit || 10,
|
||||
page: options.page || 1,
|
||||
locale: (options.locale || "de") as "de" | "en",
|
||||
where,
|
||||
})
|
||||
|
||||
if (options.type) {
|
||||
params.append('where[type][equals]', options.type)
|
||||
return result as unknown as PaginatedResponse<Post>
|
||||
} catch {
|
||||
return { docs: [], totalDocs: 0, limit: 10, totalPages: 0, page: 1, pagingCounter: 1, hasPrevPage: false, hasNextPage: false, prevPage: null, nextPage: null }
|
||||
}
|
||||
if (options.category) {
|
||||
params.append('where[categories][contains]', options.category)
|
||||
}
|
||||
if (options.series) {
|
||||
params.append('where[series][equals]', options.series)
|
||||
}
|
||||
if (options.featured) {
|
||||
params.append('where[isFeatured][equals]', 'true')
|
||||
}
|
||||
|
||||
return fetchAPI<PaginatedResponse<Post>>(
|
||||
`/api/posts?${params}`,
|
||||
{ tags: ['posts'], defaultValue: emptyPaginatedResponse as PaginatedResponse<Post> }
|
||||
)
|
||||
}
|
||||
|
||||
// Navigation
|
||||
export async function getNavigation(
|
||||
type: 'header' | 'footer' | 'mobile'
|
||||
): Promise<Navigation | null> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[type][equals]': type,
|
||||
depth: '2',
|
||||
})
|
||||
|
||||
const data = await fetchAPI<PaginatedResponse<Navigation>>(
|
||||
`/api/navigations?${params}`,
|
||||
{
|
||||
revalidate: 300,
|
||||
tags: [`navigation-${type}`],
|
||||
defaultValue: { docs: [], totalDocs: 0, limit: 10, totalPages: 0, page: 1, pagingCounter: 1, hasPrevPage: false, hasNextPage: false, prevPage: null, nextPage: null },
|
||||
export async function getNavigation(type: "header" | "footer" | "mobile"): Promise<Navigation | null> {
|
||||
try {
|
||||
const result = await cms.navigation.getNavigation(type, { depth: 2 })
|
||||
return result as unknown as Navigation | null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
)
|
||||
|
||||
return data.docs[0] || null
|
||||
}
|
||||
|
||||
// Site Settings
|
||||
export async function getSiteSettings(): Promise<SiteSettings | null> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
depth: '2',
|
||||
})
|
||||
|
||||
const data = await fetchAPI<PaginatedResponse<SiteSettings>>(
|
||||
`/api/site-settings?${params}`,
|
||||
{
|
||||
revalidate: 300,
|
||||
tags: ['site-settings'],
|
||||
defaultValue: { docs: [], totalDocs: 0, limit: 10, totalPages: 0, page: 1, pagingCounter: 1, hasPrevPage: false, hasNextPage: false, prevPage: null, nextPage: null },
|
||||
try {
|
||||
const result = await cms.settings.getSiteSettings({ depth: 2 })
|
||||
return result as unknown as SiteSettings | null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
)
|
||||
|
||||
return data.docs[0] || null
|
||||
}
|
||||
|
||||
// SEO Settings (Global)
|
||||
export async function getSeoSettings(): Promise<SeoSettings | null> {
|
||||
return fetchAPI<SeoSettings>('/api/globals/seo-settings', {
|
||||
revalidate: 3600,
|
||||
tags: ['seo-settings'],
|
||||
defaultValue: null as unknown as SeoSettings,
|
||||
})
|
||||
try {
|
||||
const result = await cms.settings.getSeoSettings()
|
||||
return result as unknown as SeoSettings | null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// Testimonials
|
||||
|
|
@ -208,17 +119,12 @@ export async function getTestimonials(options: {
|
|||
limit?: number
|
||||
locale?: string
|
||||
} = {}): Promise<PaginatedResponse<Testimonial>> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
limit: String(options.limit || 10),
|
||||
locale: options.locale || 'de',
|
||||
depth: '1',
|
||||
const result = await cms.client.getCollection("testimonials", {
|
||||
limit: options.limit || 10,
|
||||
locale: (options.locale || "de") as "de" | "en",
|
||||
depth: 1,
|
||||
})
|
||||
|
||||
return fetchAPI<PaginatedResponse<Testimonial>>(
|
||||
`/api/testimonials?${params}`,
|
||||
{ tags: ['testimonials'] }
|
||||
)
|
||||
return result as unknown as PaginatedResponse<Testimonial>
|
||||
}
|
||||
|
||||
// FAQs
|
||||
|
|
@ -227,72 +133,50 @@ export async function getFAQs(options: {
|
|||
limit?: number
|
||||
locale?: string
|
||||
} = {}): Promise<PaginatedResponse<FAQ>> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
sort: 'order',
|
||||
limit: String(options.limit || 50),
|
||||
locale: options.locale || 'de',
|
||||
depth: '1',
|
||||
const result = await cms.client.getCollection("faqs", {
|
||||
limit: options.limit || 50,
|
||||
locale: (options.locale || "de") as "de" | "en",
|
||||
sort: "order",
|
||||
depth: 1,
|
||||
where: options.category ? { "category][equals": options.category } : undefined,
|
||||
})
|
||||
|
||||
if (options.category) {
|
||||
params.append('where[category][equals]', options.category)
|
||||
}
|
||||
|
||||
return fetchAPI<PaginatedResponse<FAQ>>(
|
||||
`/api/faqs?${params}`,
|
||||
{ tags: ['faqs'] }
|
||||
)
|
||||
return result as unknown as PaginatedResponse<FAQ>
|
||||
}
|
||||
|
||||
// BlogWoman: Favorites
|
||||
export async function getFavorites(options: {
|
||||
category?: FavoriteCategory
|
||||
badge?: FavoriteBadge
|
||||
category?: string
|
||||
badge?: string
|
||||
limit?: number
|
||||
page?: number
|
||||
locale?: string
|
||||
} = {}): Promise<PaginatedResponse<Favorite>> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[isActive][equals]': 'true',
|
||||
limit: String(options.limit || 12),
|
||||
page: String(options.page || 1),
|
||||
locale: options.locale || 'de',
|
||||
depth: '1',
|
||||
try {
|
||||
const where: Record<string, unknown> = { "isActive][equals": "true" }
|
||||
if (options.category) where["category][equals"] = options.category
|
||||
if (options.badge) where["badge][equals"] = options.badge
|
||||
|
||||
const result = await cms.client.getCollection("favorites", {
|
||||
limit: options.limit || 12,
|
||||
page: options.page || 1,
|
||||
locale: (options.locale || "de") as "de" | "en",
|
||||
depth: 1,
|
||||
where,
|
||||
})
|
||||
|
||||
if (options.category) {
|
||||
params.append('where[category][equals]', options.category)
|
||||
return result as unknown as PaginatedResponse<Favorite>
|
||||
} catch {
|
||||
return { docs: [], totalDocs: 0, limit: 12, totalPages: 0, page: 1, pagingCounter: 1, hasPrevPage: false, hasNextPage: false, prevPage: null, nextPage: null }
|
||||
}
|
||||
if (options.badge) {
|
||||
params.append('where[badge][equals]', options.badge)
|
||||
}
|
||||
|
||||
return fetchAPI<PaginatedResponse<Favorite>>(
|
||||
`/api/favorites?${params}`,
|
||||
{ tags: ['favorites'], defaultValue: emptyPaginatedResponse as PaginatedResponse<Favorite> }
|
||||
)
|
||||
}
|
||||
|
||||
export async function getFavorite(
|
||||
slug: string,
|
||||
locale = 'de'
|
||||
): Promise<Favorite | null> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[slug][equals]': slug,
|
||||
'where[isActive][equals]': 'true',
|
||||
locale,
|
||||
depth: '1',
|
||||
export async function getFavorite(slug: string, locale = "de"): Promise<Favorite | null> {
|
||||
const data = await cms.client.getCollection("favorites", {
|
||||
locale: locale as "de" | "en",
|
||||
depth: 1,
|
||||
where: { "slug][equals": slug, "isActive][equals": "true" },
|
||||
limit: 1,
|
||||
})
|
||||
|
||||
const data = await fetchAPI<PaginatedResponse<Favorite>>(
|
||||
`/api/favorites?${params}`,
|
||||
{ tags: [`favorite-${slug}`] }
|
||||
)
|
||||
|
||||
return data.docs[0] || null
|
||||
return (data.docs[0] as unknown as Favorite) ?? null
|
||||
}
|
||||
|
||||
// BlogWoman: Series
|
||||
|
|
@ -300,58 +184,41 @@ export async function getSeries(options: {
|
|||
limit?: number
|
||||
locale?: string
|
||||
} = {}): Promise<PaginatedResponse<Series>> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[isActive][equals]': 'true',
|
||||
limit: String(options.limit || 20),
|
||||
locale: options.locale || 'de',
|
||||
depth: '2',
|
||||
try {
|
||||
const result = await cms.client.getCollection("series", {
|
||||
limit: options.limit || 20,
|
||||
locale: (options.locale || "de") as "de" | "en",
|
||||
depth: 2,
|
||||
where: { "isActive][equals": "true" },
|
||||
})
|
||||
|
||||
return fetchAPI<PaginatedResponse<Series>>(
|
||||
`/api/series?${params}`,
|
||||
{ tags: ['series'], defaultValue: emptyPaginatedResponse as PaginatedResponse<Series> }
|
||||
)
|
||||
return result as unknown as PaginatedResponse<Series>
|
||||
} catch {
|
||||
return { docs: [], totalDocs: 0, limit: 20, totalPages: 0, page: 1, pagingCounter: 1, hasPrevPage: false, hasNextPage: false, prevPage: null, nextPage: null }
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSeriesBySlug(
|
||||
slug: string,
|
||||
locale = 'de'
|
||||
): Promise<Series | null> {
|
||||
const params = new URLSearchParams({
|
||||
'where[tenant][equals]': TENANT_ID,
|
||||
'where[slug][equals]': slug,
|
||||
'where[isActive][equals]': 'true',
|
||||
locale,
|
||||
depth: '2',
|
||||
export async function getSeriesBySlug(slug: string, locale = "de"): Promise<Series | null> {
|
||||
const data = await cms.client.getCollection("series", {
|
||||
locale: locale as "de" | "en",
|
||||
depth: 2,
|
||||
where: { "slug][equals": slug, "isActive][equals": "true" },
|
||||
limit: 1,
|
||||
})
|
||||
|
||||
const data = await fetchAPI<PaginatedResponse<Series>>(
|
||||
`/api/series?${params}`,
|
||||
{ tags: [`series-${slug}`] }
|
||||
)
|
||||
|
||||
return data.docs[0] || null
|
||||
return (data.docs[0] as unknown as Series) ?? null
|
||||
}
|
||||
|
||||
// Newsletter Subscription
|
||||
export async function subscribeNewsletter(
|
||||
email: string,
|
||||
firstName?: string,
|
||||
source = 'website'
|
||||
source = "website"
|
||||
): Promise<{ success: boolean; message?: string }> {
|
||||
const res = await fetch(`${PAYLOAD_URL}/api/newsletter/subscribe`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
return cms.post("/api/newsletter/subscribe", {
|
||||
email,
|
||||
firstName,
|
||||
tenantId: Number(TENANT_ID),
|
||||
source,
|
||||
}),
|
||||
})
|
||||
|
||||
return res.json()
|
||||
}
|
||||
|
||||
// Contact Form Submission
|
||||
|
|
@ -363,20 +230,14 @@ export async function submitContactForm(data: {
|
|||
message: string
|
||||
formId?: number
|
||||
}): Promise<{ success: boolean; message?: string }> {
|
||||
const res = await fetch(`${PAYLOAD_URL}/api/form-submissions`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
return cms.post("/api/form-submissions", {
|
||||
form: data.formId || 1,
|
||||
submissionData: [
|
||||
{ field: 'name', value: data.name },
|
||||
{ field: 'email', value: data.email },
|
||||
{ field: 'phone', value: data.phone || '' },
|
||||
{ field: 'subject', value: data.subject },
|
||||
{ field: 'message', value: data.message },
|
||||
{ field: "name", value: data.name },
|
||||
{ field: "email", value: data.email },
|
||||
{ field: "phone", value: data.phone || "" },
|
||||
{ field: "subject", value: data.subject },
|
||||
{ field: "message", value: data.message },
|
||||
],
|
||||
}),
|
||||
})
|
||||
|
||||
return res.json()
|
||||
}
|
||||
|
|
|
|||
15
src/lib/cms.ts
Normal file
15
src/lib/cms.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Payload CMS Client — initialized from @c2s/payload-contracts
|
||||
*
|
||||
* Single shared client instance for all API calls.
|
||||
* Tenant isolation is handled automatically.
|
||||
*/
|
||||
import { createPayloadClient } from "@c2s/payload-contracts/api-client"
|
||||
|
||||
export const cms = createPayloadClient({
|
||||
baseUrl: process.env.NEXT_PUBLIC_PAYLOAD_URL || "https://cms.c2sgmbh.de",
|
||||
tenantId: process.env.NEXT_PUBLIC_TENANT_ID || "9",
|
||||
defaultLocale: "de",
|
||||
defaultDepth: 2,
|
||||
defaultRevalidate: 60,
|
||||
})
|
||||
Loading…
Reference in a new issue