From b13f628b5506a5902bdfb96fe8fe69ced4214a03 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Sun, 3 May 2026 18:46:41 +0200 Subject: [PATCH] feat: complete MDX migration, stabilize environment & verify via E2E tests Former-commit-id: ec3e64156a2e182535cbdcf0d975cd54603a517d --- app/(payload)/admin/[[...segments]]/page.tsx | 17 - app/(payload)/admin/importMap.js | 57 - app/(payload)/api/[...slug]/route.ts | 14 - app/(payload)/api/graphql/route.ts | 4 - app/(payload)/custom.scss | 151 - app/(payload)/layout.tsx | 31 - app/[locale]/(legal)/datenschutz/page.tsx | 20 - app/[locale]/(legal)/impressum/page.tsx | 37 - app/[locale]/[slug]/page.tsx | 25 +- app/[locale]/blog/[slug]/page.tsx | 35 +- app/[locale]/contact/page.tsx | 4 +- app/[locale]/layout.tsx | 51 +- app/[locale]/not-found.tsx | 72 +- app/[locale]/page.tsx | 74 +- app/actions/brochure.ts | 23 +- app/actions/contact.ts | 27 +- app/api/health/cms/route.ts | 41 - components/CMSConnectivityNotice.tsx | 86 - components/PayloadRichText.tsx | 94 - components/layout/Footer.tsx | 18 +- components/layout/Header.tsx | 8 +- content/de/agb.mdx | 22 + .../blog/moderne-verfahren-kabeltiefbau.mdx | 30 + content/de/datenschutz.mdx | 43 + content/de/home.mdx | 73 + content/de/impressum.mdx | 47 + content/de/karriere.mdx | 35 + content/de/kompetenzen.mdx | 38 + content/de/ueber-uns.mdx | 34 + content/en/agb.mdx | 22 + .../blog/modern-methods-civil-engineering.mdx | 30 + content/en/datenschutz.mdx | 44 + content/en/home.mdx | 73 + content/en/impressum.mdx | 49 + content/en/karriere.mdx | 35 + content/en/kompetenzen.mdx | 38 + content/en/ueber-uns.mdx | 34 + docker-compose.dev.yml | 34 +- i18n/request.ts | 2 - legacy/_crawl_meta.json | 14 - legacy/_site_profile.json | 253 -- legacy/impressum.html.html | 778 ----- legacy/impressum.html.meta.json | 34 - legacy/index.html | 1347 -------- legacy/index.html.html | 1347 -------- legacy/index.html.meta.json | 46 - legacy/index.meta.json | 46 - legacy/kompetenzen-01.html.html | 1190 ------- legacy/kompetenzen-01.html.meta.json | 44 - legacy/kontakt.html.html | 1699 ---------- legacy/kontakt.html.meta.json | 58 - legacy/startseite.html.html | 1280 -------- legacy/startseite.html.meta.json | 46 - legacy/ueber-uns.html.html | 908 ------ legacy/ueber-uns.html.meta.json | 36 - lib/blog.ts | 276 +- lib/mdx.ts | 21 + lib/pages.ts | 211 +- messages/de.json | 45 +- messages/en.json | 45 +- next-env.d.ts | 2 +- next.config.mjs | 6 +- .../results.json | 2 +- package.json | 24 +- payload-types.ts | 1228 ------- payload.config.ts | 107 - pnpm-lock.yaml | 2820 +++-------------- proxy.ts | 110 +- scripts/clear-db.ts | 28 - scripts/fix-content.ts | 257 -- scripts/fix-home.ts | 104 - scripts/fix-pages.ts | 158 - scripts/fix-referenzen.ts | 81 - scripts/fix-settings.ts | 49 - scripts/seed-payload.ts | 21 - src/lib/redis.ts | 22 - .../20260223_195005_products_collection.json | 2621 --------------- .../20260223_195005_products_collection.ts | 356 --- .../20260223_195151_remove_sku_unique.json | 2591 --------------- .../20260223_195151_remove_sku_unique.ts | 13 - .../20260225_003500_add_pages_collection.json | 5 - .../20260225_003500_add_pages_collection.ts | 48 - .../20260225_175000_native_localization.ts | 358 --- ...20260305_215000_products_featured_image.ts | 52 - .../20260305_222000_media_sizes_tablet.ts | 31 - src/migrations/index.ts | 39 - src/payload-generated-schema.ts | 1112 ------- src/payload/access/anyone.ts | 3 - src/payload/access/authenticated.ts | 5 - src/payload/blocks/AnimatedImage.tsx | 27 - src/payload/blocks/Callout.tsx | 22 - src/payload/blocks/CategoryGrid.tsx | 48 - src/payload/blocks/ChatBubble.tsx | 36 - src/payload/blocks/CompanyHeritage.tsx | 54 - src/payload/blocks/CompanyTimeline.tsx | 12 - src/payload/blocks/ComparisonGrid.tsx | 49 - src/payload/blocks/ContactSection.tsx | 28 - src/payload/blocks/HeroSection.tsx | 50 - src/payload/blocks/HighlightBox.tsx | 20 - src/payload/blocks/HomeBlocks.tsx | 240 -- src/payload/blocks/ImageGallery.tsx | 27 - src/payload/blocks/JobListing.tsx | 22 - src/payload/blocks/ManifestoGrid.tsx | 41 - src/payload/blocks/PDFDownload.tsx | 32 - src/payload/blocks/PowerCTA.tsx | 12 - src/payload/blocks/ProductTabs.tsx | 109 - src/payload/blocks/SplitHeading.tsx | 25 - src/payload/blocks/Stats.tsx | 27 - src/payload/blocks/StickyNarrative.tsx | 33 - src/payload/blocks/SupportCTA.tsx | 30 - src/payload/blocks/TeamGrid.tsx | 33 - src/payload/blocks/TeamProfile.tsx | 64 - src/payload/blocks/TechnicalGrid.tsx | 32 - src/payload/blocks/VisualLinkPreview.tsx | 32 - src/payload/blocks/allBlocks.tsx | 62 - src/payload/blocks/types.ts | 6 - src/payload/collections/Competences.ts | 46 - src/payload/collections/FormSubmissions.ts | 68 - src/payload/collections/Jobs.ts | 59 - src/payload/collections/Media.ts | 48 - src/payload/collections/Pages.ts | 91 - src/payload/collections/Posts.ts | 139 - src/payload/collections/References.ts | 52 - src/payload/collections/Team.ts | 53 - src/payload/collections/Users.ts | 12 - src/payload/components/Icon.tsx | 13 - src/payload/components/Logo.tsx | 13 - src/payload/globals/Settings.ts | 60 - src/payload/seed.ts | 836 ----- src/payload/utils/lexicalParser.ts | 375 --- tests/navigation.e2e.test.ts | 89 +- 131 files changed, 1388 insertions(+), 25288 deletions(-) delete mode 100644 app/(payload)/admin/[[...segments]]/page.tsx delete mode 100644 app/(payload)/admin/importMap.js delete mode 100644 app/(payload)/api/[...slug]/route.ts delete mode 100644 app/(payload)/api/graphql/route.ts delete mode 100644 app/(payload)/custom.scss delete mode 100644 app/(payload)/layout.tsx delete mode 100644 app/[locale]/(legal)/datenschutz/page.tsx delete mode 100644 app/[locale]/(legal)/impressum/page.tsx delete mode 100644 app/api/health/cms/route.ts delete mode 100644 components/CMSConnectivityNotice.tsx delete mode 100644 components/PayloadRichText.tsx create mode 100644 content/de/agb.mdx create mode 100644 content/de/blog/moderne-verfahren-kabeltiefbau.mdx create mode 100644 content/de/datenschutz.mdx create mode 100644 content/de/home.mdx create mode 100644 content/de/impressum.mdx create mode 100644 content/de/karriere.mdx create mode 100644 content/de/kompetenzen.mdx create mode 100644 content/de/ueber-uns.mdx create mode 100644 content/en/agb.mdx create mode 100644 content/en/blog/modern-methods-civil-engineering.mdx create mode 100644 content/en/datenschutz.mdx create mode 100644 content/en/home.mdx create mode 100644 content/en/impressum.mdx create mode 100644 content/en/karriere.mdx create mode 100644 content/en/kompetenzen.mdx create mode 100644 content/en/ueber-uns.mdx delete mode 100644 legacy/_crawl_meta.json delete mode 100644 legacy/_site_profile.json delete mode 100644 legacy/impressum.html.html delete mode 100644 legacy/impressum.html.meta.json delete mode 100644 legacy/index.html delete mode 100644 legacy/index.html.html delete mode 100644 legacy/index.html.meta.json delete mode 100644 legacy/index.meta.json delete mode 100644 legacy/kompetenzen-01.html.html delete mode 100644 legacy/kompetenzen-01.html.meta.json delete mode 100644 legacy/kontakt.html.html delete mode 100644 legacy/kontakt.html.meta.json delete mode 100644 legacy/startseite.html.html delete mode 100644 legacy/startseite.html.meta.json delete mode 100644 legacy/ueber-uns.html.html delete mode 100644 legacy/ueber-uns.html.meta.json create mode 100644 lib/mdx.ts delete mode 100644 payload-types.ts delete mode 100644 payload.config.ts delete mode 100644 scripts/clear-db.ts delete mode 100644 scripts/fix-content.ts delete mode 100644 scripts/fix-home.ts delete mode 100644 scripts/fix-pages.ts delete mode 100644 scripts/fix-referenzen.ts delete mode 100644 scripts/fix-settings.ts delete mode 100644 scripts/seed-payload.ts delete mode 100644 src/lib/redis.ts delete mode 100644 src/migrations/20260223_195005_products_collection.json delete mode 100644 src/migrations/20260223_195005_products_collection.ts delete mode 100644 src/migrations/20260223_195151_remove_sku_unique.json delete mode 100644 src/migrations/20260223_195151_remove_sku_unique.ts delete mode 100644 src/migrations/20260225_003500_add_pages_collection.json delete mode 100644 src/migrations/20260225_003500_add_pages_collection.ts delete mode 100644 src/migrations/20260225_175000_native_localization.ts delete mode 100644 src/migrations/20260305_215000_products_featured_image.ts delete mode 100644 src/migrations/20260305_222000_media_sizes_tablet.ts delete mode 100644 src/migrations/index.ts delete mode 100644 src/payload-generated-schema.ts delete mode 100644 src/payload/access/anyone.ts delete mode 100644 src/payload/access/authenticated.ts delete mode 100644 src/payload/blocks/AnimatedImage.tsx delete mode 100644 src/payload/blocks/Callout.tsx delete mode 100644 src/payload/blocks/CategoryGrid.tsx delete mode 100644 src/payload/blocks/ChatBubble.tsx delete mode 100644 src/payload/blocks/CompanyHeritage.tsx delete mode 100644 src/payload/blocks/CompanyTimeline.tsx delete mode 100644 src/payload/blocks/ComparisonGrid.tsx delete mode 100644 src/payload/blocks/ContactSection.tsx delete mode 100644 src/payload/blocks/HeroSection.tsx delete mode 100644 src/payload/blocks/HighlightBox.tsx delete mode 100644 src/payload/blocks/HomeBlocks.tsx delete mode 100644 src/payload/blocks/ImageGallery.tsx delete mode 100644 src/payload/blocks/JobListing.tsx delete mode 100644 src/payload/blocks/ManifestoGrid.tsx delete mode 100644 src/payload/blocks/PDFDownload.tsx delete mode 100644 src/payload/blocks/PowerCTA.tsx delete mode 100644 src/payload/blocks/ProductTabs.tsx delete mode 100644 src/payload/blocks/SplitHeading.tsx delete mode 100644 src/payload/blocks/Stats.tsx delete mode 100644 src/payload/blocks/StickyNarrative.tsx delete mode 100644 src/payload/blocks/SupportCTA.tsx delete mode 100644 src/payload/blocks/TeamGrid.tsx delete mode 100644 src/payload/blocks/TeamProfile.tsx delete mode 100644 src/payload/blocks/TechnicalGrid.tsx delete mode 100644 src/payload/blocks/VisualLinkPreview.tsx delete mode 100644 src/payload/blocks/allBlocks.tsx delete mode 100644 src/payload/blocks/types.ts delete mode 100644 src/payload/collections/Competences.ts delete mode 100644 src/payload/collections/FormSubmissions.ts delete mode 100644 src/payload/collections/Jobs.ts delete mode 100644 src/payload/collections/Media.ts delete mode 100644 src/payload/collections/Pages.ts delete mode 100644 src/payload/collections/Posts.ts delete mode 100644 src/payload/collections/References.ts delete mode 100644 src/payload/collections/Team.ts delete mode 100644 src/payload/collections/Users.ts delete mode 100644 src/payload/components/Icon.tsx delete mode 100644 src/payload/components/Logo.tsx delete mode 100644 src/payload/globals/Settings.ts delete mode 100644 src/payload/seed.ts delete mode 100644 src/payload/utils/lexicalParser.ts diff --git a/app/(payload)/admin/[[...segments]]/page.tsx b/app/(payload)/admin/[[...segments]]/page.tsx deleted file mode 100644 index 362452d78..000000000 --- a/app/(payload)/admin/[[...segments]]/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import configPromise from '@payload-config'; -import { RootPage } from '@payloadcms/next/views'; -import { importMap } from '../importMap'; - -type Args = { - params: Promise<{ - segments: string[]; - }>; - searchParams: Promise<{ - [key: string]: string | string[]; - }>; -}; - -const Page = ({ params, searchParams }: Args) => - RootPage({ config: configPromise, importMap, params, searchParams }); - -export default Page; diff --git a/app/(payload)/admin/importMap.js b/app/(payload)/admin/importMap.js deleted file mode 100644 index aecd36392..000000000 --- a/app/(payload)/admin/importMap.js +++ /dev/null @@ -1,57 +0,0 @@ -import { RscEntryLexicalCell as RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc' -import { RscEntryLexicalField as RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc' -import { LexicalDiffComponent as LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e } from '@payloadcms/richtext-lexical/rsc' -import { BlocksFeatureClient as BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { InlineToolbarFeatureClient as InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { UploadFeatureClient as UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { BlockquoteFeatureClient as BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { RelationshipFeatureClient as RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { LinkFeatureClient as LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { ChecklistFeatureClient as ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { OrderedListFeatureClient as OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { UnorderedListFeatureClient as UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { IndentFeatureClient as IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { AlignFeatureClient as AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { HeadingFeatureClient as HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { ParagraphFeatureClient as ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { InlineCodeFeatureClient as InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { SuperscriptFeatureClient as SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { SubscriptFeatureClient as SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' -import { default as default_9ed509b5e5f7d08a16335393f27586cc } from '../../../src/payload/components/Icon' -import { default as default_5470ea90f7a8fd882c2fe59ff2b1c5b9 } from '../../../src/payload/components/Logo' -import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc' - -export const importMap = { - "@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e, - "@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e, - "@payloadcms/richtext-lexical/rsc#LexicalDiffComponent": LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e, - "@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#UploadFeatureClient": UploadFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#BlockquoteFeatureClient": BlockquoteFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#RelationshipFeatureClient": RelationshipFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#ChecklistFeatureClient": ChecklistFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#OrderedListFeatureClient": OrderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#UnorderedListFeatureClient": UnorderedListFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#IndentFeatureClient": IndentFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#AlignFeatureClient": AlignFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#InlineCodeFeatureClient": InlineCodeFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#SuperscriptFeatureClient": SuperscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#SubscriptFeatureClient": SubscriptFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#StrikethroughFeatureClient": StrikethroughFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - "/src/payload/components/Icon#default": default_9ed509b5e5f7d08a16335393f27586cc, - "/src/payload/components/Logo#default": default_5470ea90f7a8fd882c2fe59ff2b1c5b9, - "@payloadcms/next/rsc#CollectionCards": CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 -} diff --git a/app/(payload)/api/[...slug]/route.ts b/app/(payload)/api/[...slug]/route.ts deleted file mode 100644 index bec81863b..000000000 --- a/app/(payload)/api/[...slug]/route.ts +++ /dev/null @@ -1,14 +0,0 @@ -import config from '@payload-config'; -import { - REST_GET, - REST_OPTIONS, - REST_PATCH, - REST_POST, - REST_DELETE, -} from '@payloadcms/next/routes'; - -export const GET = REST_GET(config); -export const POST = REST_POST(config); -export const DELETE = REST_DELETE(config); -export const PATCH = REST_PATCH(config); -export const OPTIONS = REST_OPTIONS(config); diff --git a/app/(payload)/api/graphql/route.ts b/app/(payload)/api/graphql/route.ts deleted file mode 100644 index 7270fe745..000000000 --- a/app/(payload)/api/graphql/route.ts +++ /dev/null @@ -1,4 +0,0 @@ -import config from '@payload-config'; -import { GRAPHQL_POST } from '@payloadcms/next/routes'; - -export const POST = GRAPHQL_POST(config); diff --git a/app/(payload)/custom.scss b/app/(payload)/custom.scss deleted file mode 100644 index 29fc9e810..000000000 --- a/app/(payload)/custom.scss +++ /dev/null @@ -1,151 +0,0 @@ -/* ================================================================= - KLZ Cables – Payload Admin Theme - Strictly follows docs/STYLEGUIDE.md & tailwind.config.cjs - - IMPORTANT: We use `html` selector (not `:root`) because Payload's - own CSS defines variables on `:root` and loads AFTER this file. - `html` has higher specificity than `:root`, so our values win. - ================================================================= */ - -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); - -/* ================================================================= - COLOR OVERRIDES - Payload internally maps: - --theme-elevation-* → --color-base-* - --theme-success-* → --color-success-* - We override the SOURCE variables on `html` to beat Payload's `:root`. - ================================================================= */ - -html { - /* --------------------------------------------------------------- - KLZ Primary Blue (#011dff) → Buttons, links, active states - --------------------------------------------------------------- */ - --color-success-50: #eef0ff !important; - --color-success-100: #dfe2ff !important; - --color-success-150: #cdd2ff !important; - --color-success-200: #b8bfff !important; - --color-success-250: #a0a9ff !important; - --color-success-300: #8892ff !important; - --color-success-350: #707bff !important; - --color-success-400: #5564ff !important; - --color-success-450: #3a4dff !important; - --color-success-500: #011dff !important; - /* KLZ Primary */ - --color-success-550: #0119e6 !important; - --color-success-600: #0116cc !important; - --color-success-650: #0112b3 !important; - --color-success-700: #000e99 !important; - --color-success-750: #000b80 !important; - --color-success-800: #000866 !important; - --color-success-850: #00054d !important; - --color-success-900: #000333 !important; - --color-success-950: #00011a !important; - - /* --------------------------------------------------------------- - KLZ "Foundation Neutrals" → Backgrounds, cards, borders, text - Based on tailwind.config.cjs: neutral.light=#fff, - neutral.DEFAULT=#f8f9fa, neutral.dark=#263336, neutral.black=#0a0a0a - text.primary=#1a1a1a, text.secondary=#6c757d, text.light=#adb5bd - --------------------------------------------------------------- */ - --color-base-0: #ffffff !important; - --color-base-50: #f8f9fa !important; - --color-base-100: #f1f3f5 !important; - --color-base-150: #e9ecef !important; - --color-base-200: #dee2e6 !important; - --color-base-250: #ced4da !important; - --color-base-300: #adb5bd !important; - --color-base-350: #9ba3ab !important; - --color-base-400: #868e96 !important; - --color-base-450: #6c757d !important; - --color-base-500: #5c636a !important; - --color-base-550: #4d5358 !important; - --color-base-600: #3d4246 !important; - --color-base-650: #343a40 !important; - --color-base-700: #2b3035 !important; - --color-base-750: #263336 !important; - --color-base-800: #212529 !important; - --color-base-850: #1a1a1a !important; - --color-base-900: #121212 !important; - --color-base-950: #0a0a0a !important; - --color-base-1000: #000000 !important; - - /* Typography */ - --font-body: 'Inter', system-ui, -apple-system, sans-serif !important; - --font-headings: 'Inter', system-ui, -apple-system, sans-serif !important; -} - -/* Base Body Application */ -body { - font-family: var(--font-body) !important; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -/* ================================================================= - Login / Setup Page - ================================================================= */ -.template-default.template-default--has-bg { - background: radial-gradient(circle at top right, #e6ebf5 0%, #f8f9fa 60%, #f3f4f6 100%) !important; -} - -.login__wrap, -.create-first-user__wrap { - border-top: none !important; - padding: 3rem !important; - background: rgba(255, 255, 255, 0.85) !important; - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - border: 1px solid var(--theme-elevation-150) !important; - box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15) !important; - border-radius: 1.5rem !important; -} - -/* ================================================================= - Buttons – override Payload's dark buttons with KLZ Blue - Payload uses .btn--style-primary { --bg-color: var(--theme-elevation-800) } - which makes all primary buttons near-black. We override to KLZ Blue. - ================================================================= */ -.btn--style-primary, -.btn--style-pill { - --bg-color: #011dff !important; - --color: #ffffff !important; - --hover-bg: #0116cc !important; - --hover-color: #ffffff !important; -} - -.btn--style-primary.btn--disabled, -.btn--style-pill.btn--disabled { - --bg-color: #b8bfff !important; - --color: #ffffff !important; - --hover-bg: #b8bfff !important; -} - -/* Sidebar Active Items */ -[class*="nav-group__link--active"], -[class*="nav__link--active"] { - --theme-elevation-800: #011dff !important; - color: #011dff !important; - border-left-color: #011dff !important; -} - -.btn--style-secondary { - --box-shadow: inset 0 0 0 1px #011dff !important; - --color: #011dff !important; - --hover-color: #0116cc !important; - --hover-box-shadow: inset 0 0 0 1px #0116cc !important; -} - -/* ================================================================= - Logo & Icon - ================================================================= */ -.klz-admin-logo, -.klz-admin-icon { - display: block !important; - visibility: visible !important; - opacity: 1 !important; - height: 32px !important; - width: auto !important; - max-width: 100% !important; - object-fit: contain !important; -} \ No newline at end of file diff --git a/app/(payload)/layout.tsx b/app/(payload)/layout.tsx deleted file mode 100644 index c9b7e796a..000000000 --- a/app/(payload)/layout.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import configPromise from '@payload-config'; -import { RootLayout } from '@payloadcms/next/layouts'; -import React from 'react'; - -import '@payloadcms/next/css'; -import './custom.scss'; -import { handleServerFunctions } from '@payloadcms/next/layouts'; -import { importMap } from './admin/importMap'; - -type Args = { - children: React.ReactNode; -}; - -const serverFunction: any = async function (args: any) { - 'use server'; - return handleServerFunctions({ - ...args, - config: configPromise, - importMap, - }); -}; - -const Layout = ({ children }: Args) => { - return ( - - {children} - - ); -}; - -export default Layout; diff --git a/app/[locale]/(legal)/datenschutz/page.tsx b/app/[locale]/(legal)/datenschutz/page.tsx deleted file mode 100644 index 1a4c369a9..000000000 --- a/app/[locale]/(legal)/datenschutz/page.tsx +++ /dev/null @@ -1,20 +0,0 @@ -export default function DatenschutzPage() { - return ( -
-
-

Datenschutzerklärung

-
-

1. Datenschutz auf einen Blick

-

- Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie diese Website besuchen. - Die vollständige Datenschutzerklärung der E-TIB GmbH wird aktuell überarbeitet und an dieser Stelle zur Verfügung gestellt. -

-

2. Allgemeine Hinweise und Pflichtinformationen

-

- Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. -

-
-
-
- ); -} diff --git a/app/[locale]/(legal)/impressum/page.tsx b/app/[locale]/(legal)/impressum/page.tsx deleted file mode 100644 index 0c4e1d17e..000000000 --- a/app/[locale]/(legal)/impressum/page.tsx +++ /dev/null @@ -1,37 +0,0 @@ -export default function ImpressumPage() { - return ( -
-
-

Impressum

-
-

Angaben gemäß § 5 TMG

-

- E-TIB GmbH
- Gewerbestraße 22
- 03172 Guben -

-

- Vertreten durch:
- Geschäftsführer: Danny Joseph -

-

- Kontakt:
- Telefon: +49 15207230518
- E-Mail: d.joseph@e-tib.com -

-

- Registereintrag:
- Eintragung im Handelsregister.
- Registergericht: Amtsgericht Cottbus
- Registernummer: HRB 12403 CB -

-

- Umsatzsteuer-ID:
- Umsatzsteuer-Identifikationsnummer gemäß § 27 a Umsatzsteuergesetz:
- DE304799919 -

-
-
-
- ); -} diff --git a/app/[locale]/[slug]/page.tsx b/app/[locale]/[slug]/page.tsx index 9326bf419..353027b10 100644 --- a/app/[locale]/[slug]/page.tsx +++ b/app/[locale]/[slug]/page.tsx @@ -4,10 +4,23 @@ import { getTranslations, setRequestLocale } from 'next-intl/server'; import { Metadata } from 'next'; import { getPageBySlug } from '@/lib/pages'; import { mapSlugToFileSlug, mapFileSlugToTranslated } from '@/lib/slugs'; -import PayloadRichText from '@/components/PayloadRichText'; +import { MDXRemote } from 'next-mdx-remote/rsc'; import { SITE_URL } from '@/lib/schema'; import TrackedLink from '@/components/analytics/TrackedLink'; +// Import components used in MDX +import { HeroVideo as HomeHero } from '@/components/blocks/HeroVideo'; +import { SubCompanyTiles as HomeSubCompanyTiles } from '@/components/blocks/SubCompanyTiles'; +import { CompetenceBentoGrid as HomeCompetenceBentoGrid } from '@/components/blocks/CompetenceBentoGrid'; +import { ReferencesSlider as HomeReferencesSlider } from '@/components/blocks/ReferencesSlider'; + +const mdxComponents = { + HomeHero, + HomeSubCompanyTiles, + HomeCompetenceBentoGrid, + HomeReferencesSlider, +}; + interface PageProps { params: Promise<{ locale: string; @@ -72,18 +85,20 @@ export default async function Page(props: { params: Promise<{ locale: string; sl notFound(); } - // Redirect if accessed via a different locale's slug + // Redirect logic removed to simplify for now, as slugs match file names + /* const fileSlug = await mapSlugToFileSlug(pageData.slug || slug, locale); const correctSlug = await mapFileSlugToTranslated(fileSlug, locale); if (correctSlug && correctSlug !== slug) { redirect(`/${locale}/${correctSlug}`); } + */ // Full-bleed pages render blocks edge-to-edge without the generic article wrapper if (pageData.frontmatter.layout === 'fullBleed') { return (
- +
); } @@ -120,9 +135,9 @@ export default async function Page(props: { params: Promise<{ locale: string; sl )} - {/* Main content with shared blog components */} + {/* Main content */}
- +
{/* Support Section */} diff --git a/app/[locale]/blog/[slug]/page.tsx b/app/[locale]/blog/[slug]/page.tsx index 449fb184c..c72d9057a 100644 --- a/app/[locale]/blog/[slug]/page.tsx +++ b/app/[locale]/blog/[slug]/page.tsx @@ -5,7 +5,7 @@ import { getPostBySlug, getAdjacentPosts, getReadingTime, - extractLexicalHeadings, + getHeadings, } from '@/lib/blog'; import { Metadata } from 'next'; import Link from 'next/link'; @@ -16,9 +16,7 @@ import TableOfContents from '@/components/blog/TableOfContents'; import { Heading } from '@/components/ui'; import { setRequestLocale } from 'next-intl/server'; import BlogEngagementTracker from '@/components/analytics/BlogEngagementTracker'; - -// Payload CMS Imports -import PayloadRichText from '@/components/PayloadRichText'; +import { MDXRemote } from 'next-mdx-remote/rsc'; interface BlogPostProps { params: Promise<{ @@ -65,20 +63,9 @@ export default async function BlogPost({ params }: BlogPostProps) { notFound(); } - // If the user accessed this post using a slug from a different locale - // (e.g. via the generic language switcher), redirect them to the correct localized slug URL - if (post.slug && post.slug !== slug) { - redirect(`/${locale}/blog/${post.slug}`); - } - const { prev, next, isPrevRandom, isNextRandom } = await getAdjacentPosts(post.slug, locale); - - // Convert Lexical content into a plain string to estimate reading time roughly - // Extract headings for TOC - const headings = extractLexicalHeadings(post.content?.root || post.content); - - // Convert Lexical content into a plain string to estimate reading time roughly - const rawTextContent = JSON.stringify(post.content); + const headings = getHeadings(post.content); + const readingTime = getReadingTime(post.content); return (
@@ -86,7 +73,7 @@ export default async function BlogPost({ params }: BlogPostProps) { title={post.frontmatter.title} slug={slug} category={post.frontmatter.category} - readingTime={getReadingTime(rawTextContent)} + readingTime={readingTime} /> {/* Featured Image Header */} @@ -131,7 +118,7 @@ export default async function BlogPost({ params }: BlogPostProps) { })} - {getReadingTime(rawTextContent)} min read + {readingTime} min read {(new Date(post.frontmatter.date) > new Date() || post.frontmatter.public === false) && ( <> @@ -168,7 +155,7 @@ export default async function BlogPost({ params }: BlogPostProps) { })} - {getReadingTime(rawTextContent)} min read + {readingTime} min read {(new Date(post.frontmatter.date) > new Date() || post.frontmatter.public === false) && ( <> @@ -197,9 +184,9 @@ export default async function BlogPost({ params }: BlogPostProps) { )} - {/* Main content with enhanced styling rendering Payload Lexical */} + {/* Main content */}
- +
{/* Power CTA */} @@ -284,8 +271,8 @@ export default async function BlogPost({ params }: BlogPostProps) { '@id': `${SITE_URL}/${locale}/blog/${slug}`, }, articleSection: post.frontmatter.category, - wordCount: rawTextContent.split(/\s+/).length, - timeRequired: `PT${getReadingTime(rawTextContent)}M`, + wordCount: post.content.split(/\s+/).length, + timeRequired: `PT${readingTime}M`, } as any } /> diff --git a/app/[locale]/contact/page.tsx b/app/[locale]/contact/page.tsx index f40c3a9cf..5bea24558 100644 --- a/app/[locale]/contact/page.tsx +++ b/app/[locale]/contact/page.tsx @@ -62,7 +62,8 @@ export default async function ContactPage({ params }: ContactPageProps) { setRequestLocale(locale); const t = await getTranslations({ locale, namespace: 'Contact' }); - // Get translated slug to redirect if user used incorrect static slug + // Get translated slug - redirect logic removed to prevent loop with next.config.js rewrites + /* const { headers } = await import('next/headers'); const headersList = await headers(); const urlPath = headersList.get('x-invoke-path') || ''; @@ -75,6 +76,7 @@ export default async function ContactPage({ params }: ContactPageProps) { redirect(`/${locale}/${contactSlugDe}`); } } + */ return (
diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx index e0e9b323d..a2e939811 100644 --- a/app/[locale]/layout.tsx +++ b/app/[locale]/layout.tsx @@ -2,7 +2,6 @@ import { Footer } from '@/components/layout/Footer'; import { Header } from '@/components/layout/Header'; import JsonLd from '@/components/JsonLd'; import SkipLink from '@/components/SkipLink'; -import CMSConnectivityNotice from '@/components/CMSConnectivityNotice'; import AnalyticsShell from '@/components/analytics/AnalyticsShell'; import { Metadata, Viewport } from 'next'; import { NextIntlClientProvider } from 'next-intl'; @@ -12,8 +11,7 @@ import { SITE_URL } from '@/lib/schema'; import FeedbackClientWrapper from '@/components/FeedbackClientWrapper'; import { setRequestLocale } from 'next-intl/server'; import { Inter } from 'next/font/google'; -import { getPayload } from 'payload'; -import configPromise from '@payload-config'; +import { mapFileSlugToTranslated } from '@/lib/slugs'; const inter = Inter({ subsets: ['latin'], @@ -76,36 +74,34 @@ export default async function Layout(props: { const safeLocale = supportedLocales.includes(localeStr) ? localeStr : 'en'; setRequestLocale(safeLocale); - + let messages: Record = {}; try { messages = await getMessages(); - } catch { + } catch (err) { + console.error('[Layout] Failed to load messages:', err); messages = {}; } - - // Fetch navigation and company info from Payload Global Settings - const payload = await getPayload({ config: configPromise }); - const settings = await payload.findGlobal({ - slug: 'settings', - locale: safeLocale as any, - }).catch(() => null); - - const navLinks = (settings?.mainNav && settings.mainNav.length > 0) - ? settings.mainNav.map((n) => ({ - label: n.label, - url: n.url, - })) - : [ - { label: 'Kompetenzen', url: `/${safeLocale}/kompetenzen` }, - { label: 'Über uns', url: `/${safeLocale}/ueber-uns` }, - { label: 'Karriere & Messen', url: `/${safeLocale}/karriere` } - ]; - + + const navLinks = [ + { + label: safeLocale === 'de' ? 'Kompetenzen' : 'Competencies', + url: `/${safeLocale}/${await mapFileSlugToTranslated('kompetenzen', safeLocale)}` + }, + { + label: safeLocale === 'de' ? 'Über uns' : 'About Us', + url: `/${safeLocale}/${await mapFileSlugToTranslated('ueber-uns', safeLocale)}` + }, + { + label: safeLocale === 'de' ? 'Karriere & Messen' : 'Careers & Events', + url: `/${safeLocale}/${await mapFileSlugToTranslated('karriere', safeLocale)}` + } + ]; + const companyInfo = { - contactEmail: settings?.contactEmail || 'info@e-tib.com', - contactPhone: settings?.contactPhone || '+49 15207230518', - address: settings?.address || 'Gewerbestraße 22\\n03172 Guben' + contactEmail: 'info@e-tib.com', + contactPhone: '+49 15207230518', + address: 'Gewerbestraße 22\n03172 Guben' }; // Pick only the namespaces required by client components to reduce the hydration payload size @@ -185,7 +181,6 @@ export default async function Layout(props: {