Files
cameleer-website/docs/superpowers/plans/2026-04-24-cameleer-website-copy-refresh.md
hsiegeln 2526b1f0fc docs: implementation plan for copy + brand refresh
13 tasks, each self-contained with exact file paths, final copy,
verification steps, and a commit at the end. Covers: logo + favicon
import (tasks 1-3), SEO meta (task 4), Hero static + rotating H1
(tasks 5-6), all five section copy rewrites (tasks 7-11), OG image
redesign (task 12), end-to-end verification (task 13). CSP-safe
rotation via Astro <script> bundling (script-src 'self' respected).
2026-04-24 23:34:38 +02:00

38 KiB
Raw Blame History

Cameleer website copy + brand refresh — 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: Reposition the homepage from "observability tool" to "hosted Camel runtime with observability baked in." Refresh copy (3 rotating Hero headlines, two humor pops, plain-language tone), and replace the placeholder topographic-wave icon with the real camel product logo.

Architecture: Pure content + static asset refresh on an Astro 5 site. No new components, no new pages, no new deps. One small piece of client-side JS lives in the Hero (three-line rotation with reduced-motion guard and pause-on-interaction) — delivered via Astro's <script> block so it gets bundled and served same-origin (CSP is strict: script-src 'self' with no 'unsafe-inline'; inline <script> tags would be blocked).

Tech Stack: Astro 5, Tailwind CSS (design tokens already defined), TypeScript, Vitest for logic tests, html-validate + linkinator for build-output checks, Playwright MCP available for browser verification.

Reference spec: docs/superpowers/specs/2026-04-24-cameleer-website-copy-refresh-design.md


Ground rules

  • Dev server: npm run devhttp://localhost:4321. Leave it running across tasks where possible.
  • Build check: npm run build after any component edit. Treat warnings as errors in component files.
  • No placeholders: every copy string in this plan is the final copy. Do not paraphrase.
  • Verify visually: most tasks end with a Playwright navigate-and-screenshot check. The playwright MCP tools are available (mcp__playwright__browser_navigate, mcp__playwright__browser_take_screenshot).
  • Commit scope: each task ends in a single focused commit. Do not batch.
  • CSP: use Astro <script> blocks (default bundled mode). Never use is:inline on a <script>. Never use inline onclick/onhover handlers.

Task 1: Import the real Cameleer product logo + icon set

Files:

  • Create: public/cameleer-logo.svg
  • Create: public/cameleer-logo.png
  • Create: public/icons/cameleer-16.png
  • Create: public/icons/cameleer-32.png
  • Create: public/icons/cameleer-48.png
  • Create: public/icons/cameleer-180.png
  • Create: public/icons/cameleer-192.png
  • Create: public/icons/cameleer-512.png

Assets come from the sibling design-system repo: C:/Users/Hendrik/Documents/projects/design-system/assets/.

  • Step 1: Create the public/icons/ directory
mkdir -p C:/Users/Hendrik/Documents/projects/cameleer-website/public/icons
  • Step 2: Copy the SVG and PNG logo variants
cd C:/Users/Hendrik/Documents/projects/cameleer-website
cp ../design-system/assets/cameleer-logo.svg public/cameleer-logo.svg
cp ../design-system/assets/cameleer-logo.png public/cameleer-logo.png
cp ../design-system/assets/cameleer-16.png public/icons/cameleer-16.png
cp ../design-system/assets/cameleer-32.png public/icons/cameleer-32.png
cp ../design-system/assets/cameleer-48.png public/icons/cameleer-48.png
cp ../design-system/assets/cameleer-180.png public/icons/cameleer-180.png
cp ../design-system/assets/cameleer-192.png public/icons/cameleer-192.png
cp ../design-system/assets/cameleer-512.png public/icons/cameleer-512.png
  • Step 3: Verify files landed
cd C:/Users/Hendrik/Documents/projects/cameleer-website
ls -la public/cameleer-logo.svg public/cameleer-logo.png public/icons/

Expected: 8 files listed, non-zero sizes. cameleer-logo.svg is ~1.5 MB (ship as-is per spec §3.1).

  • Step 4: Commit
cd C:/Users/Hendrik/Documents/projects/cameleer-website
git add public/cameleer-logo.svg public/cameleer-logo.png public/icons/
git commit -m "feat(brand): import real cameleer product logo + favicon set

Camel + cameleer figure on compass rose, amber on transparent. Imported
from design-system/assets. Replaces the placeholder topographic-wave icon
across favicon chain, header, and OG assets (subsequent tasks)."

