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).
38 KiB
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 dev→ http://localhost:4321. Leave it running across tasks where possible. - Build check:
npm run buildafter 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
playwrightMCP 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 useis:inlineon a<script>. Never use inlineonclick/onhoverhandlers.
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."
Task 3: Replace the inline SVG in SiteHeader with the real logo
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 ~7–14):
<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>anddescriptionprops 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 Camel→Your 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
-javaagentreference. -
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
setIntervalis insideif (!reduced && lines.length > 1) { ... }— so whenreducedis 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
tilesarray
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
stepsarray 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 ~14–22):
<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 ~23–31):
<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 ~52–55):
<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:
- Run Apache Camel without running Apache Camel.
- Camel integrations, minus the baggage.
- Your camels, our caravan. You just ride.
- (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
previewmode
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.