@justanarthur/payload-www 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +381 -0
  2. package/dist/access.d.ts +11 -0
  3. package/dist/access.js +34 -0
  4. package/dist/blocks.d.ts +24 -0
  5. package/dist/blocks.js +75 -0
  6. package/dist/collections.d.ts +200 -0
  7. package/dist/collections.js +625 -0
  8. package/dist/components.d.ts +6 -0
  9. package/dist/components.js +38 -0
  10. package/dist/config.d.ts +100 -0
  11. package/dist/config.js +914 -0
  12. package/dist/core-access.d.ts +11 -0
  13. package/dist/core-access.js +34 -0
  14. package/dist/core-blocks.d.ts +24 -0
  15. package/dist/core-blocks.js +75 -0
  16. package/dist/core-fields.d.ts +36 -0
  17. package/dist/core-fields.js +134 -0
  18. package/dist/core-utils.d.ts +16 -0
  19. package/dist/core-utils.js +59 -0
  20. package/dist/data-collections.d.ts +200 -0
  21. package/dist/data-collections.js +625 -0
  22. package/dist/data-seed.d.ts +76 -0
  23. package/dist/data-seed.js +212 -0
  24. package/dist/data-test.d.ts +30 -0
  25. package/dist/data-test.js +1018 -0
  26. package/dist/fields.d.ts +36 -0
  27. package/dist/fields.js +134 -0
  28. package/dist/globals.d.ts +48 -0
  29. package/dist/globals.js +228 -0
  30. package/dist/hooks.d.ts +108 -0
  31. package/dist/hooks.js +196 -0
  32. package/dist/imagehash.d.ts +3 -0
  33. package/dist/imagehash.js +24 -0
  34. package/dist/import-map-provider.d.ts +20 -0
  35. package/dist/import-map-provider.js +26 -0
  36. package/dist/index.d.ts +6 -0
  37. package/dist/index.js +38 -0
  38. package/dist/metadata.d.ts +122 -0
  39. package/dist/metadata.js +335 -0
  40. package/dist/pages.d.ts +323 -0
  41. package/dist/pages.js +1016 -0
  42. package/dist/render-components.d.ts +42 -0
  43. package/dist/render-components.js +144 -0
  44. package/dist/render-metadata.d.ts +122 -0
  45. package/dist/render-metadata.js +335 -0
  46. package/dist/render-pages.d.ts +574 -0
  47. package/dist/render-pages.js +1450 -0
  48. package/dist/render-utils.d.ts +158 -0
  49. package/dist/render-utils.js +341 -0
  50. package/dist/seed.d.ts +76 -0
  51. package/dist/seed.js +212 -0
  52. package/dist/server.d.ts +922 -0
  53. package/dist/server.js +2055 -0
  54. package/dist/test.d.ts +30 -0
  55. package/dist/test.js +1018 -0
  56. package/dist/translator.d.ts +2 -0
  57. package/dist/translator.js +24 -0
  58. package/dist/utils.d.ts +16 -0
  59. package/dist/utils.js +59 -0
  60. package/dist/with-www-config.d.ts +100 -0
  61. package/dist/with-www-config.js +914 -0
  62. package/package.json +246 -0
