feat(home): conversion-rate optimization pass on homepage
E2E Test Suite / Smoke Tests (P0) (push) Failing after 9m26s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Form Interaction Tests (push) Has been cancelled
E2E Test Suite / Destructive & Chaos Tests (push) Has been cancelled
E2E Test Suite / Cross-Browser Regression (chromium) (push) Has been cancelled
E2E Test Suite / Cross-Browser Regression (firefox) (push) Has been cancelled
E2E Test Suite / Cross-Browser Regression (webkit) (push) Has been cancelled
E2E Test Suite / Mobile Device Tests (push) Has been cancelled
E2E Test Suite / Security Header Tests (push) Has been cancelled
E2E Test Suite / Test Report Summary (push) Has been cancelled
Ping Search Engines / Notify Search Engines (push) Failing after 12m53s
Deploy to Production / Build & Verify (push) Blocked by required conditions
Deploy to Production / Pre-Deploy Tests (push) Blocked by required conditions
Deploy to Production / Deploy to Railway (push) Has been cancelled
Deploy to Production / Deploy to Render (push) Has been cancelled
Deploy to Production / Deploy to VPS (PM2) (push) Has been cancelled
Deploy to Production / Deploy to Fly.io (push) Has been cancelled
Deploy to Production / Post-Deploy Verification (push) Has been cancelled
Deploy to Production / Notify on Failure (push) Has been cancelled

Hero
- Tightened H1 to a benefit-led, audience-first value prop
  ("Custom Software That Powers Enterprises & Governments")
- Replaced generic subhead with a ~135-char outcome line that names
  the audience (startups, enterprises, government bodies)
- Swapped primary CTA copy to an action verb ("Get a free consultation")
  and secondary to "See our work"; added source query params + data-cta
  hooks so analytics can attribute CTA clicks
- Added a micro-trust line under the CTAs (free 30-min call, reply within
  1 business day, no commitment)

Social proof
- New ClientLogos.astro component rendered below the hero. Grayscale
  strip with hover pop, image+wordmark fallback, TODO documenting the
  five required SVG assets in public/images/clients/
- Default roster sourced from the live portfolio (PLNR, RENTEC, IIT
  Patna, MOC Soft Technologies, Govt. of Bihar)
- Existing testimonials carousel left intact (3 quotes with name/role)

Services preview
- Reframed the 4 cards around outcome headlines and added deep links
  to /services#<slug> for each service detail section
- Renamed "Learn More" to "Learn more" and made it a real <a> link
  with aria-label for screen readers

