diff --git a/components/CookieBanner.vue b/components/CookieBanner.vue
index 59ad859..21c1cf6 100644
--- a/components/CookieBanner.vue
+++ b/components/CookieBanner.vue
@@ -16,7 +16,7 @@
Datenschutzerklärung
diff --git a/components/Header.vue b/components/Header.vue
index 0d1f104..87d44e9 100644
--- a/components/Header.vue
+++ b/components/Header.vue
@@ -45,12 +45,6 @@
:path="`/notebooks/${item.slug}`"
@click="trackEvent('header-item-clicked', { label: item.label })"
/>
-
{
- return (
- props.product?.pattern && [
- randomTailwindColor(props.product.pattern.id, "group-hover:shadow", 200, "/60")
- ]
- );
+ return props.product?.pattern
+ ? [randomTailwindColor(props.product.pattern.id, "group-hover:shadow", 200, "/60")]
+ : [];
});
const hasProductOptions = computed(() => {
diff --git a/components/SelectionBox.vue b/components/SelectionBox.vue
index 23d8282..bd71bae 100644
--- a/components/SelectionBox.vue
+++ b/components/SelectionBox.vue
@@ -1,12 +1,14 @@
-
{{ label }}
-
+
diff --git a/composables/useProductContent.ts b/composables/useProductContent.ts
index 08eed13..f0a10a3 100644
--- a/composables/useProductContent.ts
+++ b/composables/useProductContent.ts
@@ -1,7 +1,7 @@
// Product content keyed by cover type
// This content is displayed on product detail pages as storytelling modules
-export type CoverType = "Hardcover" | "Softcover" | "Heft" | "Spiralbindung";
+export type CoverType = "Hardcover" | "Softcover" | "Heft" | "Spiralbindung" | "Promo";
export interface FeatureModule {
eyebrow?: string;
@@ -199,6 +199,44 @@ export const FEATURE_MODULES: Record = {
imageRight: true,
},
],
+
+ Promo: [
+ {
+ eyebrow: "12 Wochen · 3 Monate",
+ headline: "Struktur für deinen Alltag",
+ subtitle: "Planung, Intention & Reflexion",
+ body: `Dieses Journaling Booklet im Format A5 sorgt für mehr Produktivität im Alltag.
+ Es beinhaltet Monats-, Wochen- und Tagesplanungen sowie inspirierenden Zitaten
+ für insgesamt 12 Wochen bzw. 3 Monate. Jeder Tag bietet Platz für eine
+ Tagesintention, den täglichen Aufgaben, dem Notieren von Mahlzeiten und der
+ Fitnessroutine. Darüber hinaus bietet es die Möglichkeit der eigene
+ Tagesreflexion. Als tägliche Begleiter soll es helfen, deine Zeit effektiv zu
+ managen, um mit mehr Klarheit und Struktur deine Ziele anzugehen.`,
+ imageRight: true,
+ },
+ {
+ eyebrow: "Gestaltet von mk rietzl",
+ headline: "VIVUS 89 Recyclingpapier",
+ subtitle: "Matt, 120g/qm, fliederfarbener Umschlag",
+ body: `Das Journaling Booklet wurde konzipiert und gestaltet von Michèle Rietzl
+ (mk rietzl). Es ist auf VIVUS 89 Recyclingpapier gedruckt. Die matte,
+ ungestrichene Oberfläche mit feiner Textur verhindert Durchschlagen – selbst bei
+ Füllfederhaltern und Aquarellfarben. Mit 120g/qm und 1,2-fachem Volumen fühlt
+ sich jede Seite substanziell an, ohne starr zu wirken. Der fliederfarbene
+ Umschlag sorgt für schlichte Farbakzente.`,
+ imageRight: false,
+ },
+ {
+ eyebrow: "Handgefertigt in Stuttgart",
+ headline: "Fadenbindung mit offenem Buchrücken",
+ subtitle: "Vollständiges Aufklappen zum Schreiben",
+ body: `Bei der Bindung handelt es sich um eine klassische Fadenbindung mit offenem
+ Buchrücken. Dies ermöglicht ein vollständiges Aufklappen, was sich ideal zum
+ Schreiben eignet. Die Booklets werden mit größter Sorgfalt in Stuttgart
+ produziert. Jedes Exemplar ist handgefertigt.`,
+ imageRight: true,
+ },
+ ],
};
// =============================================================================
@@ -244,6 +282,15 @@ export const TECHNICAL_SPECS: Record> = {
Zertifizierung: "FSC® C018175, Blauer Engel, EU Ecolabel",
Herstellung: "Stuttgart, Deutschland",
},
+ Promo: {
+ Format: "150 × 210 mm (A5)",
+ Umfang: "12 Wochen / 3 Monate",
+ Layout: "Vorgedruckt (Tages-, Wochen- & Monatsplanung)",
+ Papier: "VIVUS 89, 120g/qm, 1,2-faches Volumen, ungestrichen matt",
+ Einband: "Fliederfarbener Softcover",
+ Bindung: "Fadenbindung mit offenem Buchrücken",
+ Herstellung: "Handgefertigt in Stuttgart",
+ },
};
// =============================================================================
@@ -284,6 +331,8 @@ export function getCoverType(coverName?: string): CoverType {
if (name.includes("hardcover")) return "Hardcover";
if (name.includes("softcover")) return "Softcover";
if (name.includes("spiral") || name.includes("wire")) return "Spiralbindung";
+ // Standalone promo bucket (cover named "Promo").
+ if (name.includes("promo")) return "Promo";
return "Hardcover"; // fallback
}
@@ -314,10 +363,10 @@ export function useProductContent(
derivedSpecs["Format"] = prod.cover.copyText.format;
}
- // Seitenanzahl from pages
- if (prod.pages?.name) {
+ // Seitenanzahl from pages (skip for Promo/standalone — page count not relevant)
+ if (prod.pages?.name && coverType.value !== "Promo") {
derivedSpecs["Seitenanzahl"] = prod.pages.name;
- } else if (prod.pages?.count) {
+ } else if (prod.pages?.count && coverType.value !== "Promo") {
const sheets = Math.floor(prod.pages.count / 2);
derivedSpecs["Seitenanzahl"] = `${prod.pages.count} Seiten (${sheets} Blatt)`;
}
diff --git a/nuxt.config.ts b/nuxt.config.ts
index e5bd0f0..d225b10 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -45,7 +45,10 @@ export default defineNuxtConfig({
routeRules: {
// Cart & Checkout: Client-only (no SSR)
"/cart": { ssr: false },
- "/checkout/**": { ssr: false }
+ "/checkout/**": { ssr: false },
+ // Local dev: proxy CMS media. In prod nginx routes /uploads → cms;
+ // without it the browser would hit the Nuxt origin and 404.
+ "/uploads/**": { proxy: "http://cms:5555/uploads/**" }
// All other pages use default SSR
},
diff --git a/pages/details/[slug].vue b/pages/details/[slug].vue
index f8b247d..3dddf6e 100644
--- a/pages/details/[slug].vue
+++ b/pages/details/[slug].vue
@@ -77,48 +77,40 @@
{{ product?.cover?.copyText?.paper }}
-
+
-
-
-
- Seiten
-
-
+
+
+ Seiten
+
1 && handleVariantClick('pages', pages)"
/>
-
-
- Layout
-
-
+
+ Layout
+
1 && handleVariantClick('ruling', ruling)"
>
@@ -126,15 +118,10 @@
-
-
-
- Einband
-
-
+
+
-
+
+
+
+
+
+ {{ fact.label }}
+
+
+
+
+
+
-
+
@@ -421,6 +419,18 @@ const productVariantsPatterns = computed(() => {
}));
});
+// Fixed/standalone products (no selectable pages & ruling, e.g. Journaling Booklet)
+// surface their key specs as pre-selected locked chips in the buy box.
+const buyBoxFacts = computed(() => {
+ if (productVariantsPages.value.length || productVariantsRuling.value.length) return [];
+ const s = (technicalSpecs.value ?? {}) as Record
;
+ const facts: { label: string; value: string }[] = [];
+ if (s.Umfang) facts.push({ label: "Umfang", value: s.Umfang });
+ if (s.Layout) facts.push({ label: "Layout", value: s.Layout });
+ if (s.Einband) facts.push({ label: "Einband", value: s.Bindung ? `${s.Einband} · ${s.Bindung}` : s.Einband });
+ return facts;
+});
+
// Testimonials data
const testimonials: Testimonial[] = [
{
diff --git a/pages/index.vue b/pages/index.vue
index 9b1b923..1c47016 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -49,23 +49,32 @@
-
-
-
-
Premium Notizbücher für kreative Köpfe
-
- Erfahre wie unsere handgefertigten Notizbücher aus recyceltem Papier hergestellt werden
-
-
- Jetzt entdecken
+
+
+
+
+
Neu im Sortiment
+
{{ promo.name }}
+
+
+ {{ promo.name }} entdecken
+
+
+
+
+