9.9 KiB
creeer Landing — Additions: Header + Cómo empezar + Footer
Date: 2026-07-21
Branch: feat/header-comoempezar-footer
Builds on: docs/superpowers/specs/2026-07-20-creeer-landing-design.md (original 7-section landing, already implemented).
Goal
Complete the page's structural chrome and its conversion on-ramp by adding three pieces to the existing one-page landing:
- A minimal sticky Header (wordmark + persistent CTA).
- A new "Cómo empezar" section (3 client-facing steps ending in a direct WhatsApp link).
- A slim Footer.
No new architecture: these reuse the existing primitives, tokens, motion pattern, and content-in-lib/content.ts convention. Still a statically-exported Next.js 14 site — no backend, no forms, contact via direct links only.
Global constraints (inherited — apply to every piece here)
- Wordmark always lowercase
creeer., rendered via the sharedWordmarkprimitive (never re-implemented, never uppercased). - Paleta (tokens):
ink #0A1F44·gold #B8901f(accents on LIGHT) ·gold-bright #D4AF37(accents on DARK) ·base #FBFAF7(light bg) ·cream #F5EBD0(text on dark) ·muted/muted-dark. - Tipografía híbrida: Georgia italic = voz de marca (wordmark + citas + títulos de sección); Inter = body/UI.
- Sin backend, sin formularios — contacto solo por enlaces directos (WhatsApp/mailto/LinkedIn).
- Un único
<h1>en toda la página — vive en el Hero. New pieces use<h2>/<h3>or no heading; Header/Footer carry no heading. - Todo el copy vive en
lib/content.ts(nuevas clavescomoEmpezaryfooter). - Voz en segunda persona, sin jerga corporativa. Idioma español.
- Todas las animaciones Framer Motion se desactivan con
prefers-reduced-motionviausePrefersReducedMotion()+motionProps(reduced)(same pattern the 7 sections already use). output: export— el build estático debe seguir produciendoout/.
File structure (additions)
components/
├── layout/
│ ├── Header.tsx # NEW — sticky bar (server component, pure CSS sticky)
│ ├── Footer.tsx # NEW — slim footer strip
│ └── __tests__/
│ ├── Header.test.tsx # NEW
│ └── Footer.test.tsx # NEW
└── sections/
├── ComoEmpezar.tsx # NEW — section 07 (client component, motion pattern)
└── __tests__/
└── ComoEmpezar.test.tsx # NEW
lib/content.ts # ADD `comoEmpezar` and `footer` keys
app/page.tsx # compose Header + ComoEmpezar + Footer
Component 1 — Header (minimal sticky)
Interface: Header() at components/layout/Header.tsx. No props. Server component (no state, no JS — position: sticky is pure CSS).
Layout & style:
<header>withsticky top-0 z-50, light background (bg-base/80orbg-pure/80) +backdrop-blur+ a subtle bottom border (border-b border-ink/10). The light bar stays legible while scrolling over both light and dark sections.- A
Container-width inner row,flex items-center justify-between, vertical padding ~py-3/py-4. - Left:
<Wordmark size="base" />wrapped in an<a href="#top">(or the page top) — the wordmark ink color is the default (dark on the light bar). - Right: the
CTAprimitive,variant="light", label fromcierre.cta("Define tu siguiente movimiento"+→),href="#contacto". On small screens the CTA stays but may use a slightly smaller padding/label; the wordmark + CTA layout is identical on mobile (no menu, no hamburger). - Semantic
<header>; wrap the CTA link region in<nav aria-label="Principal">. No animation (nothing to gate on reduced motion).
A11y: the sticky header must not obscure anchor targets — ensure #contacto still scrolls into view (the closing section has ample padding; acceptable without extra scroll-margin, but scroll-mt on anchor targets may be added if visual testing shows clipping).
Component 2 — "Cómo empezar" section (07)
Interface: ComoEmpezar() at components/sections/ComoEmpezar.tsx. Client component using the established motion + usePrefersReducedMotion() + motionProps(reduced) + Container pattern (mirror Mecanismo.tsx/Disciplinas.tsx).
Placement: inserted between <Estratega /> (06) and <Cierre />. Cierre becomes section 08. This positions the on-ramp right before the contact close.
Purpose & differentiation: this is the client's on-ramp ("cómo empezar contigo"), distinct from Mecanismo which is her method ("cómo trabajo"). Framing is the engagement path that ends in the WhatsApp CTA.
Layout & style: light section (bg-base), py-24 md:py-32. Eyebrow + <h2> title (Georgia italic), then 3 numbered steps in a md:grid-cols-3 grid using the Mecanismo visual language (large Georgia-italic numbers 01/02/03 in gold, step name <h3>, short description in muted). A final CTA below the steps.
Steps (starting copy in content.ts, editable by the dueña):
- Escríbeme — cuéntame dónde está tu negocio hoy.
- Sesión de diagnóstico — una conversación para ubicar tu punto de inflexión.
- Estrategia ejecutable — sales con claridad y tu siguiente movimiento definido.
CTA (direct WhatsApp with prefilled message): an <a> (or the CTA primitive) whose href is the WhatsApp click-to-chat URL with a prefilled text, e.g. https://wa.me/<number>?text=Hola%2C%20quiero%20agendar%20una%20sesi%C3%B3n%20de%20diagn%C3%B3stico. The base number reuses cierre.contact.whatsapp (currently the 520000000000 placeholder — a TODO pending the dueña's real number). The full prefilled href and the un-encoded message live in content.ts under comoEmpezar so copy/number changes touch only content.
Light-section token discipline: accents in gold (never gold-bright), bg-base, text-ink/text-muted — matching the other light sections.
Component 3 — Footer (slim strip)
Interface: Footer() at components/layout/Footer.tsx. No props. Static (no motion).
Rationale: Cierre already renders the closing quote, primary CTA, and the three contact links. The footer therefore does not repeat the contact list — that would be redundant and produce a heavy "double dark block" right after the dark Cierre. Instead it is a thin closing strip.
Layout & style: <footer> with bg-dark, a subtle top divider (border-t border-cream/10), modest vertical padding (py-8/py-10), Container-width. Contents, centered or space-between:
<Wordmark size="base" onDark />(small, gold-bright middle-e / period per the primitive).- A short tagline:
"tu estratega de crecimiento"(text-muted-dark/cream, small). - Legal line:
© 2026 creeer(year from a constant incontent.ts, or computed — see decision below).
Decision — year: use a static © 2026 creeer string stored in content.ts footer.legal (static export → no need for a live new Date(); keeps the build deterministic and the copy in one place). The dueña/maintainer updates the year with the rest of the copy.
Out of scope: no privacy-policy page / aviso de privacidad, no social-icon set beyond what Cierre already links. These can be added later as their own change.
Content additions (lib/content.ts)
export const comoEmpezar = {
eyebrow: 'cómo empezar',
title: 'Tu siguiente movimiento empieza con una conversación.', // Georgia-italic h2
steps: [
{ n: '01', name: 'Escríbeme', desc: 'cuéntame dónde está tu negocio hoy.' },
{ n: '02', name: 'Sesión de diagnóstico', desc: 'una conversación para ubicar tu punto de inflexión.' },
{ n: '03', name: 'Estrategia ejecutable', desc: 'sales con claridad y tu siguiente movimiento definido.' },
],
cta: 'Agenda tu sesión de diagnóstico',
// WhatsApp prefilled: base number reused from `cierre.contact.whatsapp`
whatsappText: 'Hola, quiero agendar una sesión de diagnóstico',
};
export const footer = {
tagline: 'tu estratega de crecimiento',
legal: '© 2026 creeer',
};
The ComoEmpezar component builds the WhatsApp href from the cierre.contact.whatsapp number + encodeURIComponent(comoEmpezar.whatsappText) so number and message stay single-sourced. All copy above (title, steps, CTA, tagline) is a sensible default that the dueña can edit in content.ts.
Page composition (app/page.tsx)
<Header />
<main>
<Hero variant="editorial" />
<FraseAncla />
<ParaQuien />
<Mecanismo />
<Disciplinas />
<Estratega />
<ComoEmpezar /> {/* NEW — 07 */}
<Cierre /> {/* now 08 */}
</main>
<Footer />
The JSON-LD <script> already present in the page is preserved. Single-<h1> invariant holds (only Hero).
Testing (thin, matching the existing per-section pattern)
- Header: renders the wordmark text and a CTA link with
href="#contacto". - ComoEmpezar: renders the three step names and a WhatsApp link whose
hrefstarts withhttps://wa.me/and includes the encoded prefilledtext. - Footer: renders the wordmark and the legal/year line; does not introduce a second
<h1>.
matchMedia is already stubbed in vitest.setup.ts, so ComoEmpezar's usePrefersReducedMotion() works in tests.
Constraints satisfied
- No backend, no forms; contact via direct links (Header CTA →
#contacto; ComoEmpezar →wa.me). - Existing palette/typography/tokens reused; light section uses
gold, dark footer usesgold-bright/cream. - Single
<h1>preserved (Hero only). - Reduced-motion honored uniformly (ComoEmpezar follows the motion pattern; Header/Footer are static).
- Static export unaffected (all client interactivity is CSS/anchor links).
Out of scope (future changes, each its own branch)
- Testimonials / social proof, results/case studies, FAQ.
- Privacy-policy page, cookie/analytics integration.
- Real OG image, branded favicon, real portrait photo, real contact details (dueña-pending).