Skip to content

[pm-manager/pm-coder][pricing-fallback-landing] add /pricing and /get-started fallback landing page - #144

Merged
Smetools merged 2 commits into
mainfrom
hassan-pricing-fallback-landing
Aug 3, 2026
Merged

[pm-manager/pm-coder][pricing-fallback-landing] add /pricing and /get-started fallback landing page#144
Smetools merged 2 commits into
mainfrom
hassan-pricing-fallback-landing

Conversation

@Smetools

@Smetools Smetools commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

What this is

EPIC 24 - Pricing Page + GTM Surface. Both open slices, one branch, one PR (pm-coder's standing rule: an epic's slices are never built separately):

  • #7670 - Fallback landing page (/get-started) - insurance for the 16 Aug paid-ad launch in case the StratDev agency page slips.
  • #5824 - Pricing page (/pricing) - the marketing site had no pricing surface at all.

#6953 (the third child of this epic) was NOT touched - it already sits at stage "Push to Production" with its own fix landed.

Agent: pm-manager / pm-coder - run 11

Odoo: https://smetools.odoo.com/odoo/project.task/7670
Odoo: https://smetools.odoo.com/odoo/project.task/5824

A repo deviation, flagged on purpose

pm-coder's standing routine assumes the core knowcap app repo (worktrees off origin/hassan, PRs to hassan). This ticket's code lives in knowcap-website, a different, satellite repo - confirmed directly (EditorialShell, /for/saudi-arabia, hero-section.tsx all live here, not in the app repo). Its own rules differ: trunk is main (no hassan branch exists here), so this worktree was cut from origin/main and this PR targets main.

Numbers verified against the live database, not copied from the ticket

Queried public.plans directly (Supabase):

Plan monthly_price_cents per_seat_pricing Shown as
free 0 false $0, no card
pro 2000 true $20/seat/mo
business 4000 true $40/seat/mo
enterprise 0 (custom, negotiated) true Custom, book a call

Feature bullets per tier are drawn from each plan's own capabilities jsonb column (capture / chat / ask / broadcast / extraction / artifacts / graph / personal_integrations / team_governance / admin_analytics / confirm_hierarchy / mcp_analyze / mcp_write / vertical_template), not invented.

No annual toggle on either page. #6953 (this epic's sibling ticket, same launch window) found the app currently mischarges anyone who picks annual billing - no annual Stripe price exists - and is removing the annual offer everywhere (paywall, settings, pricing page, marketing site) before 16 Aug for exactly that reason. Showing "2 months free" here would be the identical false promise on the marketing site, so it's deliberately absent. Revisit once #6953 Part B ships a real annual price.

Design system

Both pages use the shared EditorialShell (matches the live /for/saudi-arabia page), not hero-section.tsx / beta-hero-section.tsx - both confirmed dead (zero importers, grepped) per the ticket's own warning. The old components/navbar.tsx / components/footer.tsx are ALSO dead (zero importers, not used by the homepage or anywhere else) - not touched.

