Files
cameleer-website/docs/superpowers/plans/2026-04-25-cameleer-website-relaunch.md

1132 lines
40 KiB
Markdown
Raw Permalink Normal View History

# Cameleer Website Relaunch — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Rebuild the Cameleer homepage composition + copy on the existing static Astro 5 stack to fix conversion gaps identified in the post-launch design review (single H1, social proof strip, before/after walkthrough, simplified pricing teaser, fewer puns).
**Architecture:** Pure content + structural change. No new dependencies, no backend, no analytics, no forms. Two new section components replace two retired ones; five existing sections rebuilt-in-place; tier names refreshed across `index.astro` and `/pricing.astro`. One CSS line added (`scroll-behavior: smooth`) for the new in-page anchor CTA.
**Tech Stack:** Astro 5, Tailwind CSS, vitest (existing), html-validate, linkinator, Lighthouse CI. No new libraries.
**Spec:** `docs/superpowers/specs/2026-04-25-cameleer-website-relaunch-design.md`
---
## File structure
**New files:**
- `src/components/sections/SocialProofStrip.astro` — founder quote + design-partner CTA (new section, sits between Hero and walkthrough)
- `src/components/sections/ThreeAmWalkthrough.astro` — before/after split with 3 callouts (replaces DualValueProps + ProductShowcase)
**Deleted files:**
- `src/components/sections/DualValueProps.astro`
- `src/components/sections/ProductShowcase.astro`
**Modified files:**
- `src/components/sections/Hero.astro` — kill rotator, single H1, microline, secondary CTA, annotation pin overlay
- `src/components/sections/HowItWorks.astro` — slim copy on steps 1, 3
- `src/components/sections/WhyUs.astro` — drop `03:00` watermark, reword card 2
- `src/components/sections/PricingTeaser.astro` — rename tiers, 2 cards on homepage, "See all plans" link
- `src/components/sections/FinalCTA.astro` — H2 + sub + single CTA reword
- `src/pages/index.astro` — section imports/order updated
- `src/pages/pricing.astro` — tier names refreshed
- `src/styles/global.css` — add `html { scroll-behavior: smooth }` plus reduced-motion override
**Unchanged (do not touch):**
- `src/components/SiteHeader.astro`, `SiteFooter.astro`, `CTAButtons.astro`, `Lightbox.astro`, `TopographicBg.astro`, `RouteDiagram.astro`
- `src/middleware.ts`, `src/middleware.test.ts`
- `src/config/auth.ts` (existing tests cover this — must stay green)
- `astro.config.mjs`, `tailwind.config.mjs`, `package.json`
---
## Working assumptions
- Branch `relaunch-2026-04-25` is checked out (already created).
- Spec doc is committed at `e338347` (already done).
- `npm ci` has been run; `node_modules/` is present.
- Tailwind tokens used in this plan all exist in `tailwind.config.mjs` — verified: `bg`, `bg-elevated`, `border`, `border-strong`, `accent`, `accent-muted`, `cyan`, `text`, `text-muted`, `text-faint`, `font-sans`, `font-mono`, `text-hero`, `max-w-content`, `max-w-prose`.
- The CTAButtons component API is unchanged — it already accepts `secondaryLabel`, `secondaryHref`, `showSecondary` props.
---
## Task 1: Add `scroll-behavior: smooth` to global.css
**Files:**
- Modify: `src/styles/global.css`
**Why first:** Foundational and tiny; the new hero anchor CTA needs it. Keep separate so the diff is reviewable on its own.
- [ ] **Step 1.1: Read the file**
Use the Read tool on `src/styles/global.css` (required by edit hooks).
- [ ] **Step 1.2: Insert the smooth-scroll rule into the `html` block**
The existing `html` block at line 16-21:
```css
html {
@apply bg-bg text-text font-sans;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
```
Replace with (adds the one new property):
```css
html {
@apply bg-bg text-text font-sans;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
```
- [ ] **Step 1.3: Verify the build still works**
Run: `npm run build`
Expected: `✔ Completed in …ms` with no errors and `dist/` populated.
- [ ] **Step 1.4: Commit**
```bash
git add src/styles/global.css
git commit -m "feat(styles): enable smooth in-page anchor scrolling
Adds html { scroll-behavior: smooth } with a prefers-reduced-motion
override. Required for the relaunch hero's 'See it in action' anchor
CTA to feel natural.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 2: Create `SocialProofStrip.astro`
**Files:**
- Create: `src/components/sections/SocialProofStrip.astro`
**Spec reference:** §6.2 of the design spec.
**Why now:** Add the new component before any consumer references it. Astro is happy with unimported components, so the build stays green throughout.
- [ ] **Step 2.1: Create the file with the full component body**
Write the full content below to `src/components/sections/SocialProofStrip.astro`:
```astro
---
import { getAuthConfig } from '../../config/auth';
const auth = getAuthConfig();
// PENDING — must be filled in before publish:
// 1. [Founder Name] placeholder below.
// 2. The "ex-nJAMS" mention is gated on Hendrik's trademark review
// (same pattern as WhyUs.astro §10 caveat). If the review is not
// cleared by publish time, drop the " · ex-nJAMS" suffix from the
// attribution line.
const founderName = '[Founder Name]';
const designPartnerSubject = 'Design partner enquiry — Cameleer';
const designPartnerHref = `mailto:${auth.salesEmail}?subject=${encodeURIComponent(designPartnerSubject)}`;
---
<section class="border-b border-border">
<div class="max-w-content mx-auto px-6 py-16 md:py-20">
<div class="max-w-3xl mx-auto">
<p class="text-accent font-mono text-xs tracking-[0.25em] uppercase mb-4">
// Built by people who've done this before
</p>
<blockquote class="border-l-[3px] border-accent pl-5 max-w-[62ch]">
<p class="text-lg md:text-xl text-text italic leading-relaxed mb-3">
&ldquo;We spent 15 years building integration monitoring for banks that couldn&rsquo;t afford downtime. Cameleer is what we&rsquo;d build today &mdash; purpose-built for Apache Camel, no retrofit.&rdquo;
</p>
<footer class="text-sm font-mono text-text-muted">
&mdash; <span class="text-text">{founderName}</span>, co-founder &middot; ex-nJAMS
</footer>
</blockquote>
<a
href={designPartnerHref}
class="inline-flex items-center gap-2 mt-7 font-mono text-sm text-cyan hover:text-accent transition-colors"
>
Apply to the design-partner program <span aria-hidden="true">&rarr;</span>
</a>
</div>
</div>
</section>
```
- [ ] **Step 2.2: Verify the build**
Run: `npm run build`
Expected: build succeeds. The component isn't imported yet, so it produces no output but must still type-check.
- [ ] **Step 2.3: Commit**
```bash
git add src/components/sections/SocialProofStrip.astro
git commit -m "feat(sections): add SocialProofStrip component
Founder pedigree quote plus design-partner mailto CTA.
Uses auth.salesEmail (not auth.salesMailto) so we can pass a subject.
Two PENDING gates documented in the component:
- [Founder Name] placeholder
- 'ex-nJAMS' wording subject to trademark clearance
Component is created but not yet wired into index.astro.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 3: Create `ThreeAmWalkthrough.astro`
**Files:**
- Create: `src/components/sections/ThreeAmWalkthrough.astro`
**Spec reference:** §6.3 of the design spec.
- [ ] **Step 3.1: Create the file with the full component body**
Write the full content below to `src/components/sections/ThreeAmWalkthrough.astro`:
```astro
---
import Lightbox from '../Lightbox.astro';
interface Callout {
title: string;
body: string;
}
const callouts: Callout[] = [
{
title: 'Cross-service correlation.',
body: 'Every exchange carries its correlation ID forward. One click jumps to what the downstream route did with the same message.',
},
{
title: 'Runtime detail, not guesswork.',
body: 'Circuit breaker tripped. Fallback path ran. Request tried backend:80. The pieces a 3 AM page actually needs — already captured.',
},
{
title: 'The whole story of a failure.',
body: 'Exception class, message, stack trace, headers, payload — all pinned to the exchange. No log-grepping tour.',
},
];
---
<section id="walkthrough" class="border-b border-border bg-bg">
<div class="max-w-content mx-auto px-6 py-24 md:py-32">
<div class="max-w-3xl mb-14 md:mb-20">
<p class="text-cyan font-mono text-xs tracking-[0.25em] uppercase mb-4">// When something breaks</p>
<h2 class="text-hero font-bold text-text mb-5">
The 3 AM page. With and without Cameleer.
</h2>
<p class="text-lg text-text-muted leading-relaxed">
Same Camel app. Same failed exchange. Different night.
</p>
</div>
<div class="grid md:grid-cols-2 gap-6 md:gap-8 items-stretch">
<!-- Left: Without Cameleer -->
<div class="without-card relative rounded-lg border border-dashed border-border-strong bg-bg overflow-hidden">
<div class="px-5 pt-5 pb-3 font-mono text-[11px] tracking-[0.2em] uppercase text-text-faint border-b border-border">
Without Cameleer · 03:12 AM
</div>
<pre class="font-mono text-[13px] leading-[1.65] text-text-muted px-5 py-5 overflow-x-auto whitespace-pre"><code><span class="text-text">$</span> kubectl logs camel-router-7d4f8c
<span class="text-rose">ERROR</span> org.apache.camel.CamelExecutionException
at org.apache.camel.processor.SendProcessor.process
at org.apache.camel.processor.Pipeline.process
...
<span class="text-text">$</span> grep "order-842" *.log
router-3.log: <span class="text-accent">WARN</span> exchange order-842 stuck in saga-fulfillment
router-3.log: <span class="text-rose">ERROR</span> processor backend:80 → connect timeout
<span class="text-text">$</span> ssh prod-integration-3
prod-integration-3 $ kubectl logs ...
&gt; <span class="text-cyan">slack #integration-team</span>
"anyone know why order-842 is stuck??"
<span class="text-text-faint">[3 of 4 reactions, no answer]</span>
<span class="text-accent">~47 min later: someone wakes up an SRE.</span></code></pre>
</div>
<!-- Right: With Cameleer -->
<figure class="with-card relative rounded-lg border border-border-strong bg-bg-elevated overflow-hidden">
<div class="px-5 pt-5 pb-3 font-mono text-[11px] tracking-[0.2em] uppercase text-accent border-b border-border">
With Cameleer · 30 sec
</div>
<Lightbox
src="/product/error-detail.png"
alt="Cameleer Mission Control — failed exchange order-842 with full execution context"
width={1920}
height={945}
loading="lazy"
imgClass="block w-full h-auto"
/>
<div class="px-5 py-4 font-mono text-[13px] leading-[1.6] text-text-muted border-t border-border">
<span class="text-accent">▸</span> Open exchange <span class="text-text">order-842</span> → see the failure pinned → click <span class="text-text">Replay</span> after fix.
</div>
<div class="absolute inset-0 ring-1 ring-inset ring-accent/10 pointer-events-none rounded-lg"></div>
</figure>
</div>
<ul class="grid md:grid-cols-3 gap-6 md:gap-8 mt-14">
{callouts.map((c, i) => (
<li class="relative pl-10">
<span
class="absolute left-0 top-0 inline-flex items-center justify-center w-7 h-7 rounded-full border border-accent/40 bg-accent/10 text-accent font-mono text-xs"
aria-hidden="true"
>
{String(i + 1).padStart(2, '0')}
</span>
<h3 class="text-text font-semibold mb-1.5">{c.title}</h3>
<p class="text-text-muted leading-relaxed">{c.body}</p>
</li>
))}
</ul>
</div>
</section>
<style>
.with-card {
box-shadow:
0 1px 0 rgba(240, 180, 41, 0.08) inset,
0 30px 60px -25px rgba(0, 0, 0, 0.7),
0 12px 30px -12px rgba(0, 0, 0, 0.5);
}
</style>
```
- [ ] **Step 3.2: Verify the build**
Run: `npm run build`
Expected: build succeeds. Linkinator hasn't run yet — anchor target `#walkthrough` will validate when this section is wired into index.astro (Task 10).
- [ ] **Step 3.3: Commit**
```bash
git add src/components/sections/ThreeAmWalkthrough.astro
git commit -m "feat(sections): add ThreeAmWalkthrough component
Replaces DualValueProps + ProductShowcase with a single before/after
split: a styled <pre> block (the 'without' state) next to the
existing /product/error-detail.png screenshot (the 'with' state).
Three short callouts below.
Section anchor #walkthrough is the target for the Hero's
'See it in action ↓' secondary CTA (added in Task 4).
The 'without' panel is implemented as a styled <pre> per the spec —
no asset production required. A future phase may swap to a recorded
terminal screencap; that swap is a one-component change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 4: Rebuild `Hero.astro`
**Files:**
- Modify: `src/components/sections/Hero.astro`
**Spec reference:** §6.1 of the design spec.
**Changes:**
1. Remove the rotator (3 spans inside H1, the wrapper styles `.hero-rotator` / `.hero-line`, the `<script>` block).
2. Replace with a single H1.
3. Add the price microline under the CTAs.
4. Pass new props to `CTAButtons` for the secondary CTA (`See it in action ↓``#walkthrough`).
5. Add three positioned annotation pins on top of the existing screenshot, plus three short callout labels rendered below the image.
- [ ] **Step 4.1: Read the current file**
Use the Read tool on `src/components/sections/Hero.astro` (required by edit hooks).
- [ ] **Step 4.2: Replace the file with the rebuilt version**
Write the full content below to `src/components/sections/Hero.astro`:
```astro
---
import CTAButtons from '../CTAButtons.astro';
import TopographicBg from '../TopographicBg.astro';
import Lightbox from '../Lightbox.astro';
interface Pin {
label: string;
body: string;
// Position percentages relative to the screenshot container.
top: string;
left: string;
}
const pins: Pin[] = [
{ label: '01', body: 'Correlation ID — click to follow one exchange across services.', top: '14%', left: '12%' },
{ label: '02', body: 'Failure in context — circuit breaker tripped, fallback ran, tried backend:80.', top: '46%', left: '52%' },
{ label: '03', body: 'Full error pinned — exception, stack trace, headers, payload.', top: '78%', left: '78%' },
];
---
<section class="relative overflow-hidden border-b border-border">
<TopographicBg opacity={0.22} lines={11} />
<div class="relative max-w-content mx-auto px-6 pt-16 pb-20 md:pt-24 md:pb-24 lg:pt-28">
<div class="grid lg:grid-cols-12 gap-10 lg:gap-14 items-center">
<div class="lg:col-span-5">
<img
src="/cameleer-logo.svg"
width="64"
height="64"
alt=""
decoding="async"
class="shrink-0 mb-5 hero-mark"
/>
<p
class="inline-flex items-center gap-2 mb-7 rounded-full border border-accent/30 bg-accent/[0.08] text-accent px-3.5 py-1 text-sm italic font-medium"
>
<span aria-hidden="true" class="text-base">✦</span>
Your camels called. They want a GPS.
</p>
<h1 class="font-bold text-text mb-6 hero-h1">
Ship Camel integrations. Sleep through the night.
</h1>
<p class="text-lg md:text-xl text-text-muted max-w-prose leading-relaxed mb-8">
Cameleer is the hosted runtime and observability platform for Apache Camel — auto-traced, replay-ready, cross-service correlated. The 3 AM page becomes a 30-second answer.
</p>
<CTAButtons
size="lg"
secondaryLabel="See it in action ↓"
secondaryHref="#walkthrough"
/>
<p class="mt-4 font-mono text-xs text-text-faint">
14-day trial · from €20/mo · no credit card
</p>
</div>
<div class="lg:col-span-7 relative">
<div class="hero-shot relative rounded-lg border border-border-strong bg-bg-elevated overflow-hidden">
<Lightbox
src="/product/exchange-detail.png"
alt="Cameleer Mission Control — route execution detail with processor-level trace"
width={1920}
height={945}
loading="eager"
/>
<div class="absolute inset-0 ring-1 ring-inset ring-accent/10 pointer-events-none rounded-lg"></div>
{pins.map((pin) => (
<span
aria-hidden="true"
class="hero-pin absolute inline-flex items-center justify-center w-7 h-7 rounded-full bg-accent text-bg font-mono text-xs font-bold pointer-events-none"
style={`top:${pin.top};left:${pin.left}`}
>
{pin.label}
</span>
))}
</div>
<ul class="hero-pin-legend mt-5 grid sm:grid-cols-3 gap-3 text-text-muted">
{pins.map((pin) => (
<li class="flex items-start gap-2 text-sm leading-snug">
<span class="font-mono text-accent text-xs mt-0.5">{pin.label}</span>
<span>{pin.body}</span>
</li>
))}
</ul>
<div aria-hidden="true" class="hero-shot-glow"></div>
</div>
</div>
</div>
</section>
<style>
.hero-h1 {
font-size: clamp(2.25rem, 4.5vw, 4rem);
line-height: 1.05;
letter-spacing: -0.02em;
}
.hero-shot {
box-shadow:
0 1px 0 rgba(240, 180, 41, 0.08) inset,
0 30px 60px -20px rgba(0, 0, 0, 0.6),
0 10px 25px -10px rgba(0, 0, 0, 0.5);
}
.hero-pin {
box-shadow: 0 0 0 4px rgba(240, 180, 41, 0.22), 0 4px 10px -2px rgba(0, 0, 0, 0.5);
transform: translate(-50%, -50%);
}
.hero-shot-glow {
position: absolute;
inset: 10% -5% 10% -5%;
background: radial-gradient(60% 60% at 50% 50%, rgba(240, 180, 41, 0.18), transparent 70%);
filter: blur(40px);
z-index: -1;
}
@keyframes hero-mark-sway {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-2px) rotate(-1.5deg); }
}
.hero-mark {
animation: hero-mark-sway 7s ease-in-out infinite;
transform-origin: 50% 90%;
}
@media (prefers-reduced-motion: reduce) {
.hero-mark { animation: none; }
}
</style>
```
- [ ] **Step 4.3: Verify the build**
Run: `npm run build`
Expected: build succeeds. The rotator script and old `[data-hero-rotator]` selector are gone.
- [ ] **Step 4.4: Commit**
```bash
git add src/components/sections/Hero.astro
git commit -m "feat(hero): single H1, annotation pins, microline, anchor CTA
- Drop the rotating headline and its <script> block
- Replace with single category-defining H1: 'Ship Camel integrations.
Sleep through the night.'
- Add price microline under the CTAs (14-day trial · from €20/mo)
- Replace 'Sign in' secondary CTA with 'See it in action ↓' anchor
to #walkthrough
- Add three numbered annotation pins overlaid on the screenshot,
with a 3-up legend below the image (correlation ID, failure
context, error pinned)
The eyebrow pill is retained — the only surviving camel pun on
the homepage per the pun-budget decision in the spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 5: Slim `HowItWorks.astro` copy
**Files:**
- Modify: `src/components/sections/HowItWorks.astro`
**Spec reference:** §6.4. Cut the redundant "no SDK / nothing to instrument" repetition since it's already in the Hero sub.
- [ ] **Step 5.1: Read the current file**
Use the Read tool on `src/components/sections/HowItWorks.astro`.
- [ ] **Step 5.2: Apply the edit**
Replace the `steps` array (current lines 9-25) with the slimmed version:
```astro
const steps: Step[] = [
{
n: '01',
title: 'Point us at your Camel app',
body: 'Drop it in, or connect one you already run. No code changes.',
},
{
n: '02',
title: 'We take it from there',
body: 'Every route, every processor, every exchange — discovered and traced automatically. Sensitive fields are masked by default.',
},
{
n: '03',
title: 'Watch it run',
body: 'Browse executions, tap live traffic, replay failed exchanges, follow flows across services.',
},
];
```
(Use the Edit tool — `old_string` is the existing `steps` array literal, `new_string` is the new one above.)
- [ ] **Step 5.3: Verify the build**
Run: `npm run build`
Expected: build succeeds.
- [ ] **Step 5.4: Commit**
```bash
git add src/components/sections/HowItWorks.astro
git commit -m "refactor(how-it-works): slim repetitive 'no SDK' boilerplate
The 'no code changes / no SDK / no rewrite' line is already said
clearly in the Hero subhead and the WhyUs cards. Repeating it on
step 1 of HowItWorks adds nothing. Step 3's tail 'Nothing to
instrument. Nothing to maintain.' is two sentences saying the
same thing — both removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 6: Refresh `WhyUs.astro` (cut watermark, reword card 2)
**Files:**
- Modify: `src/components/sections/WhyUs.astro`
**Spec reference:** §6.5. Two changes: drop the giant `03:00` decorative watermark on card 2, and reword card 2 to remove the second 3 AM reference.
- [ ] **Step 6.1: Read the current file**
Use the Read tool on `src/components/sections/WhyUs.astro`.
- [ ] **Step 6.2: Replace the file with the refreshed version**
Write the full content below to `src/components/sections/WhyUs.astro`:
```astro
---
// Final nJAMS-legacy wording is subject to Hendrik's trademark review before go-live
// (see docs/superpowers/specs/2026-04-24-cameleer-website-design.md §10).
---
<section class="border-b border-border">
<div class="max-w-content mx-auto px-6 py-20 md:py-24">
<div class="max-w-2xl mb-16">
<p class="text-accent font-mono text-xs tracking-[0.25em] uppercase mb-4">Why Cameleer</p>
<h2 class="text-hero font-bold text-text mb-4">
A purpose-built tool, from the team that has built integration observability before.
</h2>
</div>
<div class="grid md:grid-cols-2 gap-8 md:gap-12">
<div class="rounded-lg border border-border bg-bg-elevated p-8 transition-all duration-200 ease-out hover:-translate-y-0.5 hover:border-accent/40 hover:shadow-[0_12px_32px_-12px_rgba(240,180,41,0.18)]">
<h3 class="text-xl font-bold text-text mb-4">Generic APMs do not understand Camel. Cameleer does.</h3>
<p class="text-text-muted leading-relaxed mb-4">
Most monitoring tools see your app as a Java process and a pile of HTTP calls. Cameleer understands that you are running a Camel app — choices, splits, multicasts, error handlers, and every other EIP pattern as first-class citizens.
</p>
<p class="text-text-muted leading-relaxed">
So when you ask &ldquo;why did this exchange fail?&rdquo;, you get an answer, not a log tail. And you can reach back into a running app to replay a message, deep-trace a correlation ID, or toggle recording — observability that does things, not just shows them.
</p>
</div>
<div class="rounded-lg border border-border bg-bg-elevated p-8 transition-all duration-200 ease-out hover:-translate-y-0.5 hover:border-accent/40 hover:shadow-[0_12px_32px_-12px_rgba(240,180,41,0.18)]">
<h3 class="text-xl font-bold text-text mb-4">Built by people who've operated integration in production for 15 years.</h3>
<p class="text-text-muted leading-relaxed mb-4">
We spent over a decade building integration monitoring for banks, insurers, and logistics operators — the kind of shops where a stuck exchange is a regulatory event, not just an inconvenience.
</p>
<p class="text-text-muted leading-relaxed">
Cameleer is what we'd build today, purpose-built for Apache Camel. No legacy, no retrofit, no assumptions about a generic middleware platform.
</p>
</div>
</div>
</div>
</section>
```
- [ ] **Step 6.3: Verify the build**
Run: `npm run build`
Expected: build succeeds.
- [ ] **Step 6.4: Commit**
```bash
git add src/components/sections/WhyUs.astro
git commit -m "refactor(why-us): drop 03:00 watermark, reword card 2
The decorative giant '03:00' watermark on card 2 plus its 'live'
ops-desk timestamp gimmick was the third repetition of the 3 AM
metaphor on the homepage — the post-launch review flagged that
five hits turns a sharp pain point into a slogan.
Card 2 reworded to lead with 'operated integration in production
for 15 years' — same pedigree claim, no second 3 AM reference.
The walkthrough section already does the 3 AM beat in full.
Card 1 unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 7: Rebuild `FinalCTA.astro`
**Files:**
- Modify: `src/components/sections/FinalCTA.astro`
**Spec reference:** §6.7. Drop the camel pun, reword H2 to bookend the hero, single CTA.
- [ ] **Step 7.1: Read the current file**
Use the Read tool on `src/components/sections/FinalCTA.astro`.
- [ ] **Step 7.2: Replace the file with the rebuilt version**
Write the full content below to `src/components/sections/FinalCTA.astro`:
```astro
---
import CTAButtons from '../CTAButtons.astro';
import TopographicBg from '../TopographicBg.astro';
---
<section class="relative overflow-hidden">
<TopographicBg opacity={0.18} lines={6} />
<div class="relative max-w-content mx-auto px-6 py-24 md:py-32 text-center">
<h2 class="text-display font-bold text-text mb-6">
Ship integrations. Sleep through the night.
</h2>
<p class="text-lg md:text-xl text-text-muted max-w-prose mx-auto mb-10">
14-day free trial. Your first Camel app, hosted, traced, and running in under ten minutes. No code changes.
</p>
<div class="flex justify-center">
<CTAButtons size="lg" showSecondary={false} />
</div>
</div>
</section>
```
- [ ] **Step 7.3: Verify the build**
Run: `npm run build`
Expected: build succeeds.
- [ ] **Step 7.4: Commit**
```bash
git add src/components/sections/FinalCTA.astro
git commit -m "refactor(final-cta): bookend the hero, drop camel pun
H2 now echoes the Hero (intentional bookend pattern). Sub line
loses the 'No camels harmed' aside. Single primary CTA — no
secondary.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 8: Refresh `PricingTeaser.astro` (rename tiers, 2 cards on homepage)
**Files:**
- Modify: `src/components/sections/PricingTeaser.astro`
**Spec reference:** §6.6. Rename to `Trial / Starter / Scale / Enterprise`, show only Trial + Starter on the homepage, replace the inline link with a "See all plans" line below.
- [ ] **Step 8.1: Read the current file**
Use the Read tool on `src/components/sections/PricingTeaser.astro`.
- [ ] **Step 8.2: Replace the file with the rebuilt version**
Write the full content below to `src/components/sections/PricingTeaser.astro`:
```astro
---
import { getAuthConfig } from '../../config/auth';
interface Tier {
name: string;
price: string;
sub: string;
href: string;
cta: string;
highlight?: boolean;
}
const auth = getAuthConfig();
const tiers: Tier[] = [
{
name: 'Trial',
price: 'Free',
sub: '14 days · 1 environment · 2 apps',
href: auth.signUpUrl,
cta: 'Start free trial',
},
{
name: 'Starter',
price: '20 € /mo',
sub: '2 environments · 10 apps · 7-day retention',
href: auth.signUpUrl,
cta: 'Start on Starter',
highlight: true,
},
];
---
<section class="border-b border-border">
<div class="max-w-content mx-auto px-6 py-20 md:py-24">
<div class="max-w-2xl mb-12">
<p class="text-accent font-mono text-xs tracking-[0.25em] uppercase mb-4">Pricing</p>
<h2 class="text-hero font-bold text-text mb-4">Start free. Grow when you need to.</h2>
<p class="text-text-muted text-lg">
No credit card. No sales call. Just a working trial in ten minutes.
</p>
</div>
<div class="grid md:grid-cols-2 gap-5 lg:items-stretch max-w-3xl">
{tiers.map((tier) => (
<div
class={`relative rounded-lg bg-bg-elevated p-6 flex flex-col transition-all duration-200 ease-out hover:-translate-y-0.5
${tier.highlight
? 'ring-2 ring-accent shadow-[0_20px_50px_-20px_rgba(240,180,41,0.35)] md:-translate-y-2 md:pt-8 md:pb-7'
: 'border border-border hover:border-accent/40 hover:shadow-[0_12px_32px_-12px_rgba(240,180,41,0.18)]'}`}
>
{tier.highlight && (
<span class="absolute -top-3 left-6 inline-flex items-center gap-1.5 rounded-full bg-accent text-bg px-3 py-0.5 text-[11px] font-bold tracking-wide font-mono">
<span aria-hidden="true">★</span>
MOST POPULAR
</span>
)}
<div class="mb-4">
<div class={`font-mono text-xs tracking-wider mb-2 ${tier.highlight ? 'text-accent' : 'text-text-muted'}`}>{tier.name.toUpperCase()}</div>
<div class="text-2xl font-bold text-text">{tier.price}</div>
</div>
<p class="text-text-muted text-sm leading-relaxed flex-grow mb-5">{tier.sub}</p>
<a
href={tier.href}
class={`inline-flex items-center justify-center rounded px-4 py-2 text-sm font-semibold transition-colors
${tier.highlight
? 'bg-accent text-bg hover:bg-accent-muted'
: 'border border-border-strong text-text hover:border-accent hover:text-accent'}`}
>
{tier.cta}
</a>
</div>
))}
</div>
<p class="mt-8 font-mono text-sm text-text-muted">
<a href="/pricing" class="text-cyan hover:text-accent transition-colors">
See all plans (Scale, Enterprise) →
</a>
</p>
</div>
</section>
```
- [ ] **Step 8.3: Verify the build**
Run: `npm run build`
Expected: build succeeds.
- [ ] **Step 8.4: Commit**
```bash
git add src/components/sections/PricingTeaser.astro
git commit -m "refactor(pricing-teaser): rename tiers, show only 2 cards
- Tier rename: MID → Starter (HIGH and Enterprise live on /pricing).
- Homepage shows Trial + Starter only. Starter retains the
★ MOST POPULAR ribbon.
- 'See full comparison →' inline link replaced by a clearer
'See all plans (Scale, Enterprise) →' line below the cards.
- Trial card price stays 'Free'; the tier name stays honest about
the 14-day cap.
The full /pricing.astro page still shows all four renamed tiers —
updated separately in the next commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 9: Refresh `pricing.astro` page tier names
**Files:**
- Modify: `src/pages/pricing.astro`
**Spec reference:** §6.6. Rename all four tiers and update the CTA labels.
- [ ] **Step 9.1: Read the current file**
Use the Read tool on `src/pages/pricing.astro`.
- [ ] **Step 9.2: Apply targeted edits**
Use the Edit tool to make these four replacements (in order):
**Edit 9.2.a — MID tier:**
`old_string`:
```
name: 'MID',
price: '20 €',
priceNote: 'per month',
envs: '2 environments',
apps: '10 apps',
retention: '7-day retention',
features: ['Everything in Trial', 'Data flow lineage', 'Cross-service correlation'],
href: auth.signUpUrl,
cta: 'Start on MID',
```
`new_string`:
```
name: 'Starter',
price: '20 €',
priceNote: 'per month',
envs: '2 environments',
apps: '10 apps',
retention: '7-day retention',
features: ['Everything in Trial', 'Data flow lineage', 'Cross-service correlation'],
href: auth.signUpUrl,
cta: 'Start on Starter',
```
**Edit 9.2.b — HIGH tier:**
`old_string`:
```
name: 'HIGH',
price: 'Contact',
priceNote: 'sales',
envs: 'Unlimited environments',
apps: '50 apps',
retention: '90-day retention',
features: ['Everything in MID', 'Live debugger', 'Exchange replay', 'Live tap'],
```
`new_string`:
```
name: 'Scale',
price: 'Contact',
priceNote: 'sales',
envs: 'Unlimited environments',
apps: '50 apps',
retention: '90-day retention',
features: ['Everything in Starter', 'Live debugger', 'Exchange replay', 'Live tap'],
```
**Edit 9.2.c — BUSINESS tier:**
`old_string`:
```
name: 'BUSINESS',
price: 'Contact',
priceNote: 'sales',
envs: 'Unlimited environments',
apps: 'Unlimited apps',
retention: '365-day retention',
features: ['Everything in HIGH', 'Priority support', 'SLA', 'Dedicated success contact'],
```
`new_string`:
```
name: 'Enterprise',
price: 'Contact',
priceNote: 'sales',
envs: 'Unlimited environments',
apps: 'Unlimited apps',
retention: '365-day retention',
features: ['Everything in Scale', 'Priority support', 'SLA', 'Dedicated success contact'],
```
**Edit 9.2.d — page meta description (if it references the old tier names):**
Check the BaseLayout `description` prop for any mention of "MID/HIGH/BUSINESS" — if present, replace with the new names. In the existing pricing.astro the description mentions "20 €/month or enterprise plans" which is still accurate; only update if the actual file references old tier labels.
- [ ] **Step 9.3: Verify the build**
Run: `npm run build`
Expected: build succeeds. `dist/pricing/index.html` should contain `Starter`, `Scale`, `Enterprise` (and no `MID`, `HIGH`, `BUSINESS`).
- [ ] **Step 9.4: Sanity check the rendered output**
Run: `grep -E "MID|HIGH|BUSINESS" dist/pricing/index.html` (use the Bash tool — this is a verification, not a forbidden grep).
Expected: empty output. If anything is matched, find and rename it.
- [ ] **Step 9.5: Commit**
```bash
git add src/pages/pricing.astro
git commit -m "refactor(pricing-page): rename tiers Trial/Starter/Scale/Enterprise
Customer-facing tier names replace the internally-coded
MID/HIGH/BUSINESS labels. Pricing structure (envs, apps,
retention, features) is unchanged. CTA labels updated to match.
The 'Everything in X' feature lines are updated to reference the
new neighbour names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 10: Wire new sections into `index.astro`
**Files:**
- Modify: `src/pages/index.astro`
**Spec reference:** §5 (final 7-section order). This is the task that makes the new structure live.
- [ ] **Step 10.1: Read the current file**
Use the Read tool on `src/pages/index.astro`.
- [ ] **Step 10.2: Replace the file with the rebuilt version**
Write the full content below to `src/pages/index.astro`:
```astro
---
import BaseLayout from '../layouts/BaseLayout.astro';
import SiteHeader from '../components/SiteHeader.astro';
import SiteFooter from '../components/SiteFooter.astro';
import Hero from '../components/sections/Hero.astro';
import SocialProofStrip from '../components/sections/SocialProofStrip.astro';
import ThreeAmWalkthrough from '../components/sections/ThreeAmWalkthrough.astro';
import HowItWorks from '../components/sections/HowItWorks.astro';
import WhyUs from '../components/sections/WhyUs.astro';
import PricingTeaser from '../components/sections/PricingTeaser.astro';
import FinalCTA from '../components/sections/FinalCTA.astro';
---
<BaseLayout
title="Cameleer — Ship Camel integrations. Sleep through the night."
description="The hosted runtime and observability platform for Apache Camel. Auto-traced, replay-ready, cross-service correlated — so the 3 AM page becomes a 30-second answer."
>
<SiteHeader />
<main>
<Hero />
<SocialProofStrip />
<ThreeAmWalkthrough />
<HowItWorks />
<WhyUs />
<PricingTeaser />
<FinalCTA />
</main>
<SiteFooter />
</BaseLayout>
```
- [ ] **Step 10.3: Verify the build**
Run: `npm run build`
Expected: build succeeds with no warnings about missing components or unresolved imports.
- [ ] **Step 10.4: Confirm the new section anchor renders**
Run: `grep -c 'id="walkthrough"' dist/index.html`
Expected: `1`. The hero's secondary CTA `#walkthrough` link will now resolve.
- [ ] **Step 10.5: Commit**
```bash
git add src/pages/index.astro
git commit -m "feat(homepage): wire SocialProofStrip + ThreeAmWalkthrough
Updates the homepage section order to the proof-first arc:
Hero → SocialProofStrip → ThreeAmWalkthrough → HowItWorks
→ WhyUs → PricingTeaser → FinalCTA
The retired DualValueProps and ProductShowcase imports are dropped
here; the unused .astro files themselves are deleted in Task 11.
Page <title> + <meta description> updated to lead with the new H1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 11: Delete retired components
**Files:**
- Delete: `src/components/sections/DualValueProps.astro`
- Delete: `src/components/sections/ProductShowcase.astro`
**Why now:** No consumers remain after Task 10. Removing them keeps the source tree honest.
- [ ] **Step 11.1: Confirm no imports remain**
Run: `grep -rn "DualValueProps\|ProductShowcase" src/` (Bash tool).
Expected: empty output. If anything matches, fix the consumer first.
- [ ] **Step 11.2: Delete both files**
Run: `rm "src/components/sections/DualValueProps.astro" "src/components/sections/ProductShowcase.astro"`
- [ ] **Step 11.3: Verify the build**
Run: `npm run build`
Expected: build succeeds. `dist/index.html` does not regress; the new walkthrough renders in their place.
- [ ] **Step 11.4: Commit**
```bash
git add -A src/components/sections/
git commit -m "chore(sections): delete retired DualValueProps + ProductShowcase
These two sections were collapsed into ThreeAmWalkthrough.astro
(Task 3). No remaining consumers — removed from the tree.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
```
---
## Task 12: Run full quality gates
**Files:** none modified.
**Why:** The relaunch is complete. Run every gate the project ships with and record the result. Any failure here is a blocker for merge.
- [ ] **Step 12.1: Run vitest**
Run: `npm run test`
Expected: all tests pass. The relaunch did not touch `middleware.ts`, `auth.ts`, or any tested file, so this should be green.
- [ ] **Step 12.2: Run a clean build**
Run: `npm run build`
Expected: `✔ Completed`, no warnings, `dist/` populated.
- [ ] **Step 12.3: Run html-validate**
Run: `npm run lint:html`
Expected: no errors. If errors appear, fix them and re-run from Step 12.2.
- [ ] **Step 12.4: Run linkinator**
Run: `npm run lint:links`
Expected: no broken links. The new `#walkthrough` anchor must resolve. If linkinator fails on the in-page anchor (rare — most configs accept fragments), check `linkinator.config.json` and add the fragment to the skip list only if necessary.
- [ ] **Step 12.5: Run Lighthouse CI**
Run: `npm run lh`
Expected: all 4 categories ≥ 0.95 (the project's existing CI threshold per README.md). If any score regresses below 0.95, investigate and fix before claiming done. Typical regressions to watch for:
- Performance: the new `<pre>` block in ThreeAmWalkthrough should not push LCP — but verify.
- Accessibility: pin labels (`aria-hidden="true"` on decorative pins) plus the `aria-describedby` linkage if any was added; also check tab order on the secondary anchor CTA.
- [ ] **Step 12.6: Final report — write the summary**
Compose a single-screen summary of what changed, where it landed, and any open items (PENDING gates: Founder name, nJAMS trademark). This goes in the final user-facing message, not into a file.
---
## Self-review checklist (run by author after writing the plan)
**Spec coverage:**
- §6.1 Hero rebuild → Task 4 ✓
- §6.2 SocialProofStrip → Task 2 ✓
- §6.3 ThreeAmWalkthrough → Task 3 ✓
- §6.4 HowItWorks slim → Task 5 ✓
- §6.5 WhyUs refresh → Task 6 ✓
- §6.6 PricingTeaser refresh → Task 8 ✓
- §6.6 /pricing tier rename → Task 9 ✓
- §6.7 FinalCTA reword → Task 7 ✓
- §7 Nav unchanged → no task (correct — nothing to do)
- §9 scroll-behavior CSS → Task 1 ✓
- §9 deletions → Task 11 ✓
- §12 Validation → Task 12 ✓
- §12 PENDING gates → surfaced as code comments in Task 2 ✓
**Placeholder scan:** No "TBD" / "TODO" / "implement later" markers in any task body. The `<!-- PENDING -->` markers in `SocialProofStrip.astro` are intentional code comments per spec §12 — they survive into the shipped code as deliberate publish gates.
**Type / name consistency:** `auth.salesEmail` is used in Task 2 and matches the actual export in `src/config/auth.ts`. `Lightbox` is imported in both Hero and ThreeAmWalkthrough with consistent props. CTAButtons props (`secondaryLabel`, `secondaryHref`, `showSecondary`) match the existing component API.
**Order safety:** Each task leaves the build green. Tasks 2-3 add components without consumers; Tasks 4-9 modify existing components in place; Task 10 swaps the imports atomically; Task 11 deletes only after no consumers remain.