docs: design spec for Header + Cómo empezar + Footer additions

This commit is contained in:
erikgh committed 2026-07-21 15:31:55 -06:00
1 parent 421576a5b7
commit 4f73312526
1 file changed
+157
@@ -0,0 +1,157 @@
# 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:
1. A minimal sticky **Header** (wordmark + persistent CTA).
2. A new **"Cómo empezar"** section (3 client-facing steps ending in a direct WhatsApp link).
3. 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 shared `Wordmark` primitive (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 claves `comoEmpezar` y `footer`).
- **Voz** en segunda persona, sin jerga corporativa. **Idioma** español.
- **Todas las animaciones Framer Motion** se desactivan con `prefers-reduced-motion` via `usePrefersReducedMotion()` + `motionProps(reduced)` (same pattern the 7 sections already use).
- **`output: export`** — el build estático debe seguir produciendo `out/`.
## 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>` with `sticky top-0 z-50`, light background (`bg-base/80` or `bg-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 `CTA` primitive, `variant="light"`, label from `cierre.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):**
1. **Escríbeme** — cuéntame dónde está tu negocio hoy.
2. **Sesión de diagnóstico** — una conversación para ubicar tu punto de inflexión.
3. **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 in `content.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`)
```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 `href` starts with `https://wa.me/` and includes the encoded prefilled `text`.
- **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 uses `gold-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).