Rework landing page: copy, real tool screenshots, design system alignment#38
Conversation
Lead hero copy with the Seller Central access gap instead of a generic skills pitch, and add a section teasing the Amazon Ads Console simulator and Interview Lab as enrollee-exclusive tools (coming soon, not yet wired into amph-v2). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q2obMCR2P3RHTZMqph1QL1
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe home page adds revised hero messaging, pain-point content, simulator cards, enrollee-only practice offerings, and scroll-triggered reveals. Supporting CSS adds responsive layouts, staggered animations, CTA styling, and badge alignment. ChangesHome simulator landing experience
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant HomePage
participant RevealSection
participant IntersectionObserver
participant HomeStyles
Browser->>HomePage: render hero and content sections
HomePage->>RevealSection: render pain, simulator, access, pricing, and CTA sections
RevealSection->>IntersectionObserver: observe section
IntersectionObserver->>RevealSection: report viewport intersection
RevealSection->>HomeStyles: add is-visible class
HomeStyles->>Browser: reveal sections and stagger content
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/page.tsx`:
- Around line 17-19: Update the hero copy in the page component to replace “a
client hands them the login” with wording that describes a client granting
authorized access, and expand “VAs” to “virtual assistants (VAs)” on first use.
Keep the language direct and plain-spoken for the Filipino VA audience while
preserving the surrounding message.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 5cc17047-ee65-4807-b70a-04ed2b36952c
📒 Files selected for processing (2)
src/app/home.module.csssrc/app/page.tsx
| Most VAs don't touch a real Amazon account until a client hands them the | ||
| login. {BRAND_NAME} skips that: five practice tools built on real Amazon Ads | ||
| Console mechanics, so you already know where everything is before that day comes. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not normalize password sharing in the hero copy.
“Client hands them the login” presents credential sharing as the normal access path. Use wording such as “a client grants them authorized access,” and expand VAs to “virtual assistants (VAs)” on first use.
As per coding guidelines, **/*.{md,mdx,ts,tsx,js,jsx} requires direct, plain-spoken language for the Filipino VA audience and defined jargon.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/page.tsx` around lines 17 - 19, Update the hero copy in the page
component to replace “a client hands them the login” with wording that describes
a client granting authorized access, and expand “VAs” to “virtual assistants
(VAs)” on first use. Keep the language direct and plain-spoken for the Filipino
VA audience while preserving the surrounding message.
Source: Coding guidelines
…ording Headline now names the actual struggle (theory without a place to practice it) instead of a generic "three courses" framing. Also corrects copy that miscounted the offering as three courses — it's one course sold in three tiers.
…case Hero leads with "Learn Amazon PPC the right way" / "We turn the theoretical into the practical." Replaces the old generic "What you learn" list with a pain-points section naming the actual struggle (no Seller Central access, freezing on real decisions, never getting to make mistakes that teach) and a five-card simulator showcase pulling real names/descriptions from the tools catalog, closing on the practice-to-workplace payoff.
Each simulator card on the landing page now shows an actual screenshot of that tool in use, captured from a live scenario run (Bamboo Cutting Board fixture) rather than a description-only card. Along the way, found and fixed a real product bug: Badge stretched to full card width instead of staying a pill whenever it was a direct child of CardHeader (a column flexbox with default align-items: stretch) — visible on all five tool runner pages as an oversized colored banner instead of a small label. Added align-self: flex-start to the shared Badge component so this can't regress elsewhere. Screenshots were retaken after the fix.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/page.tsx (1)
189-191: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRemove the prohibited AI interview feature.
“AI mock interviews” directly conflicts with the product restriction. Remove this offering or replace it with a non-AI practice format.
As per coding guidelines, “Do not add OpenAI, Anthropic, LangChain, LLM APIs, mentor chat, or AI mistake-analysis features.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/page.tsx` around lines 189 - 191, Update the marketing copy in the page content to remove the prohibited “AI mock interviews” offering, replacing it with a non-AI practice format or omitting the offering while preserving the surrounding resume review and cover letter messaging.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/page.tsx`:
- Around line 112-119: Update the painList content in the page component to
define ACoS, ROAS, and CPC at their first use, using their full terms and
direct, plain-spoken wording for Filipino virtual assistants while preserving
the surrounding pain-point message.
- Around line 16-57: Add focused test coverage for the homepage simulator cards
defined by SIMULATORS in the homepage component. Verify the expected simulator
metadata and that each configured simulator card is rendered, rather than
relying only on the existing smoke test in critical-path.spec.ts.
---
Outside diff comments:
In `@src/app/page.tsx`:
- Around line 189-191: Update the marketing copy in the page content to remove
the prohibited “AI mock interviews” offering, replacing it with a non-AI
practice format or omitting the offering while preserving the surrounding resume
review and cover letter messaging.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 2db199c5-f99d-498b-adad-56a17a8616db
⛔ Files ignored due to path filters (5)
public/images/tools/tool-bid-elevator.jpgis excluded by!**/*.jpgpublic/images/tools/tool-campaign-builder.jpgis excluded by!**/*.jpgpublic/images/tools/tool-keyword-research.jpgis excluded by!**/*.jpgpublic/images/tools/tool-listing-audit.jpgis excluded by!**/*.jpgpublic/images/tools/tool-str-triage.jpgis excluded by!**/*.jpg
📒 Files selected for processing (3)
src/app/home.module.csssrc/app/page.tsxsrc/components/ui/Badge.module.css
| const SIMULATORS: SimMeta[] = [ | ||
| { | ||
| id: 'campaign-builder', | ||
| name: 'Campaign Builder', | ||
| description: | ||
| 'Build Sponsored Products, Sponsored Brands, Sponsored Display, and Sponsored TV campaigns. Practice the full Amazon Ads Console campaign wizard, start to finish.', | ||
| icon: 'Rocket', | ||
| screenshot: '/images/tools/tool-campaign-builder.jpg', | ||
| }, | ||
| { | ||
| id: 'bid-elevator', | ||
| name: 'Bid Elevator', | ||
| description: | ||
| 'Adjust keyword bids against real performance data. Cut waste, raise your converters, defend ACoS at target.', | ||
| icon: 'ChartLine', | ||
| screenshot: '/images/tools/tool-bid-elevator.jpg', | ||
| }, | ||
| { | ||
| id: 'str-triage', | ||
| name: 'Search Term Triage', | ||
| description: | ||
| 'Keep, pause, negate, or re-bid search terms. Practice the weekly triage workflow every PPC specialist runs.', | ||
| icon: 'List', | ||
| screenshot: '/images/tools/tool-str-triage.jpg', | ||
| }, | ||
| { | ||
| id: 'listing-audit', | ||
| name: 'Listing Audit', | ||
| description: | ||
| "Score a product listing on title, bullets, images, and A+ content. Find what's actually hurting conversion.", | ||
| icon: 'BookOpen', | ||
| screenshot: '/images/tools/tool-listing-audit.jpg', | ||
| }, | ||
| { | ||
| id: 'keyword-research', | ||
| name: 'Keyword Research', | ||
| description: | ||
| 'Categorize keywords as primary, secondary, or negative. Build the keyword list that drives every Sponsored Products campaign.', | ||
| icon: 'MagnifyingGlass', | ||
| screenshot: '/images/tools/tool-keyword-research.jpg', | ||
| }, | ||
| ]; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n \
-g '*.test.ts' -g '*.test.tsx' -g '*.spec.ts' -g '*.spec.tsx' \
'HomePage|SIMULATORS|Campaign Builder|Bid Elevator|Search Term Triage|Listing Audit|Keyword Research' .Repository: projectamazonph/amph-v2
Length of output: 161
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== page.tsx outline ==\n'
ast-grep outline src/app/page.tsx --view expanded || true
printf '\n== relevant tests/files ==\n'
git ls-files 'src/**/*test.*' 'src/**/*spec.*' | sed -n '1,200p'
printf '\n== search for homepage-related test coverage ==\n'
rg -n -S -g '*.test.ts' -g '*.test.tsx' -g '*.spec.ts' -g '*.spec.tsx' \
'page\.tsx|SIMULATORS|Campaign Builder|Bid Elevator|Search Term Triage|Listing Audit|Keyword Research|HomePage|homepage' src test .Repository: projectamazonph/amph-v2
Length of output: 1528
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== src/app/page.tsx ==\n'
wc -l src/app/page.tsx
sed -n '1,220p' src/app/page.tsx
printf '\n== files that look like homepage tests or snapshots ==\n'
fd -a -t f 'page.*(test|spec)\.(ts|tsx|js|jsx)$|homepage|home' src test . 2>/dev/null || trueRepository: projectamazonph/amph-v2
Length of output: 8837
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== grep for the simulator ids/descriptions in all repo files ==\n'
rg -n -S 'campaign-builder|bid-elevator|str-triage|listing-audit|keyword-research|Campaign Builder|Bid Elevator|Search Term Triage|Listing Audit|Keyword Research' .
printf '\n== list app tests directories ==\n'
find src -type d | sed -n '1,200p'Repository: projectamazonph/amph-v2
Length of output: 38305
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== test files in repo ==\n'
git ls-files | rg '\.(test|spec)\.(ts|tsx|js|jsx)$' || true
printf '\n== page.tsx content ==\n'
cat -n src/app/page.tsx | sed -n '1,220p'
printf '\n== any tests near app/page ==\n'
rg -n -S 'render\(|screen\.|toMatchSnapshot|page\.tsx|Home|homepage|SIMULATORS' src/app src/components test . \
-g '*.{test,spec}.{ts,tsx,js,jsx}' || trueRepository: projectamazonph/amph-v2
Length of output: 11258
Add a focused test for the homepage simulator cards. src/app/page.tsx:16-57 The only current coverage here is the homepage smoke check in tests/e2e/critical-path.spec.ts, which doesn’t assert the SIMULATORS data or rendered cards.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/page.tsx` around lines 16 - 57, Add focused test coverage for the
homepage simulator cards defined by SIMULATORS in the homepage component. Verify
the expected simulator metadata and that each configured simulator card is
rendered, rather than relying only on the existing smoke test in
critical-path.spec.ts.
Source: Coding guidelines
| <h2>Where most Amazon PPC training falls apart</h2> | ||
| <ul className={styles.painList}> | ||
| <li className={styles.painItem}> | ||
| You finish the lessons, but you've never actually touched a campaign. | ||
| </li> | ||
| <li className={styles.learnItem}> | ||
| <h3>Bid optimization</h3> | ||
| <li className={styles.painItem}> | ||
| You know the vocabulary — ACoS, ROAS, CPC — but freeze the first | ||
| time you have to act on it. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Define the PPC metrics on first use.
Expand ACoS, ROAS, and CPC here so new virtual assistants can understand the pain point without prior Amazon Ads experience.
As per coding guidelines, define jargon and use direct, plain-spoken language for the Filipino VA audience.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/page.tsx` around lines 112 - 119, Update the painList content in the
page component to define ACoS, ROAS, and CPC at their first use, using their
full terms and direct, plain-spoken wording for Filipino virtual assistants
while preserving the surrounding pain-point message.
Source: Coding guidelines
Compared the live page section-by-section against the design spec in docs/stitch-prompts.md and closed the gaps: - Simulator section was a banned pattern (3-column equal grid, icon + heading + text repeated) — rebuilt as an alternating zig-zag of rows, screenshot on one side, copy on the other. - Pricing and CTA sections were centered; spec calls for left-aligned text throughout, no centered-everything layouts. De-centered both. - CTA section now uses the dark surface-3 token as the spec's full-width dark panel calls for, instead of blending into the page. - Replaced the repeated inline-style buttons with shared .btnPrimary/.btnSecondary classes so hover/active states (tactile -1px press) are possible at all. - Added the mandated motion system: hero elements cascade in on load, below-fold sections and their list items (pain points, simulator rows, coming-soon cards) reveal on scroll-in via a new RevealSection client component wrapping IntersectionObserver, with per-item stagger delays. Interactive cards get a hover lift. Respects prefers-reduced-motion (already handled globally).
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/home.module.css`:
- Around line 7-16: Rename the `@keyframes` identifier fadeInUp to fade-in-up in
home.module.css, and update every corresponding animation reference to use the
new kebab-case name, including the occurrences noted elsewhere in the diff.
- Around line 7-37: Adjust the section reveal styles around the selectors for
painSection, simSection, accessSection, pricingSection, and ctaSection by adding
a prefers-reduced-motion media query that disables animation and transitions and
forces these sections, along with their nested reveal items, to opacity: 1 and
their final transform. Keep the normal scroll-reveal behavior unchanged when
reduced motion is not requested.
In `@src/components/RevealSection.tsx`:
- Around line 15-37: Add regression tests for RevealSection covering visibility
when an observer entry intersects, visibility when boundingClientRect.top is
above the viewport, cleanup via observer disconnect/unobserve, and the empty
observer entry list without throwing. Use mocks for IntersectionObserver and
verify the rendered content’s visibility behavior.
- Around line 10-13: Rewrite the comments around RevealSection to explain why
the section is revealed only once and why the observer disconnects to avoid
content remaining hidden, rather than describing implementation details. Apply
the same update to the comments at both referenced locations, and replace all em
dashes with standard punctuation.
- Around line 23-31: Guard the observer callback in RevealSection so it handles
an empty entries list before destructuring or accessing entry. Preserve the
existing visibility and unobserve behavior for the first entry when present,
including the isIntersecting and boundingClientRect.top checks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c571d784-70ef-4aab-a0b7-7337550bf64e
📒 Files selected for processing (3)
src/app/home.module.csssrc/app/page.tsxsrc/components/RevealSection.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/page.tsx
| @keyframes fadeInUp { | ||
| from { | ||
| opacity: 0; | ||
| transform: translateY(8px); | ||
| } | ||
| to { | ||
| opacity: 1; | ||
| transform: none; | ||
| } | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Rename the keyframe to satisfy the configured naming rule.
Stylelint requires kebab-case keyframe names.
Proposed fix
-@keyframes fadeInUp {
+@keyframes fade-in-up {Replace each animation: fadeInUp ... reference with animation: fade-in-up ....
Also applies to: 93-124, 151-151
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 7-7: Expected keyframe name "fadeInUp" to be kebab-case (keyframes-name-pattern)
(keyframes-name-pattern)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/home.module.css` around lines 7 - 16, Rename the `@keyframes`
identifier fadeInUp to fade-in-up in home.module.css, and update every
corresponding animation reference to use the new kebab-case name, including the
occurrences noted elsewhere in the diff.
Source: Linters/SAST tools
| export function RevealSection({ children, className }: RevealSectionProps) { | ||
| const ref = useRef<HTMLElement>(null); | ||
| const [visible, setVisible] = useState(false); | ||
|
|
||
| useEffect(() => { | ||
| const el = ref.current; | ||
| if (!el) return; | ||
| const observer = new IntersectionObserver( | ||
| ([entry]) => { | ||
| // Reveal on normal scroll-into-view, and also if the element is | ||
| // already above the viewport (e.g. a hash-link landed past it) — | ||
| // otherwise content scrolled past before ever intersecting would | ||
| // stay permanently invisible. | ||
| if (entry.isIntersecting || entry.boundingClientRect.top < 0) { | ||
| setVisible(true); | ||
| observer.unobserve(el); | ||
| } | ||
| }, | ||
| { threshold: 0.15, rootMargin: '0px 0px -40px 0px' }, | ||
| ); | ||
| observer.observe(el); | ||
| return () => observer.disconnect(); | ||
| }, []); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Add regression tests for the reveal behavior.
Cover intersection, the above-viewport fallback, cleanup, and an empty observer entry list.
As per coding guidelines, **/*.{ts,tsx,md,mdx}: “New features must include tests.”
🧰 Tools
🪛 GitHub Actions: CI / 2_Quality Gates.txt
[error] 28-28: Typecheck failed (tsc --noEmit). TS18048: 'entry' is possibly 'undefined'.
🪛 GitHub Actions: CI / Quality Gates
[error] 28-28: TypeScript (tsc) error TS18048: 'entry' is possibly 'undefined'.
🪛 GitHub Check: Quality Gates
[failure] 28-28:
'entry' is possibly 'undefined'.
[failure] 28-28:
'entry' is possibly 'undefined'.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/RevealSection.tsx` around lines 15 - 37, Add regression tests
for RevealSection covering visibility when an observer entry intersects,
visibility when boundingClientRect.top is above the viewport, cleanup via
observer disconnect/unobserve, and the empty observer entry list without
throwing. Use mocks for IntersectionObserver and verify the rendered content’s
visibility behavior.
Source: Coding guidelines
Array destructuring from IntersectionObserverCallback's entries list types `entry` as possibly undefined under strict mode. Guard before use instead of asserting.
AGENTS.md bans em-dashes repo-wide; replaced the ones this PR introduced in copy and comments with periods, commas, or parentheses. Also made the scroll-reveal sections skip straight to their visible state under prefers-reduced-motion instead of relying solely on the global transition-duration override to make it instant.
…ent-audit status CLAUDE.md incorrectly claimed the legacy curriculum still described a different product (AdCraft/AI Mentor) and had an empty Commands section. docs/CONTENT-AUDIT-2026-07-16.md's four P0 findings were all actually resolved in a prior session but only one had a status note. Corrected both against the current repo state. Appended a SESSION-HANDOVER.md entry covering this session: landing page repositioning, the Field Manual design-drift audit and fixes (PRs #38-39), edge auth coverage extended to the full student area plus the Campaign Builder BTV scenario registry fix (PR #40, TDD), and the branch cleanup audit plus video-explainer asset PR (#41). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q2obMCR2P3RHTZMqph1QL1
* docs: update handoff docs for this session's work, correct stale content-audit status CLAUDE.md incorrectly claimed the legacy curriculum still described a different product (AdCraft/AI Mentor) and had an empty Commands section. docs/CONTENT-AUDIT-2026-07-16.md's four P0 findings were all actually resolved in a prior session but only one had a status note. Corrected both against the current repo state. Appended a SESSION-HANDOVER.md entry covering this session: landing page repositioning, the Field Manual design-drift audit and fixes (PRs #38-39), edge auth coverage extended to the full student area plus the Campaign Builder BTV scenario registry fix (PR #40, TDD), and the branch cleanup audit plus video-explainer asset PR (#41). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q2obMCR2P3RHTZMqph1QL1 * Address CodeRabbit review: don't overclaim Release 1, fix markdown lint Release 1 was marked "done" while the Ultimate tier still has no course and fact cards still need owner-filled metadata. Retitled to "substantially complete, two follow-ups remain" and made both gaps explicit rather than parenthetical. Added a language identifier to the branch-list fence (MD040). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q2obMCR2P3RHTZMqph1QL1 --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
The landing page copy overstated the product ("three courses" — it's one course, three tiers) and undersold the actual differentiator (five working practice simulators, not just lessons). Separately, the page's layout and visual language had drifted from the "Field Manual" design system in
docs/stitch-prompts.md.Badgecomponent — it stretched to full card width instead of staying a pill whenever used as a direct child ofCardHeader(visible on all 5 live tool runner pages, not just the landing page). Addedalign-self: flex-startinBadge.module.css.surface-3treatment the spec calls for, and added the mandated motion system (on-load hero cascade, scroll-triggered section/card reveals via a newRevealSectioncomponent, tactile button press, hover-lift on interactive cards). Respectsprefers-reduced-motion(already handled globally).Test plan
Co-Authored-By: Claude Sonnet 5
Claude-Session: https://claude.ai/code/session_01Q2obMCR2P3RHTZMqph1QL1
Summary by CodeRabbit
New Features
Style