@justanarthur/payload-www 0.1.2 → 0.2.0

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.
package/dist/data-test.js CHANGED
@@ -201,20 +201,25 @@ var createPagesCollection = (blocks, options = {}) => {
201
201
  renderPath = PAGES_RENDER_PATH,
202
202
  slug: collectionSlug = PAGES_SLUG2,
203
203
  localePrefix,
204
- defaultLocale
204
+ defaultLocale,
205
+ nested = false
205
206
  } = options;
207
+ const slugPattern = nested ? /^[a-z0-9_-]+$/ : /^[a-z0-9-]+$/;
206
208
  const slugField = {
207
209
  name: "slug",
208
210
  type: "text",
209
211
  required: true,
210
212
  unique: true,
211
213
  index: true,
212
- admin: { position: "sidebar" },
214
+ admin: {
215
+ position: "sidebar",
216
+ ...nested ? { description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`." } : {}
217
+ },
213
218
  validate: (value) => {
214
219
  if (typeof value !== "string")
215
220
  return "Slug must be a string";
216
- if (value !== "" && !/^[a-z0-9-]+$/.test(value)) {
217
- return "Slug must be lowercase, with hyphens (no spaces or special characters)";
221
+ if (value !== "" && !slugPattern.test(value)) {
222
+ return nested ? "Slug must be lowercase, with hyphens or the `_` nesting divider (no spaces or other special characters)" : "Slug must be lowercase, with hyphens (no spaces or special characters)";
218
223
  }
219
224
  return true;
220
225
  }
@@ -426,7 +431,8 @@ var link = (options = {}) => {
426
431
  disableLabel = false,
427
432
  relationTo = [PAGES_SLUG],
428
433
  localized = false,
429
- overrides = {}
434
+ overrides = {},
435
+ extraFields = []
430
436
  } = options;
431
437
  const result = {
432
438
  name: "link",
@@ -503,6 +509,9 @@ var link = (options = {}) => {
503
509
  options: opts
504
510
  });
505
511
  }
512
+ if (extraFields.length) {
513
+ result.fields.push(...extraFields);
514
+ }
506
515
  return { ...result, ...overrides };
507
516
  };
508
517
 
@@ -522,17 +531,22 @@ function createRevalidateGlobalHook(slug) {
522
531
 
523
532
  // src/data/collections/globals/Header/config.ts
524
533
  var createHeaderGlobal = (options = {}) => {
525
- const { renderPath = HEADER_RENDER_PATH, linkRelationTo = [PAGES_SLUG] } = options;
534
+ const {
535
+ renderPath = HEADER_RENDER_PATH,
536
+ linkRelationTo = [PAGES_SLUG],
537
+ navColumnLinkFields = [],
538
+ navItemLinkFields = []
539
+ } = options;
526
540
  const navColumnBlock = {
527
541
  slug: "navColumn",
528
542
  fields: [
529
543
  { name: "title", type: "text", required: true, localized: true },
530
- { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
544
+ { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
531
545
  ]
532
546
  };
533
547
  const navItemBlock = {
534
548
  slug: "navItem",
535
- fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
549
+ fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
536
550
  };
537
551
  return {
538
552
  slug: "header",
@@ -554,17 +568,22 @@ var createHeaderGlobal = (options = {}) => {
554
568
 
555
569
  // src/data/collections/globals/Footer/config.ts
556
570
  var createFooterGlobal = (options = {}) => {
557
- const { renderPath = FOOTER_RENDER_PATH, linkRelationTo = [PAGES_SLUG] } = options;
571
+ const {
572
+ renderPath = FOOTER_RENDER_PATH,
573
+ linkRelationTo = [PAGES_SLUG],
574
+ navColumnLinkFields = [],
575
+ navItemLinkFields = []
576
+ } = options;
558
577
  const navColumnBlock = {
559
578
  slug: "navColumn",
560
579
  fields: [
561
580
  { name: "title", type: "text", required: true, localized: true },
562
- { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
581
+ { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
563
582
  ]
564
583
  };
565
584
  const navItemBlock = {
566
585
  slug: "navItem",
567
- fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
586
+ fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
568
587
  };
569
588
  return {
570
589
  slug: "footer",
@@ -762,6 +781,7 @@ function createSitemapFile(options) {
762
781
  const collectionDefaults = options.perCollection?.[collectionSlug] ?? {};
763
782
  const urlPrefix = (options.urlPrefixes?.[collectionSlug] ?? "").replace(/\/$/, "");
764
783
  const siteUrl = options.getServerSideURL().replace(/\/$/, "");
784
+ const isNested = options.nested?.[collectionSlug] ?? false;
765
785
  for (const locale of activeLocales) {
766
786
  const docs = await queryAllDocs({
767
787
  collectionSlug,
@@ -777,13 +797,14 @@ function createSitemapFile(options) {
777
797
  if (seen.has(dedupeKey))
778
798
  continue;
779
799
  seen.add(dedupeKey);
780
- const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${storedSlug}`;
800
+ const slugPath = isNested ? storedSlug.replaceAll("_", "/") : storedSlug;
801
+ const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${slugPath}`;
781
802
  const languages = await buildHreflangAlternates({
782
803
  siteUrl,
783
804
  locale,
784
805
  urlPrefix,
785
806
  storedSlug,
786
- nested: false,
807
+ nested: isNested,
787
808
  homeSlug: "",
788
809
  defaultLocale,
789
810
  locales: activeLocales,
@@ -814,7 +835,7 @@ function createSitemapFile(options) {
814
835
  }
815
836
  // src/config/createWWWConfig.ts
816
837
  function createWWWConfig(options) {
817
- const { locales, routing, blocks, linkRelationTo, registerPosts = true, defaultPlugins } = options;
838
+ const { locales, routing, blocks, linkRelationTo, registerPosts = true, nested = false, defaultPlugins } = options;
818
839
  const defaultLocale = routing?.defaultLocale ?? locales[0] ?? "";
819
840
  const localePrefixMode = (() => {
820
841
  const raw = routing?.localePrefix;
@@ -827,7 +848,8 @@ function createWWWConfig(options) {
827
848
  }
828
849
  const buildPagesCollection = () => createPagesCollection(blocks, {
829
850
  localePrefix: localePrefixMode,
830
- defaultLocale
851
+ defaultLocale,
852
+ nested
831
853
  });
832
854
  const buildPostsCollection = () => createPostsCollection({
833
855
  localePrefix: localePrefixMode,
package/dist/fields.d.ts CHANGED
@@ -20,6 +20,14 @@ type LinkOptions = {
20
20
  overrides?: Partial<GroupField>;
21
21
  /** Legacy alias for the host's custom field overrides. */
22
22
  linkOverrides?: Partial<GroupField>;
23
+ /**
24
+ * Extra fields appended to the link group — e.g. a `description`
25
+ * text field or a `navHover` group for a mega-menu. Lets hosts
26
+ * extend the nav link schema without re-implementing the whole
27
+ * `link` field. Appended after the standard type/label/appearance
28
+ * fields.
29
+ */
30
+ extraFields?: Field[];
23
31
  };
24
32
  declare const link: (options?: LinkOptions) => Field;
25
33
  import { Field as Field2 } from "payload";
package/dist/fields.js CHANGED
@@ -36,7 +36,8 @@ var link = (options = {}) => {
36
36
  disableLabel = false,
37
37
  relationTo = [PAGES_SLUG],
38
38
  localized = false,
39
- overrides = {}
39
+ overrides = {},
40
+ extraFields = []
40
41
  } = options;
41
42
  const result = {
42
43
  name: "link",
@@ -113,6 +114,9 @@ var link = (options = {}) => {
113
114
  options: opts
114
115
  });
115
116
  }
117
+ if (extraFields.length) {
118
+ result.fields.push(...extraFields);
119
+ }
116
120
  return { ...result, ...overrides };
117
121
  };
118
122
 
package/dist/globals.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GlobalConfig } from "payload";
1
+ import { Field, GlobalConfig } from "payload";
2
2
  type CreateHeaderGlobalOptions = {
3
3
  /**
4
4
  * Optional override for the `custom.path` Payload uses to resolve
@@ -12,6 +12,17 @@ type CreateHeaderGlobalOptions = {
12
12
  * different list when your host has additional linkable collections.
13
13
  */
14
14
  linkRelationTo?: string[];
15
+ /**
16
+ * Extra fields appended to each `navColumn` link — e.g. a
17
+ * `description` text field or a `navHover` group for a mega-menu.
18
+ * Lets hosts enrich the column-link schema without redefining the
19
+ * whole nav.
20
+ */
21
+ navColumnLinkFields?: Field[];
22
+ /**
23
+ * Extra fields appended to each top-level `navItem` link.
24
+ */
25
+ navItemLinkFields?: Field[];
15
26
  };
16
27
  /**
17
28
  * Build the Header global. The lib's default shape: a `nav` blocks
@@ -19,7 +30,7 @@ type CreateHeaderGlobalOptions = {
19
30
  * and `navItem` (a single link).
20
31
  */
21
32
  declare const createHeaderGlobal: (options?: CreateHeaderGlobalOptions) => GlobalConfig;
22
- import { GlobalConfig as GlobalConfig2 } from "payload";
33
+ import { Field as Field2, GlobalConfig as GlobalConfig2 } from "payload";
23
34
  type CreateFooterGlobalOptions = {
24
35
  /**
25
36
  * Optional override for the `custom.path` Payload uses to resolve
@@ -33,6 +44,16 @@ type CreateFooterGlobalOptions = {
33
44
  * different list when your host has additional linkable collections.
34
45
  */
35
46
  linkRelationTo?: string[];
47
+ /**
48
+ * Extra fields appended to each `navColumn` link — e.g. a
49
+ * `description` text field. Lets hosts enrich the column-link
50
+ * schema without redefining the whole nav.
51
+ */
52
+ navColumnLinkFields?: Field2[];
53
+ /**
54
+ * Extra fields appended to each top-level `navItem` link.
55
+ */
56
+ navItemLinkFields?: Field2[];
36
57
  };
37
58
  /**
38
59
  * Build the Footer global. The lib's default shape mirrors the
package/dist/globals.js CHANGED
@@ -36,7 +36,8 @@ var link = (options = {}) => {
36
36
  disableLabel = false,
37
37
  relationTo = [PAGES_SLUG],
38
38
  localized = false,
39
- overrides = {}
39
+ overrides = {},
40
+ extraFields = []
40
41
  } = options;
41
42
  const result = {
42
43
  name: "link",
@@ -113,6 +114,9 @@ var link = (options = {}) => {
113
114
  options: opts
114
115
  });
115
116
  }
117
+ if (extraFields.length) {
118
+ result.fields.push(...extraFields);
119
+ }
116
120
  return { ...result, ...overrides };
117
121
  };
118
122
 
@@ -157,17 +161,22 @@ function createRevalidateGlobalHook(slug) {
157
161
 
158
162
  // src/data/collections/globals/Header/config.ts
159
163
  var createHeaderGlobal = (options = {}) => {
160
- const { renderPath = HEADER_RENDER_PATH, linkRelationTo = [PAGES_SLUG] } = options;
164
+ const {
165
+ renderPath = HEADER_RENDER_PATH,
166
+ linkRelationTo = [PAGES_SLUG],
167
+ navColumnLinkFields = [],
168
+ navItemLinkFields = []
169
+ } = options;
161
170
  const navColumnBlock = {
162
171
  slug: "navColumn",
163
172
  fields: [
164
173
  { name: "title", type: "text", required: true, localized: true },
165
- { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
174
+ { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
166
175
  ]
167
176
  };
168
177
  const navItemBlock = {
169
178
  slug: "navItem",
170
- fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
179
+ fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
171
180
  };
172
181
  return {
173
182
  slug: "header",
@@ -189,17 +198,22 @@ var createHeaderGlobal = (options = {}) => {
189
198
 
190
199
  // src/data/collections/globals/Footer/config.ts
191
200
  var createFooterGlobal = (options = {}) => {
192
- const { renderPath = FOOTER_RENDER_PATH, linkRelationTo = [PAGES_SLUG] } = options;
201
+ const {
202
+ renderPath = FOOTER_RENDER_PATH,
203
+ linkRelationTo = [PAGES_SLUG],
204
+ navColumnLinkFields = [],
205
+ navItemLinkFields = []
206
+ } = options;
193
207
  const navColumnBlock = {
194
208
  slug: "navColumn",
195
209
  fields: [
196
210
  { name: "title", type: "text", required: true, localized: true },
197
- { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
211
+ { name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
198
212
  ]
199
213
  };
200
214
  const navItemBlock = {
201
215
  slug: "navItem",
202
- fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
216
+ fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
203
217
  };
204
218
  return {
205
219
  slug: "footer",
package/dist/pages.d.ts CHANGED
@@ -207,6 +207,19 @@ type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
207
207
  * defined your own Server Component for the collection.
208
208
  */
209
209
  renderPath?: string;
210
+ /**
211
+ * Enable nested (hierarchical) slugs. When `true`, the catch-all
212
+ * `[...slug]` segments are joined with the `_` divider to form the
213
+ * stored slug (URL `/about/us` ⇄ stored `about_us`), URL paths and
214
+ * hreflang alternates are expanded back to `/about/us`, and
215
+ * `generateStaticParams` emits multi-segment params. When `false`
216
+ * (the default) only the first URL segment is used — flat slugs.
217
+ *
218
+ * Pair with `createPagesCollection({ nested: true })` (or
219
+ * `createWWWConfig({ nested: true })`) so the collection's slug
220
+ * validation accepts the `_` divider.
221
+ */
222
+ nested?: boolean;
210
223
  };
211
224
  type CreateCollectionPageExportsDeps<S extends string> = {
212
225
  /**
@@ -285,7 +298,7 @@ type CreateCollectionPageExportsDeps<S extends string> = {
285
298
  * { generateMetadata, generateStaticParams }
286
299
  * Page
287
300
  */
288
- declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
301
+ declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath, nested }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
289
302
  default: (props: {
290
303
  params: Promise<{
291
304
  locale?: string;
package/dist/pages.js CHANGED
@@ -687,7 +687,8 @@ function createCollectionPageExports({
687
687
  config: configPromise,
688
688
  routing,
689
689
  importMap: importMapArg,
690
- renderPath
690
+ renderPath,
691
+ nested = false
691
692
  }, deps, options = {}) {
692
693
  const importMap = importMapArg ?? {};
693
694
  const { jsonLd: jsonLdOption = true, changefreq = "weekly", priority = 0.5, websiteName } = options;
@@ -706,7 +707,7 @@ function createCollectionPageExports({
706
707
  const defaultRenderPath = slug === POSTS_SLUG ? POSTS_RENDER_PATH : PAGES_RENDER_PATH;
707
708
  const localePrefixMode = typeof routing.localePrefix === "string" ? routing.localePrefix : routing.localePrefix?.mode ?? "always";
708
709
  const buildLocalePath = (locale, storedSlug) => {
709
- const urlPath = getUrlPath(storedSlug, false, HOME_SLUG);
710
+ const urlPath = getUrlPath(storedSlugToSegments(storedSlug, nested), nested, HOME_SLUG);
710
711
  if (localePrefixMode === "never")
711
712
  return urlPath;
712
713
  if (localePrefixMode === "as-needed" && locale === defaultLocale)
@@ -731,7 +732,7 @@ function createCollectionPageExports({
731
732
  locale,
732
733
  urlPrefix: "",
733
734
  storedSlug,
734
- nested: false,
735
+ nested,
735
736
  homeSlug: HOME_SLUG,
736
737
  defaultLocale,
737
738
  locales,
@@ -756,7 +757,7 @@ function createCollectionPageExports({
756
757
  setRequestLocale(locale);
757
758
  const { draftMode } = await import("next/headers");
758
759
  const { isEnabled: draft } = await draftMode();
759
- const storedSlug = segmentsToStoredSlug(slugSegments, false);
760
+ const storedSlug = segmentsToStoredSlug(slugSegments, nested);
760
761
  const doc = await fetchDoc(locale, storedSlug, draft);
761
762
  if (!doc) {
762
763
  const { notFound } = await import("next/navigation");
@@ -779,7 +780,6 @@ function createCollectionPageExports({
779
780
  });
780
781
  const jsonLdNodes = doc ? await generateJsonLd(slugSegments, doc, locale) : [];
781
782
  const { alternates: hreflangAlternates, canonical } = await resolveHreflangAlternates(locale, storedSlug);
782
- console.log("render", { render, doc });
783
783
  const inner = /* @__PURE__ */ jsxs5(Fragment6, {
784
784
  children: [
785
785
  jsonLdNodes.map(({ id, schema }) => /* @__PURE__ */ jsx8("script", {
@@ -829,7 +829,7 @@ function createCollectionPageExports({
829
829
  const locale = typeof incomingLocale === "string" ? incomingLocale : defaultLocale;
830
830
  if (!locales.includes(locale))
831
831
  return { title: "Not found", robots: { index: false, follow: false } };
832
- const storedSlug = segmentsToStoredSlug(slugSegments, false);
832
+ const storedSlug = segmentsToStoredSlug(slugSegments, nested);
833
833
  const doc = await fetchDoc(locale, storedSlug);
834
834
  if (!doc)
835
835
  return { title: "Not found", robots: { index: false, follow: false } };
@@ -853,7 +853,7 @@ function createCollectionPageExports({
853
853
  if (jsonLdOption === false || !doc)
854
854
  return [];
855
855
  const siteUrl = getServerSideURL();
856
- const storedSlug = segmentsToStoredSlug(slugSegments, false);
856
+ const storedSlug = segmentsToStoredSlug(slugSegments, nested);
857
857
  const urlPath = buildLocalePath(locale, storedSlug);
858
858
  const canonical = `${siteUrl}${urlPath}`;
859
859
  const entries = Array.isArray(jsonLdOption) ? jsonLdOption : metadataType === "article" ? [{ type: "article" }] : [{ type: "website" }];
@@ -924,7 +924,7 @@ function createCollectionPageExports({
924
924
  const slugVal = doc.slug;
925
925
  if (typeof slugVal !== "string" || slugVal === "")
926
926
  continue;
927
- const segments = storedSlugToSegments(slugVal, false);
927
+ const segments = storedSlugToSegments(slugVal, nested);
928
928
  params.push({ slug: Array.isArray(segments) ? segments : [segments], locale });
929
929
  }
930
930
  }
@@ -130,6 +130,19 @@ type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
130
130
  * defined your own Server Component for the collection.
131
131
  */
132
132
  renderPath?: string;
133
+ /**
134
+ * Enable nested (hierarchical) slugs. When `true`, the catch-all
135
+ * `[...slug]` segments are joined with the `_` divider to form the
136
+ * stored slug (URL `/about/us` ⇄ stored `about_us`), URL paths and
137
+ * hreflang alternates are expanded back to `/about/us`, and
138
+ * `generateStaticParams` emits multi-segment params. When `false`
139
+ * (the default) only the first URL segment is used — flat slugs.
140
+ *
141
+ * Pair with `createPagesCollection({ nested: true })` (or
142
+ * `createWWWConfig({ nested: true })`) so the collection's slug
143
+ * validation accepts the `_` divider.
144
+ */
145
+ nested?: boolean;
133
146
  };
134
147
  type CreateCollectionPageExportsDeps<S extends string> = {
135
148
  /**
@@ -208,7 +221,7 @@ type CreateCollectionPageExportsDeps<S extends string> = {
208
221
  * { generateMetadata, generateStaticParams }
209
222
  * Page
210
223
  */
211
- declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
224
+ declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath, nested }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
212
225
  default: (props: {
213
226
  params: Promise<{
214
227
  locale?: string;
@@ -571,7 +571,8 @@ function createCollectionPageExports({
571
571
  config: configPromise,
572
572
  routing,
573
573
  importMap: importMapArg,
574
- renderPath
574
+ renderPath,
575
+ nested = false
575
576
  }, deps, options = {}) {
576
577
  const importMap = importMapArg ?? {};
577
578
  const { jsonLd: jsonLdOption = true, changefreq = "weekly", priority = 0.5, websiteName } = options;
@@ -590,7 +591,7 @@ function createCollectionPageExports({
590
591
  const defaultRenderPath = slug === POSTS_SLUG ? POSTS_RENDER_PATH : PAGES_RENDER_PATH;
591
592
  const localePrefixMode = typeof routing.localePrefix === "string" ? routing.localePrefix : routing.localePrefix?.mode ?? "always";
592
593
  const buildLocalePath = (locale, storedSlug) => {
593
- const urlPath = getUrlPath(storedSlug, false, HOME_SLUG);
594
+ const urlPath = getUrlPath(storedSlugToSegments(storedSlug, nested), nested, HOME_SLUG);
594
595
  if (localePrefixMode === "never")
595
596
  return urlPath;
596
597
  if (localePrefixMode === "as-needed" && locale === defaultLocale)
@@ -615,7 +616,7 @@ function createCollectionPageExports({
615
616
  locale,
616
617
  urlPrefix: "",
617
618
  storedSlug,
618
- nested: false,
619
+ nested,
619
620
  homeSlug: HOME_SLUG,
620
621
  defaultLocale,
621
622
  locales,
@@ -640,7 +641,7 @@ function createCollectionPageExports({
640
641
  setRequestLocale(locale);
641
642
  const { draftMode } = await import("next/headers");
642
643
  const { isEnabled: draft } = await draftMode();
643
- const storedSlug = segmentsToStoredSlug(slugSegments, false);
644
+ const storedSlug = segmentsToStoredSlug(slugSegments, nested);
644
645
  const doc = await fetchDoc(locale, storedSlug, draft);
645
646
  if (!doc) {
646
647
  const { notFound } = await import("next/navigation");
@@ -663,7 +664,6 @@ function createCollectionPageExports({
663
664
  });
664
665
  const jsonLdNodes = doc ? await generateJsonLd(slugSegments, doc, locale) : [];
665
666
  const { alternates: hreflangAlternates, canonical } = await resolveHreflangAlternates(locale, storedSlug);
666
- console.log("render", { render, doc });
667
667
  const inner = /* @__PURE__ */ jsxs3(Fragment4, {
668
668
  children: [
669
669
  jsonLdNodes.map(({ id, schema }) => /* @__PURE__ */ jsx6("script", {
@@ -713,7 +713,7 @@ function createCollectionPageExports({
713
713
  const locale = typeof incomingLocale === "string" ? incomingLocale : defaultLocale;
714
714
  if (!locales.includes(locale))
715
715
  return { title: "Not found", robots: { index: false, follow: false } };
716
- const storedSlug = segmentsToStoredSlug(slugSegments, false);
716
+ const storedSlug = segmentsToStoredSlug(slugSegments, nested);
717
717
  const doc = await fetchDoc(locale, storedSlug);
718
718
  if (!doc)
719
719
  return { title: "Not found", robots: { index: false, follow: false } };
@@ -737,7 +737,7 @@ function createCollectionPageExports({
737
737
  if (jsonLdOption === false || !doc)
738
738
  return [];
739
739
  const siteUrl = getServerSideURL();
740
- const storedSlug = segmentsToStoredSlug(slugSegments, false);
740
+ const storedSlug = segmentsToStoredSlug(slugSegments, nested);
741
741
  const urlPath = buildLocalePath(locale, storedSlug);
742
742
  const canonical = `${siteUrl}${urlPath}`;
743
743
  const entries = Array.isArray(jsonLdOption) ? jsonLdOption : metadataType === "article" ? [{ type: "article" }] : [{ type: "website" }];
@@ -808,7 +808,7 @@ function createCollectionPageExports({
808
808
  const slugVal = doc.slug;
809
809
  if (typeof slugVal !== "string" || slugVal === "")
810
810
  continue;
811
- const segments = storedSlugToSegments(slugVal, false);
811
+ const segments = storedSlugToSegments(slugVal, nested);
812
812
  params.push({ slug: Array.isArray(segments) ? segments : [segments], locale });
813
813
  }
814
814
  }
@@ -89,6 +89,14 @@ type CreateSitemapFileOptions = {
89
89
  priority?: number;
90
90
  changefreq?: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
91
91
  }>;
92
+ /**
93
+ * Per-collection nested-slug flag. When a collection is marked
94
+ * `true`, its stored `about_us` slug is expanded into the
95
+ * `/about/us` URL path (and hreflang alternates), matching a
96
+ * `createCollectionPageExports({ nested: true })` route. Defaults
97
+ * to `false` (flat slugs) for every collection.
98
+ */
99
+ nested?: Record<string, boolean>;
92
100
  };
93
101
  /**
94
102
  * A Next.js sitemap function for the host's
@@ -279,6 +279,7 @@ function createSitemapFile(options) {
279
279
  const collectionDefaults = options.perCollection?.[collectionSlug] ?? {};
280
280
  const urlPrefix = (options.urlPrefixes?.[collectionSlug] ?? "").replace(/\/$/, "");
281
281
  const siteUrl = options.getServerSideURL().replace(/\/$/, "");
282
+ const isNested = options.nested?.[collectionSlug] ?? false;
282
283
  for (const locale of activeLocales) {
283
284
  const docs = await queryAllDocs({
284
285
  collectionSlug,
@@ -294,13 +295,14 @@ function createSitemapFile(options) {
294
295
  if (seen.has(dedupeKey))
295
296
  continue;
296
297
  seen.add(dedupeKey);
297
- const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${storedSlug}`;
298
+ const slugPath = isNested ? storedSlug.replaceAll("_", "/") : storedSlug;
299
+ const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${slugPath}`;
298
300
  const languages = await buildHreflangAlternates({
299
301
  siteUrl,
300
302
  locale,
301
303
  urlPrefix,
302
304
  storedSlug,
303
- nested: false,
305
+ nested: isNested,
304
306
  homeSlug: "",
305
307
  defaultLocale,
306
308
  locales: activeLocales,