Queue-North-Website/src/pages/Industries.jsx

149 lines
7.3 KiB
React
Raw Normal View History

2026-05-18 13:55:06 -05:00
import SEO from '@/components/SEO'
feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) Client directive (Levi Halford, 2026-08-01) ahead of Google/Meta lead forms. Privacy policy: - Publish approved policy verbatim at /privacy-policy (src/data/privacyPolicy.js is the single source of truth; 292/292 source lines verified present) - Privacy Policy link in the footer of every page - Effective/Last Updated 2026-07-31, privacy@queuenorth.com as mailto Remove St. Petersburg street address from every surface named in the brief: footer, contact page, schema markup, SEO metadata, Google Maps links. Collapse ProfessionalService + Organization schema into a single Organization with areaServed: United States; drop geo coordinates, priceRange, openingHours. Add the approved US-coverage sentence to About. No replacement address. Crawler visibility (the site previously served 0 bytes of body HTML without JS): - Prerender all 19 routes at build time via src/entry-server.jsx + scripts/prerender.js - Hoist title/meta/canonical/JSON-LD into <head>; renderToString does not do this and react-helmet-async's context is empty under React 19 - Serve prerendered HTML; return a real 404 for unknown paths instead of 200 - Hydrate instead of discarding the prerendered markup SEO/perf: - Titles <=60 and descriptions <=160 chars across all pages - Add BreadcrumbList to interior pages, WebSite to home - Generate sitemap.xml from the route list with git-derived lastmod - 301 duplicate URL forms (trailing slash, //, /index.html), preserving query - Immutable caching for content-hashed assets; no-cache for HTML - Split the 522 KB bundle into app/react-vendor/router/icons - loading/decoding/fetchpriority + per-route hero preload; drop unused asset Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 01:45:52 -05:00
import { buildBreadcrumbLd } from '@/lib/seo'
2026-05-12 01:04:17 -05:00
import { industries } from '@/data/industries'
2026-05-18 14:25:45 -05:00
import { ArrowRight, Building2, CheckCircle2, HeartPulse, ShoppingCart, Factory, Landmark } from 'lucide-react'
import { Link } from 'react-router-dom'
2026-05-18 14:25:45 -05:00
const iconMap = {
'heart-pulse': HeartPulse,
'shopping-cart': ShoppingCart,
2026-05-18 14:25:45 -05:00
'factory': Factory,
'landmark': Landmark,
}
2026-05-12 01:04:17 -05:00
2026-05-26 12:22:11 -05:00
const industryAccentStyles = [
{ card: 'border-t-[3px] border-t-rose-400 hover:border-rose-400/60', iconWrap: 'bg-rose-50', icon: 'text-rose-600' },
{ card: 'border-t-[3px] border-t-primary-blue hover:border-primary-blue/50', iconWrap: 'bg-sky-50', icon: 'text-primary-blue' },
{ card: 'border-t-[3px] border-t-accent-gold hover:border-accent-gold/60', iconWrap: 'bg-amber-50', icon: 'text-amber-600' },
{ card: 'border-t-[3px] border-t-teal-500 hover:border-teal-500/50', iconWrap: 'bg-teal-50', icon: 'text-teal-600' },
]
2026-05-12 01:04:17 -05:00
const Industries = () => {
return (
<>
2026-05-18 13:55:06 -05:00
<SEO
feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) Client directive (Levi Halford, 2026-08-01) ahead of Google/Meta lead forms. Privacy policy: - Publish approved policy verbatim at /privacy-policy (src/data/privacyPolicy.js is the single source of truth; 292/292 source lines verified present) - Privacy Policy link in the footer of every page - Effective/Last Updated 2026-07-31, privacy@queuenorth.com as mailto Remove St. Petersburg street address from every surface named in the brief: footer, contact page, schema markup, SEO metadata, Google Maps links. Collapse ProfessionalService + Organization schema into a single Organization with areaServed: United States; drop geo coordinates, priceRange, openingHours. Add the approved US-coverage sentence to About. No replacement address. Crawler visibility (the site previously served 0 bytes of body HTML without JS): - Prerender all 19 routes at build time via src/entry-server.jsx + scripts/prerender.js - Hoist title/meta/canonical/JSON-LD into <head>; renderToString does not do this and react-helmet-async's context is empty under React 19 - Serve prerendered HTML; return a real 404 for unknown paths instead of 200 - Hydrate instead of discarding the prerendered markup SEO/perf: - Titles <=60 and descriptions <=160 chars across all pages - Add BreadcrumbList to interior pages, WebSite to home - Generate sitemap.xml from the route list with git-derived lastmod - 301 duplicate URL forms (trailing slash, //, /index.html), preserving query - Immutable caching for content-hashed assets; no-cache for HTML - Split the 522 KB bundle into app/react-vendor/router/icons - loading/decoding/fetchpriority + per-route hero preload; drop unused asset Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 01:45:52 -05:00
title="Industries We Serve | Queue North"
2026-05-18 13:55:06 -05:00
description="Queue North Technologies serves healthcare, retail, manufacturing, education, and finance industries with tailored communications and IT solutions."
url="https://queuenorth.com/industries"
feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) Client directive (Levi Halford, 2026-08-01) ahead of Google/Meta lead forms. Privacy policy: - Publish approved policy verbatim at /privacy-policy (src/data/privacyPolicy.js is the single source of truth; 292/292 source lines verified present) - Privacy Policy link in the footer of every page - Effective/Last Updated 2026-07-31, privacy@queuenorth.com as mailto Remove St. Petersburg street address from every surface named in the brief: footer, contact page, schema markup, SEO metadata, Google Maps links. Collapse ProfessionalService + Organization schema into a single Organization with areaServed: United States; drop geo coordinates, priceRange, openingHours. Add the approved US-coverage sentence to About. No replacement address. Crawler visibility (the site previously served 0 bytes of body HTML without JS): - Prerender all 19 routes at build time via src/entry-server.jsx + scripts/prerender.js - Hoist title/meta/canonical/JSON-LD into <head>; renderToString does not do this and react-helmet-async's context is empty under React 19 - Serve prerendered HTML; return a real 404 for unknown paths instead of 200 - Hydrate instead of discarding the prerendered markup SEO/perf: - Titles <=60 and descriptions <=160 chars across all pages - Add BreadcrumbList to interior pages, WebSite to home - Generate sitemap.xml from the route list with git-derived lastmod - 301 duplicate URL forms (trailing slash, //, /index.html), preserving query - Immutable caching for content-hashed assets; no-cache for HTML - Split the 522 KB bundle into app/react-vendor/router/icons - loading/decoding/fetchpriority + per-route hero preload; drop unused asset Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 01:45:52 -05:00
jsonLd={buildBreadcrumbLd([{ name: 'Industries', path: '/industries' }])}
2026-05-18 13:55:06 -05:00
/>
2026-05-18 14:25:45 -05:00
{/* Hero */}
2026-05-26 12:22:11 -05:00
<section className="relative isolate overflow-hidden bg-primary-navy py-16 lg:py-24 text-white">
<div className="absolute inset-0 -z-10">
<img
src="/assets/local-networking.webp"
alt="Network infrastructure used by businesses across industries"
className="h-full w-full object-cover object-center"
feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) Client directive (Levi Halford, 2026-08-01) ahead of Google/Meta lead forms. Privacy policy: - Publish approved policy verbatim at /privacy-policy (src/data/privacyPolicy.js is the single source of truth; 292/292 source lines verified present) - Privacy Policy link in the footer of every page - Effective/Last Updated 2026-07-31, privacy@queuenorth.com as mailto Remove St. Petersburg street address from every surface named in the brief: footer, contact page, schema markup, SEO metadata, Google Maps links. Collapse ProfessionalService + Organization schema into a single Organization with areaServed: United States; drop geo coordinates, priceRange, openingHours. Add the approved US-coverage sentence to About. No replacement address. Crawler visibility (the site previously served 0 bytes of body HTML without JS): - Prerender all 19 routes at build time via src/entry-server.jsx + scripts/prerender.js - Hoist title/meta/canonical/JSON-LD into <head>; renderToString does not do this and react-helmet-async's context is empty under React 19 - Serve prerendered HTML; return a real 404 for unknown paths instead of 200 - Hydrate instead of discarding the prerendered markup SEO/perf: - Titles <=60 and descriptions <=160 chars across all pages - Add BreadcrumbList to interior pages, WebSite to home - Generate sitemap.xml from the route list with git-derived lastmod - 301 duplicate URL forms (trailing slash, //, /index.html), preserving query - Immutable caching for content-hashed assets; no-cache for HTML - Split the 522 KB bundle into app/react-vendor/router/icons - loading/decoding/fetchpriority + per-route hero preload; drop unused asset Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 01:45:52 -05:00
loading="eager"
fetchPriority="high"
decoding="async"
2026-05-26 12:22:11 -05:00
/>
<div className="absolute inset-0 bg-primary-navy/82" />
<div className="absolute inset-0 bg-gradient-to-r from-primary-navy via-primary-navy/92 to-primary-navy/45" />
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
2026-05-18 14:25:45 -05:00
<div className="max-w-3xl">
<div className="inline-flex items-center gap-2 rounded-md border border-white/20 bg-white/10 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-primary-cyan mb-6">
<Building2 className="h-4 w-4" aria-hidden="true" />
Industries
</div>
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight mb-6">
Built around how your industry actually works.
</h1>
<p className="text-lg md:text-xl text-white/75 max-w-2xl leading-relaxed mb-8">
Communications and infrastructure solutions shaped by the compliance, workflow, and connectivity demands of your specific environment.
</p>
2026-05-18 14:25:45 -05:00
<Link
2026-05-27 22:33:54 -05:00
to="/contact#contact-form"
2026-05-18 14:25:45 -05:00
className="inline-flex h-11 items-center justify-center gap-2 rounded-md bg-white px-5 text-sm font-semibold text-primary-navy hover:bg-section-alt transition-colors"
>
Talk to a Specialist
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
</div>
</div>
2026-05-12 01:04:17 -05:00
</section>
{/* Industries Grid */}
2026-05-26 12:22:11 -05:00
<section className="bg-background py-16 lg:py-24">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
2026-05-26 12:22:11 -05:00
<div className="mb-10 max-w-3xl">
<p className="text-sm font-semibold uppercase tracking-wide text-primary-blue">Industry fit</p>
<h2 className="mt-3 text-3xl md:text-4xl font-bold text-primary-navy">Communications needs change by environment.</h2>
<p className="mt-4 text-lg text-soft-text">
We adapt platform, network, and support recommendations to the way your teams actually operate.
</p>
</div>
2026-05-18 13:45:39 -05:00
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
2026-05-26 12:22:11 -05:00
{industries.map((industry, index) => {
2026-05-18 14:25:45 -05:00
const Icon = iconMap[industry.icon] || Building2
2026-05-26 12:22:11 -05:00
const accent = industryAccentStyles[index % industryAccentStyles.length]
return (
2026-05-18 14:25:45 -05:00
<div
key={industry.id}
2026-05-26 12:22:11 -05:00
className={`group flex flex-col rounded-md border border-border bg-white p-8 shadow-sm hover:shadow-md transition-all ${accent.card}`}
2026-05-18 14:25:45 -05:00
>
2026-05-26 12:22:11 -05:00
<div className={`flex h-14 w-14 items-center justify-center rounded-md ${accent.iconWrap} mb-6 flex-shrink-0`}>
<Icon className={`h-7 w-7 ${accent.icon}`} aria-hidden="true" />
</div>
2026-05-18 14:25:45 -05:00
<h2 className="text-2xl font-bold text-primary-navy mb-3">{industry.name}</h2>
<p className="text-soft-text leading-relaxed mb-6">{industry.shortDesc}</p>
<ul className="space-y-2.5 mb-8 flex-1">
{industry.solutions.slice(0, 3).map((solution, i) => (
<li key={i} className="flex items-start gap-3 text-sm text-text">
<CheckCircle2 className="h-4 w-4 text-primary-blue flex-shrink-0 mt-0.5" aria-hidden="true" />
{solution}
</li>
))}
</ul>
<Link
to={`/industries/${industry.id}`}
className="inline-flex items-center gap-1.5 text-sm font-semibold text-primary-navy hover:text-primary-blue transition-colors"
aria-label={`Learn more about ${industry.name} solutions`}
>
See how we help
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
</div>
)
})}
2026-05-12 01:04:17 -05:00
</div>
</div>
2026-05-12 01:04:17 -05:00
</section>
{/* CTA */}
2026-05-26 12:22:11 -05:00
<section className="bg-section-alt py-16 lg:py-24">
2026-05-18 14:25:45 -05:00
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
2026-05-26 12:22:11 -05:00
<div className="rounded-md bg-primary-navy px-6 py-10 text-white shadow-md sm:px-8 lg:flex lg:items-center lg:justify-between lg:gap-10 lg:px-10">
2026-05-18 14:25:45 -05:00
<div>
<h2 className="text-3xl md:text-4xl font-bold mb-3">Don't see your industry?</h2>
<p className="text-white/70 max-w-2xl">
We work with businesses across all sectors. If you have specific compliance, connectivity, or workflow requirements, let's talk.
</p>
</div>
2026-05-26 12:22:11 -05:00
<div className="mt-7 flex flex-col gap-3 sm:flex-row lg:mt-0 lg:flex-shrink-0">
<Link
2026-05-27 22:33:54 -05:00
to="/contact#contact-form"
2026-05-27 12:42:25 -05:00
className="inline-flex w-full sm:w-auto h-11 items-center justify-center gap-2 rounded-md bg-white px-6 text-sm font-semibold text-primary-navy hover:bg-section-alt transition-colors"
2026-05-26 12:22:11 -05:00
>
Talk to a Specialist
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
<a
href="tel:+13217308020"
2026-05-27 12:42:25 -05:00
className="inline-flex w-full sm:w-auto h-11 items-center justify-center rounded-md border border-white/35 px-6 text-sm font-semibold text-white hover:bg-white/10 transition-colors"
2026-05-26 12:22:11 -05:00
>
Call (321) 730-8020
</a>
</div>
</div>
</div>
2026-05-12 01:04:17 -05:00
</section>
</>
2026-05-12 01:04:17 -05:00
)
}
export default Industries