Wired "Pricing" into EditorialHeader's nav and EditorialFooter's Product column, and both new routes into sitemap.ts (/pricing included; /get-started deliberately excluded + robots: {index:false}, same treatment as the existing /beta ad-funnel page - it's an ad destination, not an SEO surface).

Campaign-tag attribution (#7670's own success criterion)

app/lib/campaign.ts forwards utm_source/utm_medium/utm_campaign/utm_content/utm_term/gclid/fbclid from the incoming query string into the app.knowcap.ai/register link. Verified live in a browser this carries through correctly, including a malformed/truncated tag (page still loads, link still works - no crash).

Found and fixed a real gap while proving this live: the shared header/footer's generic "Get Started Free" button did NOT carry the tag - only the page's own two buttons did. A mobile visitor tapping the top-right button instead of the page's main CTA would have silently lost attribution. Fixed by giving EditorialShell an optional registerHref override (backward-compatible - verified all 20 existing callers of EditorialShell pass no such prop, so their behavior is byte-for-byte unchanged).

The app itself (knowcap Main, a different repo) does not yet persist these params into the account record on registration - that's explicitly out of this slice's scope ("any change to what signup does" - #7670's own words). This only keeps the tag alive through the click.

Browser proof (Stage 8)

Ran next dev locally against this branch's own code (no live backend dependency - these are static content pages), driven in the shared automation Edge via Playwright.

  • /pricing: loads clean, 0 console errors, all 4 tiers render with correct prices/features, all register/book links carry forwarded campaign params. Screenshot at desktop (1280px) and mobile (390px) - both clean, tiers stack to one column on mobile.
  • /get-started: loads clean, 0 console errors (one unrelated Next.js dev-only HMR/bfcache websocket message, not a real app error - doesn't exist in production). All 4 register links (2 page CTAs + shared header + shared footer) verified carrying the tag. OG/Twitter card tags confirmed present and resolving to a real 328KB image (WhatsApp/LinkedIn share preview criterion). Screenshot at desktop and mobile - both clean, CTA reachable above the fold on a phone.
  • Adversarial - malformed tag: ?utm_source=%E2%9C%93%00trunc&utm_campaign= - page loads fine, 0 errors.
  • Not verified by this PR (inherited app behavior, outside this repo): an already-signed-in visitor hitting the register link - that redirect logic lives in the app repo, untouched here.
  • Not attempted (explicitly out of this slice): Slice 3's cold-outside-production walk-through and the Google OAuth signup path - both need production/a real Google account.

Gates (both run as real, independent subagent invocations - no self-review)

  • /security-review: CLEAN, 0 findings. Query-string values only ever reach the link via URLSearchParams.set() (auto-encoded) + React's own attribute escaping - two independent layers close the injection/XSS/open-redirect angle. All base URLs confirmed hardcoded, never user-derived, so SSRF doesn't apply.
  • /bug-radar (quick, adapted): CLEAN, 0 findings. Note: this skill's escapes ledger is written for the core app repo (auth/DB/org-scoping bugs) - none of those classes are structurally possible on this diff (no DB routes, no auth surface touched), checked and confirmed rather than skipped. Silent-failure sweep, new-discriminant lens, and the shared-component regression check (all 20 existing EditorialShell callers) all came back clean.
  • Both first-attempt clean - no fix-and-repush cycle needed.
  • Not written to engineering/qa-manager/state/radar-health.json this run - that file is under heavy, live concurrent write traffic from qa-manager's own dark-watcher fleet, and this is a one-off adapted cross-repo check, not a literal scheduled bug-radar run against the app. Gate results recorded here and in pm-coder's own state instead.

Holding at PR - not merging (Type-1 surface)

This page makes public price promises and IS launch copy. knowcap-website is a satellite repo whose PRs normally auto-merge once the gate passes - but per pm-coder's dispatch brief, a page that makes public pricing promises to the world is exactly the kind of Type-1 surface reserved for Hassan's own click, not an automatic merge. Holding here rather than assuming the satellite auto-merge rule covers this content.

What Hassan gets from merging this

/pricing and /get-started go live on knowcap.ai once this merges (Vercel auto-deploys main). Both are ready destinations for the 16 Aug ad campaign if the agency's own page isn't ready in time.

Summary by CodeRabbit

  • New Features
    • Added a responsive pricing page featuring Free, Pro, Business, and Enterprise plans with feature comparisons and calls to action.
    • Added a campaign-aware “Get Started” landing page with registration and contact options.
    • Added campaign attribution to registration, booking, and internal links.
    • Added a Pricing link to the site footer.
  • SEO
    • Added page metadata, social sharing previews, and sitemap coverage for the pricing page.
    • Marked the campaign landing page as excluded from search indexing.

EPIC 24 - Pricing Page + GTM Surface. Two slices, one PR:
- #5824: knowcap.ai/pricing - the locked 4-tier ladder (Free/Pro/Business/
  Enterprise), wired into the shared editorial nav + footer + sitemap.
- #7670: knowcap.ai/get-started - a plain, self-owned ad-landing fallback in
  case the agency's campaign page slips before the 16 Aug launch.

Prices verified live against the public.plans table (Supabase), not copied
from the Odoo card: free=$0, pro=$20/seat, business=$40/seat, enterprise=
custom. No annual toggle on either page - #6953 (sibling ticket, same epic)
found the app currently mischarges anyone who picks annual and is removing
the annual offer everywhere before launch; showing it here would be the same
false promise on the marketing site.

Both pages forward utm_source/utm_medium/utm_campaign/utm_content/utm_term/
gclid/fbclid into the app.knowcap.ai/register link (app/lib/campaign.ts) so a
paid-ad tag survives the click into signup - including the shared header/
footer's generic "Get Started Free" button (shell.tsx gains an optional
registerHref override, backward-compatible, verified against all 20 existing
callers).

Built on the shared EditorialShell design system (matches /for/saudi-arabia)
rather than the two dead components named in the ticket (hero-section.tsx,
beta-hero-section.tsx - confirmed zero importers).

Agent: pm-manager / pm-coder - run 11

Odoo: https://smetools.odoo.com/odoo/project.task/7670
Odoo: https://smetools.odoo.com/odoo/project.task/5824
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
knowcap-landing Ready Ready Preview Aug 3, 2026 12:41pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Smetools, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b888e9ec-88b8-497b-af08-a7041cc71cfe

📥 Commits

Reviewing files that changed from the base of the PR and between 2ff447b and 5a2145c.

📒 Files selected for processing (1)
  • app/lib/pricing.ts
📝 Walkthrough

Walkthrough

Added a no-index /get-started landing page and a public /pricing page. Added shared pricing tier data, campaign parameter propagation, campaign-aware registration links, editorial navigation updates, and sitemap coverage for /pricing.

Changes

Pricing and landing flow

Layer / File(s) Summary
Pricing contract and campaign utilities
app/lib/pricing.ts, app/lib/campaign.ts
Defines four pricing tiers and propagates selected campaign parameters through external and internal URLs.
Pricing page and shared navigation
app/app/pricing/page.tsx, app/components/editorial/shell.tsx, app/app/sitemap.ts
Adds responsive pricing cards, tier-specific CTAs, Pricing navigation links, registration URL overrides, and the /pricing sitemap entry.
Get-started campaign landing page
app/app/get-started/page.tsx
Adds metadata, editorial sections, pricing summaries, and campaign-aware registration calls to action for the no-index landing page.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Visitor
  participant GetStartedPage
  participant CampaignUtility
  participant EditorialShell
  participant Registration
  Visitor->>GetStartedPage: Open page with campaign parameters
  GetStartedPage->>CampaignUtility: Build registration URL
  CampaignUtility-->>GetStartedPage: Return campaign-aware URL
  GetStartedPage->>EditorialShell: Provide registerHref
  EditorialShell->>Registration: Render campaign-aware CTA
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the addition of the /pricing and /get-started fallback landing pages, which matches the main pull request changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hassan-pricing-fallback-landing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@app/app/get-started/page.tsx`:
- Around line 107-109: Update the pricing Link in the get-started page to build
its href with withCampaignParamsRelative('/pricing', searchParams,
'get_started_fallback'), preserving campaign parameters for paid-ad visitors
while retaining the existing link text and destination.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d10b2706-3325-4dad-a81c-58bc0fe9470c

📥 Commits

Reviewing files that changed from the base of the PR and between 9da9169 and 2ff447b.

📒 Files selected for processing (6)
  • app/app/get-started/page.tsx
  • app/app/pricing/page.tsx
  • app/app/sitemap.ts
  • app/components/editorial/shell.tsx
  • app/lib/campaign.ts
  • app/lib/pricing.ts

Comment on lines +107 to +109
<p className="gs-price-link">
Full plan details on the <Link href="/pricing">pricing page</Link>.
</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve campaign parameters on the pricing-page link.

When a paid-ad visitor selects this link, /pricing receives no campaign parameters. Its registration CTA then uses utm_source=pricing_page instead of the original campaign attribution.

Build the pricing href with withCampaignParamsRelative('/pricing', searchParams, 'get_started_fallback').

Proposed fix
-import { withCampaignParams } from '`@/lib/campaign`'
+import { withCampaignParams, withCampaignParamsRelative } from '`@/lib/campaign`'
@@
   const registerUrl = withCampaignParams('https://app.knowcap.ai/register', searchParams, 'get_started_fallback')
+  const pricingUrl = withCampaignParamsRelative('/pricing', searchParams, 'get_started_fallback')
@@
-              Full plan details on the <Link href="/pricing">pricing page</Link>.
+              Full plan details on the <Link href={pricingUrl}>pricing page</Link>.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p className="gs-price-link">
Full plan details on the <Link href="/pricing">pricing page</Link>.
</p>
<p className="gs-price-link">
Full plan details on the <Link href={pricingUrl}>pricing page</Link>.
</p>
🤖 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 `@app/app/get-started/page.tsx` around lines 107 - 109, Update the pricing Link
in the get-started page to build its href with
withCampaignParamsRelative('/pricing', searchParams, 'get_started_fallback'),
preserving campaign parameters for paid-ad visitors while retaining the existing
link text and destination.

…t the code refuses

The Pro tier advertised 'Connect your own tools over MCP'. The live entitlement
code requires the Business plan for both mcp_analyze and mcp_write and returns
'This MCP tool requires the Business plan.' to a Pro customer who tries it
(entitlementService.ts). A $20/seat customer was being promised a feature the
server blocks and then asked to pay double for it.

The June feature matrix attached to EPIC 24's parent card (#6071) made the SAME
assumption, so reading that document would not have caught this — the gate moved
to Business about a week after the matrix was locked. Only the shipped code did.

Pro's fourth bullet now names the personal integrations it genuinely has
(personal_integrations IS in Pro's capability list). Business's MCP bullet now
reads as the tier where MCP starts, dropping the 'not just read' phrasing that
implied Pro had read-only access.

Prices, the 5-meeting free cap, and every other Business/Enterprise bullet were
verified against the live plans table and the code's own FEATURE_MIN_TIER map —
all correct, no other change needed.

Odoo: https://smetools.odoo.com/odoo/project.task/5824

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Smetools
Smetools merged commit b71d0f4 into main Aug 3, 2026
3 checks passed
@Smetools
Smetools deleted the hassan-pricing-fallback-landing branch August 3, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant