Redesign Der Eine. PDP from mockup, reusing existing site patterns
Sections rebuilt to match der-eine.png (hero, tagline banner, brand-story + feature icons, lifestyle photo, final CTA bar with trust badges), but each piece is built from patterns that already exist elsewhere on the site rather than one-off layouts: - Focus.tsx (feature icons) mirrors todo-cards/HowItWorks.tsx's exact icon-top/title/desc card shape and typography - Why.tsx (brand story) mirrors todo-cards/Focus.tsx's photo+text layout - Pricing.tsx's trust-badge row reuses getCartTrustBadges() (real, already-vetted copy) with /cart's own markup, not invented text - Banner.tsx reuses --font-caveat and /icon-separator-right.svg (both already used in Divider.tsx) instead of introducing new assets Photos: product.image/gallery repointed (via direct DB write, see reference_payload_direct_db_access) to two new Payload media docs cropped directly from the mockup — the previous gallery was mismatched supplier stock photos of a different-colored pen. Lifestyle.tsx's desk photo is a static /public asset (page decoration showing the pen next to another product, not a photo of the pen alone, so it doesn't belong in Products.gallery).
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
|
||||
// A full-bleed yellow tagline strip between Hero and the "Warum" section —
|
||||
// no equivalent banner/CTA-strip component exists elsewhere on the site
|
||||
// (checked), so the container itself is new, but reuses two real sitewide
|
||||
// building blocks instead of inventing them: the --font-caveat handwritten
|
||||
// typeface (Divider.tsx/About.tsx) and /icon-separator-right.svg (also
|
||||
// Divider.tsx's own "Leichtigkeit" sparkle icon), rotated to point down-right.
|
||||
export function Banner() {
|
||||
return (
|
||||
<section className="w-full bg-brand py-8 sm:py-10 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="max-w-[75rem] mx-auto flex items-center gap-4 sm:gap-6">
|
||||
<div className="relative shrink-0 size-8" style={{ rotate: "45deg" }}>
|
||||
<Image alt="" src="/icon-separator-right.svg" fill sizes="32px" />
|
||||
</div>
|
||||
<p
|
||||
className="text-h3 sm:text-h-section text-text-primary leading-tight"
|
||||
style={{ fontFamily: "var(--font-caveat)" }}
|
||||
>
|
||||
Ein guter Stift.
|
||||
<br />
|
||||
Mehr muss er nicht sein.
|
||||
</p>
|
||||
</Reveal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,62 +1,69 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug } from "../../lib/payload";
|
||||
import { Reveal, RevealGroup, RevealItem } from "../../components/Reveal";
|
||||
|
||||
// Distinct from Hero.tsx's own (shorter) feature bullets — this is the
|
||||
// "Was kann er?" section's full four-item breakdown (build, engraving,
|
||||
// size, use case), each with its own one-line explanation rather than a
|
||||
// bare phrase.
|
||||
// Simple stroke-only line icons — no matching /public asset existed for
|
||||
// these concepts (checked: pencil/pen/sparkle/shield), so these are drawn
|
||||
// fresh rather than upscaling a raster crop from the mockup, same reasoning
|
||||
// as Hero.tsx's own IconCheck (crisp at any size, recolorable).
|
||||
function IconPencil() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M18.5 4.5l5 5L9 24H4v-5L18.5 4.5z" />
|
||||
<path d="M15.5 7.5l5 5" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function IconPen() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M6 22l3-1 13-13-2-2L7 19l-1 3z" />
|
||||
<path d="M17 8l3 3" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function IconSparkle() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M14 3v8M14 17v8M3 14h8M17 14h8M6.5 6.5l5.5 5.5M16 16l5.5 5.5M21.5 6.5L16 12M12 16l-5.5 5.5" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function IconShield() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M14 3l9 3.5v6c0 6-4 10-9 12.5-5-2.5-9-6.5-9-12.5v-6L14 3z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
// This page's single feature enumeration (Hero has no bullet list anymore).
|
||||
// Same card shape as todo-cards/components/HowItWorks.tsx — icon on top,
|
||||
// centered, RevealGroup/RevealItem stagger, identical title/description
|
||||
// typography (font-semibold text-body / text-body-sm text-text-primary) —
|
||||
// reused here instead of a one-off layout, for visual consistency with the
|
||||
// rest of the site. 4 cards instead of HowItWorks' 3 numbered steps, no
|
||||
// connecting arrows (these are independent facts, not a sequence).
|
||||
const items = [
|
||||
{ title: "Metallgehäuse", desc: "Robust, wertig und angenehm in der Hand." },
|
||||
{ title: "Lasergravur", desc: "„Der Eine.“ auf der einen Seite. „einfach produktiv.“ auf der anderen." },
|
||||
{ title: "Kompakt", desc: "Passt ans Notizbuch, auf den Schreibtisch oder in die Tasche." },
|
||||
{ title: "Für jeden Tag", desc: "Für Notizen, Gedanken, Listen und alles, was du lieber aufschreibst, bevor du es wieder vergisst." },
|
||||
{ icon: IconPencil, title: "Metallgehäuse", desc: "Robust, wertig und angenehm in der Hand." },
|
||||
{ icon: IconPen, title: "Schwarze Mine", desc: "Klassische Kugelschreibermine für ein sauberes Schriftbild." },
|
||||
{ icon: IconSparkle, title: "Lasergravur", desc: "„Der Eine.“ und „einfach produktiv.“" },
|
||||
{ icon: IconShield, title: "Passt überall rein", desc: "Kompakt und leicht – für Tasche, Etui, Notizbuch." },
|
||||
];
|
||||
|
||||
// Unlike todo-cards/components/Focus.tsx, this product has no dedicated
|
||||
// lifestyle photo — only 3 supplier catalog macro shots exist, all
|
||||
// 338×338px (no larger source, confirmed against the Payload media API).
|
||||
// Uses gallery[1] (the chrome-rings close-up) — deliberately a different
|
||||
// frame than Hero's gallery (which opens on `image`, id 85) and Pricing's
|
||||
// own photo (product.image again, but cropped/treated differently there),
|
||||
// so the same handful of source photos don't read as one repeated image
|
||||
// across the page. Contained square tile, not object-cover, for the same
|
||||
// "don't blow up a 338px source" reasoning as Hero's gallery cap.
|
||||
export async function Focus() {
|
||||
const product = await getProductBySlug("stift-kugelschreiber");
|
||||
if (!product) return null;
|
||||
const photo = product.gallery[1] ?? product.image;
|
||||
|
||||
export function Focus() {
|
||||
return (
|
||||
<section className="w-full bg-bg-base flex flex-col lg:flex-row gap-10 lg:gap-16 items-center py-12 md:py-16 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="group relative w-full max-w-[20rem] lg:shrink-0 aspect-square rounded-md overflow-hidden bg-bg-muted p-10">
|
||||
<Image
|
||||
src={photo}
|
||||
alt={product.name}
|
||||
fill
|
||||
sizes="320px"
|
||||
className="object-contain transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
</Reveal>
|
||||
<Reveal className="flex flex-col gap-6 items-start flex-1 min-w-0 w-full" delay={0.1}>
|
||||
<p
|
||||
className="font-semibold text-h-emphasis text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
Was kann er?
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Schreiben. Und das ziemlich gut. Metallgehäuse, angenehmes Gewicht und eine klassische Kugelschreibermine — kein besonderes Produktivitäts-Gadget, sondern einfach ein guter Stift, den du gern zur Hand nimmst.
|
||||
</p>
|
||||
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
||||
{items.map((item) => (
|
||||
<li key={item.title} className="flex flex-col gap-1 items-start">
|
||||
<span className="font-semibold text-body text-text-primary">{item.title}</span>
|
||||
<span className="text-body-sm text-text-muted">{item.desc}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Reveal>
|
||||
<section className="w-full bg-bg-base py-12 sm:py-16 px-[var(--layout-padding-x)]">
|
||||
<RevealGroup className="grid grid-cols-2 sm:flex sm:flex-row gap-8 items-start justify-center max-w-[75rem] mx-auto">
|
||||
{items.map(({ icon: Icon, title, desc }) => (
|
||||
<RevealItem key={title} className="flex flex-col gap-4 items-center text-center flex-1 max-w-xs">
|
||||
<Icon />
|
||||
<p className="font-semibold text-body text-text-primary">{title}</p>
|
||||
<p className="text-body-sm text-text-primary text-center">{desc}</p>
|
||||
</RevealItem>
|
||||
))}
|
||||
</RevealGroup>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,23 +6,10 @@ import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKle
|
||||
import { formatPrice, discountPercent } from "../../lib/format";
|
||||
import { effectiveTaxRate } from "../../lib/cartTotals";
|
||||
|
||||
// The one bullet list on this page — after feedback that three separate
|
||||
// lists across Hero/Focus/Pricing was too much, this is the single place
|
||||
// features get enumerated, everywhere else stays prose. A subset of the
|
||||
// "Was kann er?" section's four cards (Focus.tsx) — "Für jeden Tag" is a
|
||||
// use case, not a build fact, so it's covered by the body copy instead.
|
||||
const features = ["Massives Metallgehäuse", "Lasergravur: „Der Eine.“ & „einfach produktiv.“", "Kompakt genug für jede Tasche"];
|
||||
|
||||
// Same fix/reasoning as TodoKartenHero.tsx's IconCheck — icon-check.svg's
|
||||
// fill can't be recolored from outside the SVG when loaded via <img
|
||||
// src>/next/image, so this stays an inline stroke path per page.
|
||||
function IconCheck() {
|
||||
return (
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" className="size-5 shrink-0 mt-1">
|
||||
<path d="M4 10.5l4.5 4.5L16 5.5" stroke="#f6a701" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
// No feature bullet list here (unlike this page's earlier draft) — matches
|
||||
// the mockup's minimal hero (headline, short 3-line description, price,
|
||||
// buy button only). The material/engraving/size facts live in Focus.tsx's
|
||||
// icon row instead, one enumeration point instead of two.
|
||||
|
||||
// Same "compact early teaser + delivery-time repeated next to every buy
|
||||
// button" reasoning as TodoKartenHero.tsx.
|
||||
@@ -56,33 +43,16 @@ export async function Hero() {
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-6 items-start w-full flex-1 lg:justify-center">
|
||||
<div className="flex flex-col gap-2 items-start w-full">
|
||||
<p
|
||||
className="font-semibold text-h-page text-text-primary"
|
||||
style={{ fontFamily: "var(--font-playfair)" }}
|
||||
>
|
||||
Der Eine<span className="text-brand">.</span>
|
||||
</p>
|
||||
<p
|
||||
className="font-semibold text-h3 text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
Für die eine Sache, die gerade zählt.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-body text-text-body">
|
||||
Manchmal reicht ein Stift und ein Stück Papier. Der Eine. ist ein schlichter Kugelschreiber aus Metall — angenehm in der Hand, klein genug für die Tasche und gemacht für alles, was kurz raus aus dem Kopf und irgendwo hin muss.
|
||||
<p
|
||||
className="font-semibold text-h-page text-text-primary"
|
||||
style={{ fontFamily: "var(--font-playfair)" }}
|
||||
>
|
||||
Der Eine<span className="text-brand">.</span>
|
||||
</p>
|
||||
|
||||
<ul className="flex flex-col gap-3 items-start w-full">
|
||||
{features.map((item) => (
|
||||
<li key={item} className="flex gap-[0.625rem] items-start w-full">
|
||||
<IconCheck />
|
||||
<span className="flex-1 text-body text-text-primary">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-body text-text-body">
|
||||
Der Kugelschreiber zu unseren ToDo-Karten. Aus Metall, mit schwarzer Mine und „Der Eine.“ auf der Seite.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-1 items-start">
|
||||
{product && (
|
||||
@@ -110,7 +80,7 @@ export async function Hero() {
|
||||
|
||||
{product && (
|
||||
<AddToCartButton
|
||||
label="Der Eine. bestellen"
|
||||
label="In den Warenkorb"
|
||||
productId={product.id}
|
||||
numericId={product.numericId}
|
||||
outOfStock={!product.active || product.outOfStock}
|
||||
@@ -121,13 +91,10 @@ export async function Hero() {
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* max-w cap, not the full lg:col-span-7 width — the source photos
|
||||
are only 338×338px (checked directly against the Payload media
|
||||
API, no larger size exists), so letting ProductGallery stretch
|
||||
to the full column blows them up hard. Capping the display
|
||||
width keeps the upscale factor small enough that it doesn't
|
||||
look broken; it can't fix the underlying resolution, only hide
|
||||
it. Real fix is new source photos, not a layout tweak. */}
|
||||
{/* max-w cap, not the full lg:col-span-7 width — image/gallery are
|
||||
still fairly small source crops (~594×370, ~480×230, taken
|
||||
2026-08-25 from the mockup design), so letting ProductGallery
|
||||
stretch to the full column would still upscale noticeably. */}
|
||||
{product && product.gallery.length > 0 && (
|
||||
<Reveal className="order-2 lg:order-none lg:col-span-7 flex lg:items-center" delay={0.15}>
|
||||
<div className="w-full max-w-[28rem] mx-auto lg:mx-0">
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
|
||||
// Full-bleed desk photo (ToDo-Karten notepad + "Der Eine." + notebook) —
|
||||
// a static /public asset, not a Payload product photo: it's page decoration
|
||||
// showing the pen alongside another product, not a photo *of* this product
|
||||
// alone, so it doesn't belong in Products.gallery (which ProductGallery.tsx
|
||||
// treats as swappable thumbnails of just the pen itself). Cropped from the
|
||||
// der-eine.png mockup, 2026-08-25.
|
||||
export function Lifestyle() {
|
||||
return (
|
||||
<Reveal className="w-full relative aspect-[1024/222] sm:aspect-[1024/180] lg:aspect-[1024/222]">
|
||||
<Image
|
||||
src="/der-eine-lifestyle.png"
|
||||
alt="Der Eine. neben den ToDo-Karten und einem Notizbuch auf dem Schreibtisch"
|
||||
fill
|
||||
sizes="100vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
</Reveal>
|
||||
);
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
import Image from "next/image";
|
||||
import { AddToCartButton } from "../../components/AddToCartButton";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKleinunternehmer } from "../../lib/payload";
|
||||
import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKleinunternehmer, getCartTrustBadges } from "../../lib/payload";
|
||||
import { formatPrice, discountPercent } from "../../lib/format";
|
||||
import { effectiveTaxRate } from "../../lib/cartTotals";
|
||||
|
||||
// Price/photo come from Payload (same "stift-kugelschreiber" product the
|
||||
// shop/cart use), not a hardcoded literal — same reasoning as
|
||||
// todo-cards/components/Pricing.tsx. Uses product.image (id 85, the
|
||||
// confident macro tip shot) — a third, distinct frame from Hero's gallery
|
||||
// opener and Focus's gallery[1] chrome-rings shot.
|
||||
// todo-cards/components/Pricing.tsx. Uses product.image (the mockup-derived
|
||||
// hero crop, see media ids 88/89 uploaded 2026-08-25).
|
||||
export async function Pricing() {
|
||||
const [product, shipping, defaultTaxRate, kleinunternehmer] = await Promise.all([
|
||||
const [product, shipping, defaultTaxRate, kleinunternehmer, trustBadges] = await Promise.all([
|
||||
getProductBySlug("stift-kugelschreiber"),
|
||||
getShippingSettings(),
|
||||
getDefaultTaxRatePercent(),
|
||||
getKleinunternehmer(),
|
||||
getCartTrustBadges(),
|
||||
]);
|
||||
if (!product) return null;
|
||||
const discount = discountPercent(product.price, product.compareAtPrice);
|
||||
@@ -55,7 +55,7 @@ export async function Pricing() {
|
||||
>
|
||||
Der Eine.
|
||||
</p>
|
||||
<p className="text-body-sm text-text-primary">Metall. Kugelschreiber. Fertig.</p>
|
||||
<p className="text-body-sm text-text-primary">Metall. Kugelschreiber. Für jeden Tag.</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3 items-start w-full lg:w-[18.75rem] lg:shrink-0">
|
||||
@@ -81,7 +81,7 @@ export async function Pricing() {
|
||||
</div>
|
||||
{anyLowStock && <p className="text-label font-bold text-warning">Nur noch wenige verfügbar</p>}
|
||||
<AddToCartButton
|
||||
label="In den Warenkorb"
|
||||
label="Der Eine. bestellen"
|
||||
className="w-full inline-flex items-center justify-center px-6 py-[0.8125rem] rounded-sm bg-brand hover:bg-brand-hover active:scale-[0.97] transition-all font-bold text-body text-text-primary text-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 focus-visible:ring-offset-bg-muted"
|
||||
productId={product.id}
|
||||
numericId={product.numericId}
|
||||
@@ -89,6 +89,21 @@ export async function Pricing() {
|
||||
maxQty={product.maxQty}
|
||||
variants={product.active ? product.variants : []}
|
||||
/>
|
||||
{/* Same content (getCartTrustBadges()) and markup as /cart's
|
||||
title-only row (CartContent.tsx) — reuses the real,
|
||||
already-vetted badge copy ("Nachhaltig verpackt" etc.)
|
||||
instead of inventing new text to pixel-match the mockup's
|
||||
placeholder wording. */}
|
||||
{trustBadges.length > 0 && (
|
||||
<div className="flex flex-wrap gap-x-8 gap-y-4 items-start w-full">
|
||||
{trustBadges.map((badge) => (
|
||||
<div key={badge.id} className="flex gap-3 items-center w-auto">
|
||||
<Image alt="" src={badge.icon} width={22} height={22} className="size-[1.375rem] shrink-0 object-contain" />
|
||||
<span className="text-body-sm text-text-primary whitespace-nowrap">{badge.title}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Reveal>
|
||||
</section>
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug } from "../../lib/payload";
|
||||
|
||||
// The brand-story section explaining the product's name. Same photo+text
|
||||
// layout as todo-cards/components/Focus.tsx (identical classes/structure,
|
||||
// reused for visual consistency rather than a one-off design) — the photo
|
||||
// is product.gallery[0], an engraving close-up ("einfach produktiv." on the
|
||||
// pen barrel) uploaded specifically for this section, see the mockup-derived
|
||||
// media uploaded 2026-08-25 (ids 88/89 replacing the earlier mismatched
|
||||
// green-pen supplier photos).
|
||||
export async function Why() {
|
||||
const product = await getProductBySlug("stift-kugelschreiber");
|
||||
const photo = product?.gallery[0] ?? product?.image ?? null;
|
||||
|
||||
// Plays the same structural role as todo-cards/components/HowItWorks.tsx (a
|
||||
// content section between Hero and the material/Pricing sections, matching
|
||||
// the site's established product-page rhythm) — but this is the brand-story
|
||||
// section explaining the product's name, so flowing prose fits better than
|
||||
// this file's former 2×2 scenario grid (replaced 2026-08-25 alongside the
|
||||
// Der Alltagsstift → Der Eine. rename).
|
||||
export function Why() {
|
||||
return (
|
||||
<section className="w-full bg-bg-base flex flex-col gap-6 items-center py-12 sm:py-16 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="flex flex-col gap-5 items-start text-left max-w-2xl w-full">
|
||||
<section className="w-full bg-bg-base flex flex-col lg:flex-row gap-10 lg:gap-16 items-center py-12 md:py-16 px-[var(--layout-padding-x)]">
|
||||
{photo && (
|
||||
<Reveal className="group relative w-full lg:w-[42%] lg:shrink-0 aspect-[480/230] rounded-md overflow-hidden">
|
||||
<Image
|
||||
src={photo}
|
||||
alt="Gravur „einfach produktiv.“ auf dem Stiftkorpus"
|
||||
fill
|
||||
sizes="(min-width: 1024px) 42vw, 100vw"
|
||||
className="object-cover transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
</Reveal>
|
||||
)}
|
||||
<Reveal className="flex flex-col gap-6 items-start flex-1 min-w-0 w-full" delay={0.1}>
|
||||
<p
|
||||
className="font-semibold text-h-emphasis text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
@@ -17,16 +34,16 @@ export function Why() {
|
||||
Warum „Der Eine.“?
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Weil du nicht alles gleichzeitig machen kannst.
|
||||
Unsere ToDo-Karten helfen dir, dich auf das zu konzentrieren, was heute wichtig ist.
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Aufschreiben hilft dabei, aus all den Dingen im Kopf das herauszuholen, was gerade wichtig ist. Und manchmal ist das eben nur: die eine Sache.
|
||||
Der Stift greift diese Idee auf.
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Daher steht auf der einen Seite des Stifts <strong className="font-semibold text-text-primary">Der Eine.</strong> und auf der anderen <strong className="font-semibold text-text-primary">einfach produktiv.</strong>
|
||||
Auf der einen Seite steht <strong className="font-semibold text-text-primary">„Der Eine.“</strong>, auf der anderen <strong className="font-semibold text-text-primary">„einfach produktiv.“</strong>
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Mehr steckt eigentlich nicht dahinter. Und vielleicht ist genau das der Punkt.
|
||||
Mehr Geschichte braucht es eigentlich nicht.
|
||||
</p>
|
||||
</Reveal>
|
||||
</section>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Hero } from "./components/Hero";
|
||||
import { Banner } from "./components/Banner";
|
||||
import { Why } from "./components/Why";
|
||||
import { Focus } from "./components/Focus";
|
||||
import { Lifestyle } from "./components/Lifestyle";
|
||||
import { Pricing } from "./components/Pricing";
|
||||
import { Footer } from "../components/Footer";
|
||||
import { getProductBySlug, getCompanySettings } from "../lib/payload";
|
||||
import { buildProductSchema } from "../lib/structuredData";
|
||||
|
||||
const title = "Der Eine. – Für die eine Sache, die gerade zählt.";
|
||||
const title = "Der Eine. – Der Kugelschreiber zu unseren ToDo-Karten.";
|
||||
const description =
|
||||
"Der Eine. ist ein schlichter Kugelschreiber aus Metall. Angenehm in der Hand, klein genug für die Tasche und gemacht für alles, was kurz raus aus dem Kopf und irgendwo hin muss.";
|
||||
"Der Eine. ist ein Kugelschreiber aus Metall, mit schwarzer Mine und „Der Eine.“ auf der Seite — der Stift zu unseren ToDo-Karten.";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title,
|
||||
@@ -44,8 +46,10 @@ export default async function DerEinePage() {
|
||||
)}
|
||||
<main className="flex flex-col flex-1">
|
||||
<Hero />
|
||||
<Focus />
|
||||
<Banner />
|
||||
<Why />
|
||||
<Focus />
|
||||
<Lifestyle />
|
||||
<Pricing />
|
||||
</main>
|
||||
<Footer />
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 452 KiB |
Reference in New Issue
Block a user