package/README.md ADDED
@@ -0,0 +1,381 @@
1
+ # @justanarthur/payload-www
2
+
3
+ Reusable Payload CMS website template. Wires collections, globals,
4
+ blocks, fields, access, hooks, metadata (JSON-LD, hreflang), and
5
+ Next.js page renderers behind a single `createWWWConfig({ locales, blocks })`
6
+ composer. The lib consumes your [next-intl](https://next-intl.dev) routing
7
+ config so locale validation, URL shape, hreflang alternates, and the
8
+ language switcher share a single source of truth with the rest of your app.
9
+
10
+ ## What's inside
11
+
12
+ - **Composer** — `createWWWConfig({ locales, blocks, defaultPlugins? })` returns `{ withWWWConfig }`. One composer call is enough for the most common cases.
13
+ - **Collections** — `Pages` (title, blocks tab, slug, drafts, revalidation hook), `Posts` (title, excerpt, richText, drafts, revalidation hook), `StaticPages` (system pages — 404, 500, search-empty, … — addressed by a `kind` discriminator, not a slug)
14
+ - **Globals** — `Header` and `Footer` (both `nav` blocks with `navColumn` / `navItem`)
15
+ - **Default render components** — `PagesPage`, `HeaderPage`, `FooterPage` Server Components. Override any of them by setting a different `custom.path` on the collection / global.
16
+ - **LivePreviewListener** — built in. The lib's `createCollectionPageExports` default page renders it (via `React.lazy` so the server dist stays free of `'use client'` imports) whenever Next.js draft mode is on. Hosts get live preview automatically — no opt-in required. The component itself is also exported from `/render-components` for hosts that want to mount it elsewhere.
17
+ - **Hooks** — `createRevalidateCollectionHook(opts)` (canonical factory for **all** collections: Pages, Posts, host-defined; per-locale `revalidatePath` fan-out + `revalidateTag('collection_<slug>_<id>', 'max')` + sitemap tag, with a `pathMode: 'tag-only'` mode for collections without a URL like `staticPages`), `createRevalidatePageHooks()` (deprecated alias for Pages preset), `createRevalidateGlobalHook(slug)` (per-locale tag for globals)
18
+ - **Access** — `anyone`, `authenticated`, `authenticatedOrPublished`
19
+ - **Fields** — `link`, `linkGroup` (with `disableLabel` / `appearances` / `localized` / `relationTo` / `overrides` options)
20
+ - **Metadata** — `buildArticleLd`, `buildBreadcrumbsLd`, `buildOrganizationLd`, `buildHreflangAlternates`, slug transforms, `queryDocBySlug` / `queryAllDocs` / `queryAllLocaleSlugs`
21
+ - **Pages** — `createCollectionPageExports` (Next.js App Router render factory), `addCollectionsToSitemap`. Supports a `showcase` sidebar and a `homeExtras` callback for the home route.
22
+ - **Components** — `LivePreviewListener`, `RenderBlocks`, `PageShowcase` (sidebar layout for demos / previews), `LocaleSwitcher` (server-renderable nav built from the page's hreflang alternates)
23
+ - **Route handlers** — `createPreviewHandler` (from the `/render-utils` subpath). The Next.js sitemap convention ships as `createSitemapFile` (same subpath) — it's a `MetadataRoute.Sitemap` factory for `app/(frontend)/sitemap.ts`, not a route handler, and it's `localePrefix`-aware.
24
+ - **Utils** — `getFromImportMap`, `generateImportName`, `renderCollectionModule`
25
+ - **Seed / Test** — `createBaseSeed` (publishes by default — pass `status: 'draft'` to keep a doc as a draft), `createTestPayload`
26
+
27
+ ## Quick start
28
+
29
+ ### 1. Wire the composer
30
+
31
+ ```ts
32
+ // payload.config.ts
33
+ import { buildConfig } from 'payload'
34
+ import { createWWWConfig } from '@justanarthur/payload-www/with-www-config'
35
+ import { MyCtaBlock, MyHeroBlock, MyRichTextBlock } from './blocks'
36
+
37
+ const { withWWWConfig } = createWWWConfig({
38
+ locales: ['en', 'sk', 'de'],
39
+ blocks: [MyCtaBlock, MyHeroBlock, MyRichTextBlock]
40
+ })
41
+
42
+ export default buildConfig(
43
+ withWWWConfig({
44
+ collections: [], // optional extra collections
45
+ globals: [], // optional extra globals
46
+ // ...rest of your config
47
+ })
48
+ )
49
+ ```
50
+
51
+ `withWWWConfig` injects `Pages`, `Header`, and `Footer` plus the lib's
52
+ default plugin set (seoPlugin, imageHashPlugin, translator). Use the
53
+ `defaultPlugins` callback to drop or extend the list:
54
+
55
+ ```ts
56
+ createWWWConfig({
57
+ locales: ['en', 'sk', 'de'],
58
+ blocks: [MyCtaBlock],
59
+ defaultPlugins: (defaults) => defaults.filter((p) => p !== translator)
60
+ })
61
+ ```
62
+
63
+ ### 2. Define your next-intl routing
64
+
65
+ The lib reads the same routing config next-intl uses, so URL shape,
66
+ locale validation, hreflang alternates, and the language switcher share
67
+ a single source of truth:
68
+
69
+ ```ts
70
+ // src/i18n/routing.ts
71
+ import { defineRouting } from 'next-intl/routing'
72
+
73
+ export const routing = defineRouting({
74
+ locales: ['en', 'uk'],
75
+ defaultLocale: 'en',
76
+ // 'as-needed' means `/about` for the default locale and
77
+ // `/uk/about` for the others — the lib mirrors this in
78
+ // hreflang alternates and the language switcher.
79
+ localePrefix: 'as-needed',
80
+ labels: { en: 'English', uk: 'Українська' }
81
+ })
82
+ ```
83
+
84
+ ### 3. Page exports
85
+
86
+ ```ts
87
+ // app/(frontend)/[locale]/page.tsx — home
88
+ // app/(frontend)/[locale]/[...slug]/page.tsx — catch-all
89
+ import { createCollectionPageExports } from '@justanarthur/payload-www/render-pages'
90
+ import configPromise from '@payload-config'
91
+ import { importMap } from '@/app/(payload)/admin/importMap.js'
92
+ import { routing } from '@/i18n/routing'
93
+
94
+ import { getServerSideURL } from '@/utilities/getURL'
95
+
96
+ const generateMeta = async ({ doc }) => ({ title: doc?.title })
97
+
98
+ const { default: Page, generateMetadata, generateStaticParams } =
99
+ createCollectionPageExports(
100
+ { config: configPromise, importMap, routing },
101
+ { getServerSideURL, generateMeta }
102
+ )
103
+
104
+ export default Page
105
+ export { generateMetadata, generateStaticParams }
106
+ ```
107
+
108
+ The lib auto-mounts its `LivePreviewListener` (loaded via `React.lazy`
109
+ so the server dist stays free of `'use client'` imports) whenever
110
+ Next.js draft mode is on. No opt-in required.
111
+
112
+ #### Showcase sidebar + home extras
113
+
114
+ The home route can render inside a `<PageShowcase>` two-column layout
115
+ (sidebar with metadata, JSON-LD, and a language switcher) and append a
116
+ `homeExtras` block (recent pages, recent posts, etc.):
117
+
118
+ ```ts
119
+ const { default: Page, generateMetadata, generateStaticParams } =
120
+ createCollectionPageExports(
121
+ { config: configPromise, importMap, routing },
122
+ {
123
+ getServerSideURL,
124
+ generateMeta,
125
+ showcase: { enabled: true }, // wrap in <PageShowcase>
126
+ homeExtras: async ({ locale }) => {
127
+ const { pages, posts } = await fetchRecent(locale)
128
+ return <RecentLists pages={pages} posts={posts} />
129
+ }
130
+ }
131
+ )
132
+ ```
133
+
134
+ `<PageShowcase>` and `<LocaleSwitcher>` are also exported individually
135
+ (from `/render-components` and `/render-utils` respectively) for hosts
136
+ that want to drop them in their own layouts.
137
+
138
+ ### 4. Route handlers — preview + sitemap
139
+
140
+ ```ts
141
+ // src/proxy.ts (replaces the deprecated src/middleware.ts)
142
+ import createMiddleware from 'next-intl/middleware'
143
+ import { routing } from '@/i18n/routing'
144
+ export default createMiddleware(routing)
145
+ export const config = {
146
+ matcher: ['/', '/((?!api|_next|_vercel|admin|next|.*\\..*).*)']
147
+ }
148
+ ```
149
+
150
+ ```ts
151
+ // app/(payload)/next/preview/route.ts
152
+ import { createPreviewHandler } from '@justanarthur/payload-www/render-utils'
153
+ export const GET = createPreviewHandler()
154
+ ```
155
+
156
+ ```ts
157
+ // app/(frontend)/sitemap.ts
158
+ import { createSitemapFile } from '@justanarthur/payload-www/render-utils'
159
+ import configPromise from '@payload-config'
160
+ import { getServerSideURL } from '@/utilities/getURL'
161
+
162
+ // One file, all collections, all locales — Next.js serves it at
163
+ // /sitemap.xml. The Pages collection's `afterChange` hook invalidates
164
+ // the `pages-sitemap` tag the factory reads from, so edits refresh
165
+ // the sitemap automatically.
166
+ export default createSitemapFile({
167
+ collections: ['pages', 'posts'],
168
+ config: configPromise,
169
+ getServerSideURL,
170
+ // 'as-needed' makes the default locale render without a prefix
171
+ // (`/about`), other locales prefixed (`/uk/about`). Matches the
172
+ // host's next-intl `localePrefix` so sitemap URLs match the
173
+ // actual route shape.
174
+ localePrefix: 'as-needed',
175
+ // Collections mounted under a sub-route (here: Posts at
176
+ // `/posts/[...slug]`) need their sitemap URLs prefixed so they
177
+ // match the real route. Pages live at the root, so no prefix.
178
+ urlPrefixes: { posts: '/posts' }
179
+ })
180
+ ```
181
+
182
+ The Pages collection's `afterChange` hook revalidates the
183
+ `pages-sitemap` tag the sitemap factory reads from.
184
+
185
+ ### 5. System pages (404, 500, search-empty, …)
186
+
187
+ The lib ships a `StaticPages` collection for pages that don't map to a
188
+ slug-based URL. One row per `kind` discriminator (`'not-found'`,
189
+ `'server-error'`, `'search-empty'`, `'offline'`). The host's route
190
+ file fetches the row and renders it via `createStaticPageExports` —
191
+ the same shape as `createCollectionPageExports`, minus the
192
+ metadata / sitemap / static-params plumbing (system pages have no
193
+ URL):
194
+
195
+ ```ts
196
+ // app/(frontend)/[locale]/not-found.tsx
197
+ import configPromise from '@payload-config'
198
+ import { createStaticPageExports } from '@justanarthur/payload-www/render-pages'
199
+ import { importMap } from '@/app/(payload)/admin/importMap.js'
200
+
201
+ const { default: NotFound } = createStaticPageExports({
202
+ config: configPromise,
203
+ importMap,
204
+ })
205
+
206
+ export default NotFound
207
+ ```
208
+
209
+ `createStaticPageExports` reads the active locale via
210
+ `getLocale()` from `next-intl/server` (Next.js passes no props to
211
+ not-found components, so the URL-segment locale comes from the
212
+ request config — middleware sets it, the host's `i18n/request.ts`
213
+ falls back to `defaultLocale` for invalid values). Adding a
214
+ `server-error.tsx` is the same shape with `kind: 'server-error'`.
215
+
216
+ Editors create the row in admin (under the `System` group), pick a
217
+ `kind`, and populate the `blocks` tab using the same block set you
218
+ passed to `createWWWConfig({ blocks })`. The `title` field is
219
+ admin-only — not rendered. `kind` is `unique`, so the database
220
+ enforces one row per system page. Drafts + autosave mirror `pages`.
221
+ The translator plugin includes `'static-pages'` in its default
222
+ `collections` list, so SK content fills automatically when you expand
223
+ `localization.locales`.
224
+
225
+ Revalidation uses the `pathMode: 'tag-only'` branch of
226
+ `createRevalidateCollectionHook` — no URL fan-out (system pages have
227
+ no slug), but the per-id tag (`collection_static-pages_<id>`) and the
228
+ collection-wide tag (`static-pages` via the `sitemapTag` override)
229
+ fire on every change.
230
+
231
+ ## Public API
232
+
233
+ The root import gives you the full surface:
234
+
235
+ ```ts
236
+ import {
237
+ createWWWConfig, // composer (default export)
238
+ createPagesCollection, // collection factories
239
+ createPostsCollection,
240
+ createStaticPagesCollection,
241
+ createHeaderGlobal,
242
+ createFooterGlobal,
243
+ generatePreviewPath, // admin.preview URL builder
244
+ HOME_PAGE_SLUG, PAGES_SLUG, POSTS_SLUG, STATIC_PAGES_SLUG,
245
+ link, linkGroup, // fields
246
+ appearanceOptions,
247
+ anyone, authenticated, // access
248
+ authenticatedOrPublished,
249
+ createRevalidatePageHooks, // hooks
250
+ createRevalidateCollectionHook, // hooks (canonical; createRevalidatePageHooks is a deprecated Pages preset)
251
+ createRevalidateGlobalHook,
252
+ buildArticleLd, // metadata
253
+ buildBreadcrumbsLd,
254
+ buildOrganizationLd,
255
+ buildHreflangAlternates,
256
+ queryDocBySlug, queryAllDocs, queryAllLocaleSlugs,
257
+ segmentsToStoredSlug, segmentsToUrlPath, storedSlugToSegments,
258
+ getUrlPath, buildCanonicalUrl,
259
+ createCollectionPageExports, // page factory
260
+ addCollectionsToSitemap,
261
+ LivePreviewListener, RenderBlocks, // components
262
+ PageShowcase, LocaleSwitcher, // demo / preview components
263
+ getFromImportMap, generateImportName, renderCollectionModule, // utils
264
+ createBaseSeed, createTestPayload, // dev
265
+ // constants
266
+ PAGES_RENDER_PATH, HEADER_RENDER_PATH, FOOTER_RENDER_PATH, PAGES_SITEMAP_TAG
267
+ } from '@justanarthur/payload-www'
268
+ ```
269
+
270
+ Subpath imports:
271
+
272
+ | Subpath | What's there |
273
+ |----------------------------------|-------------------------------------------------------------|
274
+ | `@justanarthur/payload-www` | root: `LivePreviewListener` only (client-safe) |
275
+ | `@justanarthur/payload-www/server` | everything else |
276
+ | `@justanarthur/payload-www/with-www-config` | `createWWWConfig` (default export) |
277
+ | `@justanarthur/payload-www/collections` | `createPagesCollection`, `createHeaderGlobal`, `createFooterGlobal` |
278
+ | `@justanarthur/payload-www/globals` | `createHeaderGlobal`, `createFooterGlobal` |
279
+ | `@justanarthur/payload-www/hooks` | revalidation hooks |
280
+ | `@justanarthur/payload-www/pages` | `createCollectionPageExports`, `addCollectionsToSitemap` |
281
+ | `@justanarthur/payload-www/render-pages` | same as `/pages` + `PagesPage` / `HeaderPage` / `FooterPage` / `PageShowcase` |
282
+ | `@justanarthur/payload-www/render-utils` | `createPreviewHandler`, `createSitemapFile`, `LivePreviewListener`, `LocaleSwitcher` |
283
+ | `@justanarthur/payload-www/render-components` | `LivePreviewListener` |
284
+ | `@justanarthur/payload-www/render-metadata` | JSON-LD + hreflang + slug utilities |
285
+ | `@justanarthur/payload-www/metadata` | same as `/render-metadata` |
286
+ | `@justanarthur/payload-www/fields` | `link`, `linkGroup`, `appearanceOptions` |
287
+ | `@justanarthur/payload-www/access` | `anyone`, `authenticated`, `authenticatedOrPublished` |
288
+ | `@justanarthur/payload-www/blocks` | `RenderBlocks` |
289
+ | `@justanarthur/payload-www/components` | `LivePreviewListener` |
290
+ | `@justanarthur/payload-www/utils` | `getFromImportMap`, `generateImportName`, `renderCollectionModule` |
291
+ | `@justanarthur/payload-www/seed` | `createBaseSeed` |
292
+ | `@justanarthur/payload-www/test` | `createTestPayload` |
293
+ | `@justanarthur/payload-www/data-seed` | same as `/seed` |
294
+ | `@justanarthur/payload-www/data-test` | same as `/test` |
295
+ | `@justanarthur/payload-www/data-collections` | collection factories |
296
+ | `@justanarthur/payload-www/config` | `createWWWConfig` (default export) |
297
+ | `@justanarthur/payload-www/imagehash` | `imageHashPlugin` re-export |
298
+ | `@justanarthur/payload-www/translator` | `translator` re-export |
299
+
300
+ ## Configuration reference
301
+
302
+ `createWWWConfig({ ... })`:
303
+
304
+ | Option | Type | Required | Description |
305
+ |------------------|-----------------------------------|----------|------------------------------------------------------------------------|
306
+ | `locales` | `string[]` | yes | Locale list. First entry is the default locale (translation source). |
307
+ | `routing` | `PageRouting` | no | The host's next-intl `defineRouting({...})` result. When passed, `locales`, `defaultLocale`, and `localePrefix` are read from this object. `localePrefix` accepts both the simple string form and next-intl's verbose `{ mode, prefixes? }` shape (normalized internally). |
308
+ | `blocks` | `Block[]` | yes | Blocks the Pages collection accepts. |
309
+ | `linkRelationTo` | `string[]` | no | Collection slugs the Header / Footer nav links can reference. Default: `['pages']`. |
310
+ | `registerPosts` | `boolean` | no | Register the lib's Posts collection. Default `true`. |
311
+ | StaticPages | — | yes | Always registered (every site has 404). Hosts filter it out in `collections:` to opt. |
312
+ | `defaultPlugins` | `(defaults: Plugin[]) => Plugin[]`| no | Final say on the default `[seoPlugin, imageHashPlugin, translator]` list. |
313
+
314
+ `createRevalidateCollectionHook({ collectionSlug, urlPathPrefix?, sitemapTag?, localePrefix?, defaultLocale? })`:
315
+
316
+ | Option | Type | Description |
317
+ |------------------|-----------------------------------|------------------------------------------------------------------------|
318
+ | `collectionSlug` | `string` | Required. The collection's slug. Used in the `collection_<slug>_<id>` tag. |
319
+ | `urlPathPrefix` | `string` | URL path prefix. `''` for root-mounted (Pages), `'/posts'` for Posts. Default `''`. |
320
+ | `sitemapTag` | `string \| false` | Tag fired alongside paths. Default `${collectionSlug}-sitemap`. Pass `false` to opt out. |
321
+ | `localePrefix` | `'always' \| 'as-needed' \| 'never'` | Mirrors next-intl. Default `'always'`. Set to `'as-needed'` (with `defaultLocale`) when the host uses as-needed routing. |
322
+ | `defaultLocale` | `string` | Default locale for `localePrefix: 'as-needed'`. Falls back to `req.payload.config.localization.defaultLocale`. |
323
+ | `pathMode` | `'url' \| 'tag-only'` | Default `'url'` — fans out `revalidatePath` per locale × slug. Set `'tag-only'` for collections without a URL (e.g. `staticPages`); the hook still fires the per-id tag (`collection_<slug>_<id>`) and the collection-wide tag (via `sitemapTag`). |
324
+
325
+ The canonical hook for all collections — Pages, Posts, and host-defined. Pages internally uses this with `collectionSlug: 'pages'`, `urlPathPrefix: ''`. Fires `revalidatePath` for **every** declared locale (not just the request locale), handles slug renames while published, fires `revalidateTag('collection_<slug>_<id>', 'max')` for hosts that cache by id, and respects `req.context.disableRevalidate` for seed scripts.
326
+
327
+ `createRevalidatePageHooks()` is a deprecated alias for `createRevalidateCollectionHook({ collectionSlug: 'pages', urlPathPrefix: '' })` — kept for backward compat with hosts that imported this name directly.
328
+
329
+ `createCollectionPageExports({ config, importMap, slug?, renderPath?, routing }, deps, options?)`:
330
+
331
+ | Param | Type | Description |
332
+ |--------------|-----------------|------------------------------------------------------------------------|
333
+ | `config` | `Promise<SanitizedConfig>` | Resolved Payload config from `payload.config.ts` |
334
+ | `importMap` | `ImportMap` | The host's `app/(payload)/admin/importMap.js` |
335
+ | `slug` | `string` | Default `'pages'` |
336
+ | `renderPath` | `string` | Override the lib's `PAGES_RENDER_PATH` |
337
+ | `routing` | `PageRouting` | The host's `defineRouting({...})` result — drives URL building, hreflang, and the language switcher |
338
+ | `deps.getServerSideURL` | `() => string` | Host's absolute URL helper |
339
+ | `deps.generateMeta` | `(args) => Promise<Metadata>` | Host's metadata composer |
340
+ | `deps.notFoundOnMissing` | `boolean` | Default `true` — render 404 for unknown slugs |
341
+ | `deps.showcase` | `ShowcaseOptions \| false` | When `{ enabled: true }`, wraps the body in `<PageShowcase>` |
342
+ | `deps.homeExtras` | `(args) => ReactNode \| Promise<ReactNode>` | Content appended to the home route (slug = `''`) |
343
+ | `options.jsonLd` | `boolean \| JsonLdEntry[]` | Default `{ type: 'website' }` for every page |
344
+ | `options.changefreq` | `string` | Default `'weekly'` |
345
+ | `options.priority` | `number` | Default `0.5` |
346
+ | `options.websiteName` | `string` | Override the auto-generated `WebSite` JSON-LD `name` |
347
+
348
+ `createSitemapFile({ ... })`:
349
+
350
+ | Option | Type | Description |
351
+ |-----------------|-----------------|------------------------------------------------------------------------|
352
+ | `collections` | `string[]` | Collection slugs whose docs appear in the sitemap |
353
+ | `config` | `Promise<any>` | The Payload config promise |
354
+ | `getServerSideURL` | `() => string` | Host's absolute URL helper |
355
+ | `localePrefix` | `'always' \| 'as-needed' \| 'never'` | Default `'always'`. Mirrors next-intl's `localePrefix` so the sitemap URLs match the host's route shape. With `'as-needed'`, the default locale renders without a prefix. |
356
+ | `locales` | `string[]` | Optional locale filter. Defaults to every `config.localization.locales`. |
357
+ | `urlPrefixes` | `Record<string, string>` | Per-collection URL path prefix. Default `''`. Pass `{ posts: '/posts' }` for a collection mounted under a sub-route. |
358
+ | `perCollection` | `Record<string, { priority?, changefreq? }>` | Per-collection overrides |
359
+
360
+ ## Migration notes
361
+
362
+ - `src/middleware.ts` is deprecated in favor of `src/proxy.ts` (next-intl ≥4). The lib doesn't ship a middleware — wire `createMiddleware(routing)` in your own `proxy.ts`.
363
+ - `PageRouting` is a new required arg on `createCollectionPageExports`. It's a structural subset of the next-intl `defineRouting` result (locales, defaultLocale, localePrefix, labels), so passing your routing object directly works.
364
+ - `createBaseSeed` now sets `_status: 'published'` on created / updated pages and posts by default. Pass `status: 'draft'` per entry to keep it as a draft.
365
+
366
+ ## Building
367
+
368
+ ```bash
369
+ bun install
370
+ bun run build # produces dist/ via bunup
371
+ bun run typecheck # tsc --noEmit
372
+ bun run test # vitest run
373
+ ```
374
+
375
+ The lib is built with the same `bunup` + `exports` plugin pattern as
376
+ the monorepo's other plugins. One shim file per subpath under
377
+ `src/exports/`, each re-exports from the implementation.
378
+
379
+ ## License
380
+
381
+ MIT
@@ -0,0 +1,11 @@
1
+ import { Access } from "payload";
2
+ declare const anyone: Access;
3
+ declare const authenticated: Access;
4
+ declare const authenticatedOrPublished: Access;
5
+ import { Access as Access_wc6ft0 } from "payload";
6
+ declare const _default: {
7
+ anyone: Access_wc6ft0;
8
+ authenticated: Access_wc6ft0;
9
+ authenticatedOrPublished: Access_wc6ft0;
10
+ };
11
+ export { _default as default, authenticatedOrPublished, authenticated, anyone };
package/dist/access.js ADDED
@@ -0,0 +1,34 @@
1
+
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
+
18
+ // src/core/access/index.ts
19
+ var anyone = () => true;
20
+ var authenticated = ({ req: { user } }) => Boolean(user);
21
+ var authenticatedOrPublished = ({ req: { user } }) => {
22
+ if (user)
23
+ return true;
24
+ return { _status: { equals: "published" } };
25
+ };
26
+
27
+ // src/exports/access.ts
28
+ var access_default = { anyone, authenticated, authenticatedOrPublished };
29
+ export {
30
+ access_default as default,
31
+ authenticatedOrPublished,
32
+ authenticated,
33
+ anyone
34
+ };
@@ -0,0 +1,24 @@
1
+ import { FC } from "react";
2
+ import { ImportMap, SanitizedConfig } from "payload";
3
+ type RenderBlocksProps = {
4
+ blocks: Array<{
5
+ blockType: string;
6
+ } & Record<string, unknown>>;
7
+ blockProps?: Record<string, unknown>;
8
+ importMap: ImportMap;
9
+ config: SanitizedConfig;
10
+ locale: string;
11
+ searchParams?: Record<string, string | string[] | undefined>;
12
+ };
13
+ /**
14
+ * Render a page's `blocks` array to React. Each block's render module
15
+ * is resolved via Payload's generated importMap. The host registers
16
+ * each block in the importMap with a key like `BlockCta#default` (use
17
+ * `generateImportName('block', 'cta')` to build the key).
18
+ *
19
+ * Falls back gracefully: if a block's importMap path is missing or
20
+ * the component is not registered, the block is skipped and a
21
+ * `console.warn` is logged (in dev).
22
+ */
23
+ declare const RenderBlocks: FC<RenderBlocksProps>;
24
+ export { RenderBlocks as default, RenderBlocksProps, RenderBlocks };
package/dist/blocks.js ADDED
@@ -0,0 +1,75 @@
1
+
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
+
18
+ // src/core/utils/getFromImportMap.ts
19
+ function getFromImportMap(key, importMap) {
20
+ return importMap[key.includes("#") ? key : key + "#default"];
21
+ }
22
+
23
+ // src/core/utils/generateImportName.ts
24
+ function generateImportName(type, slug) {
25
+ switch (type) {
26
+ case "block":
27
+ return `Block${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
28
+ case "page":
29
+ return `Page${slug.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase())}#default`;
30
+ default:
31
+ throw new Error(`Unknown type: ${type}`);
32
+ }
33
+ }
34
+
35
+ // src/render/blocks/renderBlocks.tsx
36
+ import { jsx, Fragment } from "react/jsx-runtime";
37
+ var RenderBlocks = ({
38
+ blocks,
39
+ blockProps,
40
+ config,
41
+ importMap,
42
+ locale,
43
+ searchParams
44
+ }) => {
45
+ if (!blocks || !Array.isArray(blocks) || blocks.length === 0)
46
+ return null;
47
+ const rendered = [];
48
+ for (let i = 0;i < blocks.length; i++) {
49
+ const block = blocks[i];
50
+ const { blockType } = block;
51
+ const importMapPath = config.admin?.dependencies?.[blockType]?.path ?? generateImportName("block", blockType);
52
+ const Block = getFromImportMap(importMapPath, importMap);
53
+ if (!Block) {
54
+ console.warn(`No block found for type: ${blockType}, config.admin?.dependencies?.[blockType]: ${config.admin?.dependencies?.[blockType]}`);
55
+ continue;
56
+ }
57
+ rendered.push(/* @__PURE__ */ jsx(Block, {
58
+ index: i,
59
+ ...blockProps,
60
+ ...block,
61
+ locale,
62
+ searchParams
63
+ }, i));
64
+ }
65
+ return /* @__PURE__ */ jsx(Fragment, {
66
+ children: rendered
67
+ });
68
+ };
69
+
70
+ // src/exports/blocks.ts
71
+ var blocks_default = RenderBlocks;
72
+ export {
73
+ blocks_default as default,
74
+ RenderBlocks
75
+ };