Task 2: Update BaseLayout favicon chain + delete placeholder

Files:

  • Modify: src/layouts/BaseLayout.astro — swap the single-favicon line for a proper chain

  • Delete: public/favicon.svg (placeholder 3-wavy-lines SVG)

  • Step 1: Replace the favicon <link> in BaseLayout

In src/layouts/BaseLayout.astro, find this line:

    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />

Replace with:

    <link rel="icon" type="image/svg+xml" href="/cameleer-logo.svg" />
    <link rel="icon" type="image/png" sizes="32x32" href="/icons/cameleer-32.png" />
    <link rel="apple-touch-icon" href="/icons/cameleer-180.png" />
  • Step 2: Delete the placeholder favicon
cd C:/Users/Hendrik/Documents/projects/cameleer-website
rm public/favicon.svg
  • Step 3: Build to confirm nothing references the deleted file
npm run build

Expected: build succeeds, no 404s on /favicon.svg in the output.

  • Step 4: Verify the favicon loads in the dev server

Start the dev server in the background if it isn't running:

npm run dev

Use Playwright MCP to verify:

mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_evaluate → document.querySelector('link[rel="icon"][type="image/svg+xml"]').href

Expected: ends in /cameleer-logo.svg — and a GET for that URL returns 200 (check the Network tab with mcp__playwright__browser_network_requests).

  • Step 5: Commit
git add src/layouts/BaseLayout.astro public/favicon.svg
git commit -m "feat(brand): wire favicon chain to real product logo

SVG primary + 32px PNG fallback + Apple touch icon. Removes the
placeholder 3-wavy-lines favicon."

Files:

  • Modify: src/components/SiteHeader.astro

  • Step 1: Replace the inline <svg> block with an <img> referencing the real logo

In src/components/SiteHeader.astro, find this block (lines ~714):

      <svg width="28" height="28" viewBox="0 0 32 32" aria-hidden="true">
        <rect width="32" height="32" rx="6" fill="#0c111a"/>
        <g fill="none" stroke="#f0b429" stroke-width="1.6" stroke-linecap="round">
          <path d="M4 10 Q10 6 16 12 T28 10"/>
          <path d="M4 16 Q10 12 16 18 T28 16"/>
          <path d="M4 22 Q10 18 16 24 T28 22"/>
        </g>
      </svg>

Replace with:

      <img
        src="/cameleer-logo.svg"
        width="32"
        height="32"
        alt=""
        decoding="async"
        class="shrink-0"
      />

Rationale: alt="" is correct — the adjacent <span>Cameleer</span> wordmark provides the accessible label, and the <a aria-label="Cameleer home"> wraps both. An alt on the image would cause a duplicate announcement.

  • Step 2: Verify in the dev server

With npm run dev running:

mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_take_screenshot → filename: hero-header.png

Expected: the header shows the amber camel-on-compass logo (32px) next to the "Cameleer" wordmark. No broken image icon.

  • Step 3: Commit
git add src/components/SiteHeader.astro
git commit -m "feat(brand): swap header icon for real Cameleer logo

Placeholder 3-wavy-lines SVG replaced with the product logo
(camel + cameleer figure + compass rose)."

Task 4: Update homepage title + meta description

Files:

  • Modify: src/pages/index.astro — the <title> and description props drive every <meta> in the head

  • Step 1: Replace the title and description props

In src/pages/index.astro, find:

<BaseLayout
  title="Cameleer — Zero-code observability for Apache Camel"
  description="See every route. Reach into every flow. Zero-code tracing, processor-level detail, and live control for Apache Camel — from a single -javaagent flag."
>

Replace with:

<BaseLayout
  title="Cameleer — Run Apache Camel without running Apache Camel"
  description="The hosted home for your Camel integrations — with deep tracing, replay, and live control built in. Because you chose Camel to stay free, not to stay up all night."
>
  • Step 2: Build and verify the rendered HTML
npm run build
grep -o '<title>[^<]*</title>\|<meta name="description"[^>]*>' dist/index.html

Expected:

<title>Cameleer — Run Apache Camel without running Apache Camel</title>
<meta name="description" content="The hosted home for your Camel integrations — with deep tracing, replay, and live control built in. Because you chose Camel to stay free, not to stay up all night.">
  • Step 3: Commit
git add src/pages/index.astro
git commit -m "feat(copy): update homepage title + meta description