Final CTA band
- New conversion-focused headline ("Ready to ship your next production
  system?") and a one-line offer with explicit response SLA
- Added a "what you'll get" reassurance row (discovery call, fixed-price
  scope, NDA on request)
- Primary CTA now "Get my free consultation" with source attribution;
  secondary "See case studies" preserved
- Process-section CTA renamed to "Book a discovery call" and tagged

SEO
- Updated meta description on BaseLayout invocation to match the new
  positioning; FAQPage schema and existing structured data untouched
This commit is contained in:
platform-mcp
2026-06-17 11:13:03 +05:30
parent bf59e4f3bb
commit 347efa6742
2 changed files with 234 additions and 36 deletions
+144
View File
@@ -0,0 +1,144 @@
---
/**
* ClientLogos Component
*
* Social-proof strip of client/partner logos shown beneath the hero on the
* homepage. Renders as a grayscale, lazy-loaded grid that pops to full colour
* on hover so the section stays subtle but credible.
*
* The component accepts an optional `clients` prop. Each entry can carry:
* - name: display name and accessible alt text (required)
* - logo: path to a logo image asset (optional). When provided the
* image is lazy-loaded and rendered grayscale; otherwise the
* name is rendered as a typographic wordmark fallback so the
* strip still renders intentionally while real assets are
* being collected.
* - href: optional outbound URL or internal anchor (e.g. a portfolio
* case study). Omitted entries render as non-interactive items.
* - subtitle: optional one-liner under the wordmark (e.g. "11 districts").
*
* If no `clients` prop is supplied the component uses a sensible default set
* sourced from the active WorkRoot portfolio (PLNR, RENTEC, IIT Patna, MOC
* Soft Technologies, Government of Bihar). When the real logo assets land
* in `public/images/clients/<slug>.svg` simply add the `logo` field to the
* matching entry (see TODO block in this file) and the component will swap
* the wordmark for the image automatically.
*
* @prop {Array<{ name: string; logo?: string; href?: string; subtitle?: string }>} [clients]
* @prop {string} [heading] - Eyebrow text rendered above the strip
* @prop {'light' | 'dark'} [theme] - 'light' for white sections, 'dark' for
* dark/hero adjacent placement
* @prop {string} [class] - Extra classes merged onto the wrapper section
*/
interface ClientEntry {
name: string;
logo?: string;
href?: string;
subtitle?: string;
}
interface Props {
clients?: ClientEntry[];
heading?: string;
theme?: 'light' | 'dark';
class?: string;
}
const {
clients,
heading = 'Trusted by teams shipping production software',
theme = 'light',
class: extraClass = '',
} = Astro.props;
// -----------------------------------------------------------------------------
// Default client roster — sourced from the live portfolio and testimonials.
// TODO(frontend-specialist): drop real SVG/PNG wordmarks into
// public/images/clients/<slug>.svg
// and populate the `logo` field below. Required asset slugs:
// - plnr.svg (PLNR Financing platform)
// - rentec.svg (RENTEC / FPC Cart)
// - iit-patna.svg (IIT Patna University Management)
// - moc-soft.svg (MOC Soft Technologies)
// - gov-bihar.svg (Government of Bihar — Police Management / SCMS)
// Logos should be supplied as monochrome SVG on a transparent background and
// sized roughly 160 × 48 — the grayscale filter handles the rest.
// -----------------------------------------------------------------------------
const defaultClients: ClientEntry[] = [
{ name: 'PLNR', subtitle: 'Financing Platform' },
{ name: 'RENTEC', subtitle: 'FPC Cart' },
{ name: 'IIT Patna', subtitle: 'University System' },
{ name: 'MOC Soft Technologies', subtitle: 'Enterprise Partner' },
{ name: 'Govt. of Bihar', subtitle: '11 Districts' },
];
const items: ClientEntry[] = clients && clients.length > 0 ? clients : defaultClients;
const isDark = theme === 'dark';
const sectionClass = [
'relative',
isDark
? 'bg-secondary-900'
: 'bg-white dark:bg-secondary-900',
extraClass,
].filter(Boolean).join(' ');
const eyebrowClass = isDark
? 'text-xs sm:text-sm uppercase tracking-[0.2em] text-secondary-400 font-semibold'
: 'text-xs sm:text-sm uppercase tracking-[0.2em] text-secondary-500 dark:text-secondary-400 font-semibold';
const wordmarkClass = isDark
? 'text-lg sm:text-xl font-bold text-white/80 group-hover:text-white transition-colors'
: 'text-lg sm:text-xl font-bold text-secondary-700 dark:text-secondary-200 group-hover:text-secondary-900 dark:group-hover:text-white transition-colors';
const subtitleClass = isDark
? 'block text-[11px] uppercase tracking-wider text-secondary-500 mt-1'
: 'block text-[11px] uppercase tracking-wider text-secondary-400 dark:text-secondary-500 mt-1';
const imageFilter = 'grayscale opacity-70 group-hover:grayscale-0 group-hover:opacity-100 transition-all duration-300';
---
<section class={sectionClass} aria-label="Clients and partners">
<div class="container-wrapper py-12 sm:py-16">
<p class={`text-center mb-8 ${eyebrowClass}`}>{heading}</p>
<ul
class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-x-8 gap-y-10 items-center justify-items-center"
role="list"
>
{items.map((client) => {
const Wrapper = client.href ? 'a' : 'div';
const wrapperProps = client.href
? { href: client.href, 'aria-label': `Learn more about ${client.name}` }
: { 'aria-label': client.name };
return (
<li class="w-full flex justify-center">
<Wrapper
{...wrapperProps}
class={`group flex flex-col items-center justify-center text-center w-full max-w-[180px] min-h-[64px] focus:outline-none focus:ring-2 focus:ring-primary-400 rounded-md ${client.href ? 'cursor-pointer' : ''}`}
>
{client.logo ? (
<img
src={client.logo}
alt={`${client.name} logo`}
loading="lazy"
decoding="async"
width="160"
height="48"
class={`h-10 sm:h-12 w-auto object-contain ${imageFilter}`}
/>
) : (
<span class={wordmarkClass}>{client.name}</span>
)}
{client.subtitle && (
<span class={subtitleClass}>{client.subtitle}</span>
)}
</Wrapper>
</li>
);
})}
</ul>
</div>
</section>