Thesis: 'Run Apache Camel without running Apache Camel.' Reframes the
page from observability tool to hosted runtime platform for Camel."

Task 5: Hero — static content rewrite (no rotation yet)

Files:

  • Modify: src/components/sections/Hero.astro

This task rewrites the Hero markup to the new static content. Rotation is added in Task 6. Keeping the two changes separate makes each commit reviewable and keeps a bisection target if rotation regresses something.

  • Step 1: Rewrite the Hero component

Replace the entire contents of src/components/sections/Hero.astro with:

---
import CTAButtons from '../CTAButtons.astro';
import RouteDiagram from '../RouteDiagram.astro';
import TopographicBg from '../TopographicBg.astro';
---
<section class="relative overflow-hidden border-b border-border">
  <TopographicBg opacity={0.14} lines={10} />
  <div class="relative max-w-content mx-auto px-6 pt-20 pb-24 md:pt-28 md:pb-32">
    <div class="max-w-3xl">
      <div class="flex items-center gap-3 mb-6">
        <img
          src="/cameleer-logo.svg"
          width="48"
          height="48"
          alt=""
          decoding="async"
          class="shrink-0"
        />
        <p class="text-accent font-mono text-xs tracking-[0.25em] uppercase">
          Your camels called. They want a GPS.
        </p>
      </div>
      <h1 class="text-display font-bold text-text mb-6">
        Run Apache Camel without running Apache Camel.
      </h1>
      <p class="text-lg md:text-xl text-text-muted max-w-prose leading-relaxed mb-10">
        The hosted home for your Camel integrations — with deep tracing, replay, and live control built in. Because you chose Camel to stay free, not to stay up all night.
      </p>
      <CTAButtons size="lg" />
    </div>
    <div class="mt-16 md:mt-20">
      <RouteDiagram />
    </div>
  </div>
</section>

Changes vs current:

  • Added 48px brand mark next to the kicker (per spec §3.4).

  • Kicker text: Observability · Apache CamelYour camels called. They want a GPS.

  • H1: See every route. / Reach into every flow.Run Apache Camel without running Apache Camel.

  • Subline rewritten — no more -javaagent reference.

  • Step 2: Build to confirm it compiles

npm run build

Expected: success, no warnings about missing props or broken imports.

  • Step 3: Visual check in dev server

With npm run dev running:

mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_take_screenshot → filename: hero-task5.png

Expected: amber camel mark (48px) next to the uppercase "YOUR CAMELS CALLED. THEY WANT A GPS." kicker. Headline reads "Run Apache Camel without running Apache Camel." Subline is the new plain-language version.

  • Step 4: Commit
git add src/components/sections/Hero.astro
git commit -m "feat(copy): Hero static rewrite — new kicker, thesis H1, subline

Drops -javaagent from the hero. Adds the 48px product mark next to the
kicker. Rotation is added in the next commit."

Task 6: Hero — three rotating H1 lines with fade, pause, and reduced-motion guard

Files:

  • Modify: src/components/sections/Hero.astro — add two extra <span>s inside the H1, add <style> and <script> blocks

This task adds the rotation. All three lines render in the DOM. The visible one is controlled via a data-active attribute; CSS drives the fade. The script cycles data-active every 10 seconds, pauses on hover/focus, and does nothing if prefers-reduced-motion: reduce.

aria-live="off" on the rotation wrapper prevents assistive tech from announcing every swap. aria-hidden="true" on the two inactive lines avoids duplicate heading announcements.

  • Step 1: Replace the H1 + add style + script blocks

In src/components/sections/Hero.astro, replace the current H1:

      <h1 class="text-display font-bold text-text mb-6">
        Run Apache Camel without running Apache Camel.
      </h1>

With:

      <h1
        class="text-display font-bold text-text mb-6 hero-rotator"
        aria-live="off"
        data-hero-rotator
      >
        <span class="hero-line" data-active aria-hidden="false">Run Apache Camel without running Apache Camel.</span>
        <span class="hero-line" aria-hidden="true">Camel integrations, minus the baggage.</span>
        <span class="hero-line" aria-hidden="true">Your camels, our caravan. You just ride.</span>
      </h1>

Then at the bottom of the file (after the closing </section>), add:

<style>
  .hero-rotator {
    position: relative;
    display: block;
    /* Reserve height for the tallest line so no layout shift on swap.
       Two lines at current H1 size handles all three on most viewports. */
    min-height: 2.2em;
  }
  .hero-line {
    display: block;
    opacity: 0;
    transition: opacity 700ms ease-in-out;
    /* Stack all lines on top of each other — only [data-active] is visible. */
    position: absolute;
    inset: 0;
  }
  .hero-line[data-active] {
    opacity: 1;
    position: relative;
  }
  @media (prefers-reduced-motion: reduce) {
    .hero-line {
      transition: none;
    }
  }
</style>

<script>
  // Hero rotating headline. Bundled by Astro (CSP: script-src 'self').
  const rotator = document.querySelector<HTMLElement>('[data-hero-rotator]');
  if (rotator) {
    const lines = Array.from(rotator.querySelectorAll<HTMLElement>('.hero-line'));
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (!reduced && lines.length > 1) {
      let index = 0;
      let paused = false;
      const pause = () => { paused = true; };
      const resume = () => { paused = false; };
      rotator.addEventListener('mouseenter', pause);
      rotator.addEventListener('mouseleave', resume);
      rotator.addEventListener('focusin', pause);
      rotator.addEventListener('focusout', resume);
      setInterval(() => {
        if (paused) return;
        lines[index].removeAttribute('data-active');
        lines[index].setAttribute('aria-hidden', 'true');
        index = (index + 1) % lines.length;
        lines[index].setAttribute('data-active', '');
        lines[index].setAttribute('aria-hidden', 'false');
      }, 10000);
    }
  }
</script>
  • Step 2: Build to confirm the script is bundled (not inlined)
npm run build

Then:

grep -c 'hero-rotator' dist/index.html
ls dist/_astro/*.js 2>&1 | head

Expected: the HTML contains the data-hero-rotator attribute. A hoisted JS file appears under dist/_astro/. The HTML should NOT contain an inline <script> block with the rotator code (Astro hoists <script> tags by default).

  • Step 3: Verify CSP compliance in the browser

With npm run dev running:

mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_console_messages

Expected: no Content-Security-Policy violation messages. (Note: CSP headers only apply to preview/prod; dev server doesn't enforce them — but the inline-vs-bundled distinction is a build-time property, so if Step 2 confirmed the script was hoisted, CSP will pass in prod.)

  • Step 4: Verify the rotation behavior visually
mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_evaluate →
  Array.from(document.querySelectorAll('.hero-line')).map(l => ({
    text: l.textContent?.trim(),
    active: l.hasAttribute('data-active'),
    ariaHidden: l.getAttribute('aria-hidden'),
  }))

Expected at page load:

[
  { text: 'Run Apache Camel without running Apache Camel.', active: true, ariaHidden: 'false' },
  { text: 'Camel integrations, minus the baggage.', active: false, ariaHidden: 'true' },
  { text: 'Your camels, our caravan. You just ride.', active: false, ariaHidden: 'true' },
]

Wait 11 seconds and re-run the evaluate. Expected: second entry now has active: true, ariaHidden: 'false'; first and third are inactive.

  • Step 5: Verify reduced-motion guard at the code level

The Playwright MCP in this environment does not expose a media-query emulation tool, so the runtime check is split into two parts:

(a) Code inspection — re-read the <script> block and confirm:

  • const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  • The setInterval is inside if (!reduced && lines.length > 1) { ... } — so when reduced is true, the interval is never registered.
  • The CSS @media (prefers-reduced-motion: reduce) .hero-line { transition: none; } — so even if a swap fired, it would be instant. Belt and suspenders.

(b) Optional manual verification — if you want a live check, toggle reduced-motion at the OS level:

  • Windows: Settings → Accessibility → Visual effects → Animation effects: Off
  • Then reload the page and wait ~15 seconds. First line should remain active.

If (a) matches the code you just wrote, (b) is optional — the guard is structurally correct and the CSS fallback makes it defensive.

  • Step 6: Commit
git add src/components/sections/Hero.astro
git commit -m "feat(hero): rotate three positioning lines on a 10s cycle

All three lines render in the DOM; CSS drives the fade via data-active.
Reduced-motion users see the first line only (no interval, no fade).
Rotation pauses on hover and keyboard focus. aria-live=off on the
rotator so AT does not announce every swap; aria-hidden flips per-swap
to avoid duplicate heading announcements."

Task 7: DualValueProps — three outcome-led tiles

Files:

  • Modify: src/components/sections/DualValueProps.astro

Rewrite the three tile headlines and bodies. Outcome-led, no -javaagent, no "nanosecond", no "45+ EIP". Keep the existing card styling.

  • Step 1: Rewrite the tiles array

In src/components/sections/DualValueProps.astro, replace the current tiles definition:

const tiles: Tile[] = [
  {
    outcome: 'Cut debugging time in half.',
    capability:
      'Every processor on every route, timed to the nanosecond. Choice branches, splits, multicasts, and error handlers preserved as a proper execution tree — not a pile of log lines.',
  },
  {
    outcome: 'Ship integrations with confidence.',
    capability:
      'Capture real payloads and replay them on demand. Deep-trace a specific correlation ID across services. Push trace settings to a running agent without a redeploy.',
  },
  {
    outcome: 'Keep what you have built.',
    capability:
      'One `-javaagent` flag. No code changes, no SDK, no framework lock-in. Native understanding of 45+ EIP node types across Apache Camel 4.x.',
  },
];

With:

const tiles: Tile[] = [
  {
    outcome: 'Ship integrations, then sleep.',
    capability:
      'Every route, every processor, every exchange — traced automatically. When something breaks at 3 AM, the answer is already waiting for you. So you do not have to be.',
  },
  {
    outcome: 'Debug in daylight.',
    capability:
      'Replay the exact exchange that failed. Follow a single request across services. See payloads before and after each processor. The pieces your ops team needs at 3 AM, captured already — so 3 AM stays quiet.',
  },
  {
    outcome: 'Keep what you built. Keep what you chose.',
    capability:
      'You picked Apache Camel on purpose — open, portable, yours. Cameleer runs and understands your Camel apps as they are. No code changes, no SDK, no rewrite, no lock-in.',
  },
];

Note: the template still renders tile.capability through a backtick-to-<code> replace. None of the new bodies use backticks, so the replace is a no-op. Keep the template untouched.

  • Step 2: Build
npm run build

Expected: success.

  • Step 3: Visual check
mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_take_screenshot → filename: dualvalue.png

Expected: three tiles with the new outcome-led headlines and softened bodies. No backtick-code fragments visible. No mentions of "nanosecond", "-javaagent", "45+", or "EIP".

  • Step 4: Grep-confirm the removals
grep -E 'nanosecond|javaagent|45\+|EIP node' dist/index.html || echo "CLEAN"

Expected: CLEAN.

  • Step 5: Commit
git add src/components/sections/DualValueProps.astro
git commit -m "feat(copy): DualValueProps — outcome-led, plain language

Three tiles: ship-then-sleep, debug-in-daylight, keep-what-you-chose.
Drops -javaagent, nanosecond, and 45+ EIP node types from the landing
copy — those belong in docs."

Task 8: HowItWorks — three softer steps, drop the bash snippet

Files:

  • Modify: src/components/sections/HowItWorks.astro

  • Step 1: Rewrite the steps array and the section subtitle

In src/components/sections/HowItWorks.astro, replace the steps constant and the subtitle paragraph.

The steps constant:

const steps: Step[] = [
  {
    n: '01',
    title: 'Add the agent',
    body: 'Drop the Cameleer agent JAR alongside your Camel app and start it with a single flag. That is the entire installation.',
    code: 'java \\\n  -javaagent:cameleer-agent.jar \\\n  -jar your-camel-app.jar',
  },
  {
    n: '02',
    title: 'Launch your app',
    body: 'Every route, processor, exchange, and route graph is discovered and reported automatically. Configurable redaction keeps sensitive fields out of the trace.',
  },
  {
    n: '03',
    title: 'See it in Mission Control',
    body: 'Browse executions, tap live traffic, replay failed exchanges, and follow flows across services. Nothing to instrument, nothing to maintain.',
  },
];

Becomes:

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. No SDK. Nothing to rewrite.',
  },
  {
    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. Nothing to instrument. Nothing to maintain.',
  },
];

The subtitle:

      <p class="text-text-muted text-lg">Three steps. No code changes. Works across Camel 4.x.</p>

Becomes:

      <p class="text-text-muted text-lg">Three steps. No code changes. Nothing to maintain.</p>

The code? field on Step 1 is gone; the {step.code && (...)} conditional in the template renders nothing for steps without code. No template change needed.

  • Step 2: Build
npm run build
  • Step 3: Confirm the bash snippet is gone
grep -E 'javaagent|cameleer-agent\.jar' dist/index.html || echo "CLEAN"

Expected: CLEAN.

  • Step 4: Visual check
mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_take_screenshot → filename: howitworks.png

Expected: three numbered cards with the new titles and bodies. No <pre> block in any card.

  • Step 5: Commit
git add src/components/sections/HowItWorks.astro
git commit -m "feat(copy): HowItWorks — plain-language steps, bash snippet gone

Step 1 no longer shows java -javaagent:... on the marketing page; that
detail belongs in docs/install. Subtitle tightened to 'Nothing to
maintain.'"

Task 9: WhyUs — softer, warmer bodies with 3-AM framing

Files:

  • Modify: src/components/sections/WhyUs.astro

  • Step 1: Replace both tile bodies and the second tile's headline

Find the first tile (lines ~1422):

      <div class="rounded-lg border border-border bg-bg-elevated p-8">
        <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">
          Our Java agent speaks 45+ Apache Camel EIP node types natively — choices, splits, multicasts, doTry, error handlers, dynamic endpoints, thread boundaries in async routes. It extracts your route topology as a first-class graph, not a pile of metrics.
        </p>
        <p class="text-text-muted leading-relaxed">
          A bidirectional protocol lets the server push deep-trace requests, per-route recording toggles, and signed config changes back to running agents — turning passive observability into active control. Not something you build in a weekend.
        </p>
      </div>

Replace with:

      <div class="rounded-lg border border-border bg-bg-elevated p-8">
        <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 "why did this exchange fail?", 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>

Find the second tile (lines ~2331):

      <div class="rounded-lg border border-border bg-bg-elevated p-8">
        <h3 class="text-xl font-bold text-text mb-4">Built by people who have shipped this class of product before.</h3>
        <p class="text-text-muted leading-relaxed mb-4">
          The Cameleer team spent years building and supporting integration monitoring for banks, insurers, and logistics operators. We know what integration teams actually need at 3 AM — and what they never use.
        </p>
        <p class="text-text-muted leading-relaxed">
          Cameleer is what we would build today, purpose-built for Apache Camel — no legacy, no retrofit, no assumptions about a generic middleware platform.
        </p>
      </div>

Replace with:

      <div class="rounded-lg border border-border bg-bg-elevated p-8">
        <h3 class="text-xl font-bold text-text mb-4">Built by people who know what 3 AM looks like.</h3>
        <p class="text-text-muted leading-relaxed mb-4">
          We spent years building integration monitoring for banks, insurers, and logistics operators — the kind of shops where a stuck exchange at 3 AM means someone's phone is ringing. We know what integration teams actually need then, and what they never use.
        </p>
        <p class="text-text-muted leading-relaxed">
          Cameleer is what we would build today, purpose-built for Apache Camel. No legacy, no retrofit, no assumptions about a generic middleware platform.
        </p>
      </div>

Keep the existing comment block at the top of the file (trademark review note).

  • Step 2: Build
npm run build
  • Step 3: Confirm the removals
grep -E '45\+|bidirectional protocol|signed config changes|deep-trace requests' dist/index.html || echo "CLEAN"

Expected: CLEAN.

  • Step 4: Commit
git add src/components/sections/WhyUs.astro
git commit -m "feat(copy): WhyUs — warmer language, 3-AM framing

Tile 2 headline now 'Built by people who know what 3 AM looks like.'
Bodies soften 'bidirectional protocol / signed config' into plain-value
language. nJAMS-legacy trademark review note preserved."

Task 10: PricingTeaser — subline tweak

Files:

  • Modify: src/components/sections/PricingTeaser.astro

  • Step 1: Replace the subline paragraph

Find (lines ~5255):

      <p class="text-text-muted text-lg">
        No credit card for the trial.
        <a href="/pricing" class="text-accent hover:underline">See full comparison →</a>
      </p>

Replace with:

      <p class="text-text-muted text-lg">
        No credit card. No sales call. Just a working trial in ten minutes.
        <a href="/pricing" class="text-accent hover:underline">See full comparison →</a>
      </p>

Tier cards and prices unchanged.

  • Step 2: Build
npm run build
  • Step 3: Commit
git add src/components/sections/PricingTeaser.astro
git commit -m "feat(copy): PricingTeaser — 'no credit card, no sales call'

Subline slightly warmer and more concrete ('a working trial in ten
minutes'). Tier cards untouched."

Task 11: FinalCTA — second humor pop

Files:

  • Modify: src/components/sections/FinalCTA.astro

  • Step 1: Replace the headline and subline

Find:

    <h2 class="text-display font-bold text-text mb-6">
      Start seeing your routes.
    </h2>
    <p class="text-lg md:text-xl text-text-muted max-w-prose mx-auto mb-10">
      14-day free trial. Your first app, instrumented and live in under 10 minutes.
    </p>

Replace with:

    <h2 class="text-display font-bold text-text mb-6">
      Your camels called. Time to ride.
    </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. No camels harmed.
    </p>

CTAButtons block unchanged.

  • Step 2: Build
npm run build
  • Step 3: Visual check
mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_take_screenshot → filename: finalcta.png

Expected: large centered "Your camels called. Time to ride." over the topographic background, subline ends with "No camels harmed.", CTA buttons still work.

  • Step 4: Commit
git add src/components/sections/FinalCTA.astro
git commit -m "feat(copy): FinalCTA — 'Your camels called. Time to ride.'

Second humor pop (pairing with the Hero kicker). Subline adds the
tasteful-absurd 'No camels harmed.' closer."

Task 12: Redesign OG image around the new thesis

Files:

  • Modify: public/og-image.svg — full rewrite

Target: 1200×630, solid dark background (#060a13), amber accents (#f0b429), centered layout with the real logo + the thesis headline + a short subhead.

  • Step 1: Read the current OG image to understand conventions
cat C:/Users/Hendrik/Documents/projects/cameleer-website/public/og-image.svg

Note the existing dimensions, font references, and colors, so the replacement keeps the same structural shape.

  • Step 2: Replace the file with the new design

Write the following to public/og-image.svg:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" width="1200" height="630">
  <rect width="1200" height="630" fill="#060a13"/>
  <!-- Subtle topographic lines -->
  <g fill="none" stroke="#f0b429" stroke-width="1.2" stroke-linecap="round" opacity="0.10">
    <path d="M0 140 Q200 80 400 160 T800 140 T1200 160"/>
    <path d="M0 250 Q200 190 400 270 T800 250 T1200 270"/>
    <path d="M0 360 Q200 300 400 380 T800 360 T1200 380"/>
    <path d="M0 470 Q200 410 400 490 T800 470 T1200 490"/>
  </g>
  <!-- Product mark (fallback: amber circle w/ wordmark — real PNG logo embedded would exceed OG size budget) -->
  <g transform="translate(90, 110)">
    <circle cx="60" cy="60" r="58" fill="none" stroke="#f0b429" stroke-width="2"/>
    <text x="60" y="74" text-anchor="middle" font-family="DM Sans, system-ui, sans-serif" font-size="40" font-weight="700" fill="#f0b429">C</text>
  </g>
  <text x="220" y="190" font-family="DM Sans, system-ui, sans-serif" font-size="28" font-weight="600" fill="#f0b429" letter-spacing="3">CAMELEER</text>
  <text x="90" y="340" font-family="DM Sans, system-ui, sans-serif" font-size="64" font-weight="700" fill="#f4f5f7">Run Apache Camel</text>
  <text x="90" y="420" font-family="DM Sans, system-ui, sans-serif" font-size="64" font-weight="700" fill="#f4f5f7">without running Apache Camel.</text>
  <text x="90" y="500" font-family="DM Sans, system-ui, sans-serif" font-size="28" font-weight="400" fill="#a0a8b8">The hosted home for your Camel integrations.</text>
  <text x="90" y="540" font-family="DM Sans, system-ui, sans-serif" font-size="28" font-weight="400" fill="#a0a8b8">Deep tracing, replay, and live control — built in.</text>
</svg>

Rationale for the "C" fallback mark: the real product PNG logo at OG resolution would bloat the SVG past reasonable social-card budgets, and embedding a raster inside SVG is awkward. The amber circle-C on topographic lines reads correctly at the common 600×315 OG thumbnail render.

  • Step 3: Verify the SVG renders

Open the file in a browser or image viewer to confirm it renders at 1200×630 and the headline doesn't overflow.

mcp__playwright__browser_navigate → http://localhost:4321/og-image.svg
mcp__playwright__browser_take_screenshot → filename: og-image.png

Expected: centered dark card, amber topographic lines, amber circle "C" mark top-left, "Run Apache Camel / without running Apache Camel." as the main text, softened subhead below.

  • Step 4: Commit
git add public/og-image.svg
git commit -m "feat(brand): redesign OG image around new thesis

1200x630, solid #060a13 ground, amber topographic lines, circle-C mark,
headline 'Run Apache Camel without running Apache Camel.' plus short
subhead. The full camel-compass product logo is not embedded — raster
inside SVG at OG size would bloat the asset. Circle-C wordmark reads
cleanly at the 600x315 thumbnail render."

Task 13: End-to-end verification

Files: none modified; verification-only.

  • Step 1: Clean build + run all static checks
cd C:/Users/Hendrik/Documents/projects/cameleer-website
rm -rf dist
npm run build
npm run test
npm run lint:html
npm run lint:links

Expected: all green. lint:html checks the built HTML against .htmlvalidate.json. lint:links walks internal links in the built output.

  • Step 2: Full-page visual capture in the dev server
npm run dev
mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_resize → width: 1440, height: 900
mcp__playwright__browser_take_screenshot → filename: homepage-desktop.png, fullPage: true
mcp__playwright__browser_resize → width: 375, height: 812
mcp__playwright__browser_take_screenshot → filename: homepage-mobile.png, fullPage: true

Visual review checklist — walk through each screenshot and confirm:

  • Header: amber camel-on-compass logo + "Cameleer" wordmark, nav link "Pricing", CTA buttons on the right.

  • Hero: 48px brand mark next to the "YOUR CAMELS CALLED. THEY WANT A GPS." kicker. Headline reads the current rotation line (one of the three). Subline starts with "The hosted home for your Camel integrations".

  • DualValueProps: three tiles with the new headlines ("Ship integrations, then sleep.", "Debug in daylight.", "Keep what you built. Keep what you chose.").

  • HowItWorks: three cards with "Point us at your Camel app", "We take it from there", "Watch it run". No <pre> bash snippet anywhere.

  • WhyUs: tile 2 headline reads "Built by people who know what 3 AM looks like."

  • PricingTeaser: subline reads "No credit card. No sales call. Just a working trial in ten minutes."

  • FinalCTA: "Your camels called. Time to ride." + subline ending in "No camels harmed."

  • Step 3: Observe rotation live

With the browser still open, wait ~25 seconds on the homepage and watch the H1 cycle. Expected order:

  1. Run Apache Camel without running Apache Camel.
  2. Camel integrations, minus the baggage.
  3. Your camels, our caravan. You just ride.
  4. (wraps back to #1)
  • Step 4: Confirm no forbidden terms appear in the built HTML
cd C:/Users/Hendrik/Documents/projects/cameleer-website
grep -i -E 'javaagent|bytebuddy|nanosecond|45\+ EIP|\-jar your-camel-app' dist/index.html || echo "CLEAN"

Expected: CLEAN. If anything shows up, the corresponding earlier task regressed — re-open that task's step that removed the term.

  • Step 5: Confirm the real logo assets are actually reachable
cd C:/Users/Hendrik/Documents/projects/cameleer-website
for path in /cameleer-logo.svg /icons/cameleer-32.png /icons/cameleer-180.png; do
  curl -sI "http://localhost:4321$path" | head -1
done

Expected: each line begins with HTTP/1.1 200.

  • Step 6: Confirm no console errors or CSP violations in preview mode
npm run preview

Then:

mcp__playwright__browser_navigate → http://localhost:4321
mcp__playwright__browser_console_messages

Expected: no messages with level error. preview mode emits the real CSP headers, so this is the definitive CSP check.

  • Step 7: No commit

This is verification only. If any step fails, it points to a regression in an earlier task — fix it there with an amended commit or a follow-up fix commit in the relevant task's scope, not as a general cleanup.


Spec coverage verification (self-review)

Spec section Covered by task
§2.1 new thesis in copy Task 4 (title), Task 5 (Hero H1 default), Task 6 (rotation)
§2.2 three rotating lines + behavior + accessibility Task 6
§2.3 forbidden terms Tasks 4, 5, 7, 8, 9 — each task removes specific terms; Task 13 Step 4 greps the final HTML
§3.1 import asset list Task 1
§3.2 header icon swap Task 3
§3.3 favicon chain + delete placeholder Task 2
§3.4 Hero brand mark (48px next to kicker) Task 5
§3.5 OG image redesign Task 12
§4.1 Hero copy (kicker, H1, subline, remove -javaagent) Tasks 5 + 6
§4.2 DualValueProps rewrite Task 7
§4.3 HowItWorks rewrite + drop bash snippet Task 8
§4.4 WhyUs softening + tile 2 headline Task 9
§4.5 PricingTeaser subline tweak Task 10
§4.6 FinalCTA humor pop Task 11

All spec sections are covered by at least one task.