diff --git a/app/services/[slug]/ExpertisePageClient.tsx b/app/services/[slug]/ExpertisePageClient.tsx index a00bda1..0903d5a 100644 --- a/app/services/[slug]/ExpertisePageClient.tsx +++ b/app/services/[slug]/ExpertisePageClient.tsx @@ -8,15 +8,20 @@ import { WhyProcedure, TechStack, FAQSection, - ExpertiseCTA, RelatedExpertise, WhoWeWorkWith, ProcessTimeline, UseCasesGrid, WhyChooseProcedure, QualityMatters, + ArchitectureSection, + EngagementModels, + RiskReversal, + PhilosophySection, + HowItWorks, } from "@/components/expertise"; import { Testimonials } from "@/components/sections/Testimonials"; +import { Stats } from "@/components/sections/Stats"; import { CalInline } from "@/components/CalInline"; import { motion } from "framer-motion"; @@ -97,6 +102,8 @@ export default function ExpertisePageClient({ ? ["Product Design", "UX Design", "UI Design", "Design Systems", "Product Strategy", "User Research"] : expertise.slug === "kubernetes" ? ["Kubernetes Consulting", "Container Orchestration", "Cloud Native Infrastructure", "Kubernetes Implementation", "Kubernetes Optimization"] + : expertise.slug === "dotnet-development" + ? [".NET Development Services", "ASP.NET Core Development", "C# Development", "Azure .NET Development", ".NET Migration Services", "Enterprise .NET Consulting"] : pageData.hero.badge, areaServed: [ { "@type": "Country", name: "United States" }, @@ -131,6 +138,8 @@ export default function ExpertisePageClient({ ? ["Backend Engineering", "Software Development", "API Development"] : expertise.slug === "frontend-development" ? ["Frontend Engineering", "Web Development", "UI/UX Development"] + : expertise.slug === "dotnet-development" + ? [".NET Development", "ASP.NET Core", "C# Development", "Azure Development", "Enterprise Software Development"] : [pageData.hero.badge, "Enterprise AI Engineering", "Software Development"], }, // FAQ Schema (only if FAQs exist) @@ -192,13 +201,15 @@ export default function ExpertisePageClient({ badge={pageData.hero.badge} headline={pageData.hero.headline} headlineAccent={pageData.hero.headlineAccent} - tagline={pageData.hero.tagline} - description={pageData.hero.description} + tagline={expertise.slug === "dotnet-development" ? undefined : pageData.hero.tagline} + description={expertise.slug === "dotnet-development" ? pageData.hero.tagline : pageData.hero.description} primaryCTA={ expertise.slug === "frontend-development" ? { text: "Talk to a Frontend Specialist", href: "#book-call" } : expertise.slug === "backend-development" ? { text: "Talk to a Backend Specialist", href: "#book-call" } + : expertise.slug === "dotnet-development" + ? { text: "Talk to a .NET Expert", href: "#book-call" } : undefined } secondaryCTA={ @@ -207,26 +218,51 @@ export default function ExpertisePageClient({ "ai-agents", "ai-security", "ai-privacy", + "dotnet-development", ].includes(expertise.slug) ? undefined : { text: "View Case Studies", href: "/work" } } /> + {expertise.slug === "dotnet-development" && ( + + )} + - {["frontend-development", "backend-development"].includes(expertise.slug) && pageData.whoWeWorkWith && ( + {["frontend-development", "backend-development", "dotnet-development"].includes(expertise.slug) && pageData.whoWeWorkWith && ( ({ ...a, icon: Icons[a.icon as keyof typeof Icons] || Icons.users, }))} closingStatement={pageData.whoWeWorkWith.closingStatement} + commonApplications={pageData.whoWeWorkWith.commonApplications} + variant={expertise.slug === "dotnet-development" ? "tabs" : "cards"} + /> + )} + + {/* For dotnet-development: Philosophy section comes early, before TechStack */} + {expertise.slug === "dotnet-development" && pageData.philosophy && ( + )} @@ -245,16 +281,31 @@ export default function ExpertisePageClient({ /> )} - + {expertise.slug === "dotnet-development" ? ( + + ) : ( + + )} {pageData.useCases && ( ({ ...uc, icon: Icons[uc.icon as keyof typeof Icons] || Icons.code, @@ -263,12 +314,14 @@ export default function ExpertisePageClient({ /> )} - {pageData.whyChoose && ( + {/* For non-dotnet pages: Philosophy section in original position */} + {expertise.slug !== "dotnet-development" && pageData.whyChoose && ( )} @@ -288,6 +341,44 @@ export default function ExpertisePageClient({ /> )} + {pageData.architecture && ( + + )} + + {pageData.engagementModels && ( + + )} + + {pageData.howItWorks && ( + + )} + + {pageData.riskReversal && ( + + )} + {/* Book a Call Section */}
@@ -301,7 +392,11 @@ export default function ExpertisePageClient({

Ready to Discuss Your
- {pageData.hero.badge} Project? + + {expertise.slug === "dotnet-development" + ? ".NET Project?" + : `${pageData.hero.badge} Project?`} +

{bookingSubtext[expertise.slug] || @@ -324,11 +419,6 @@ export default function ExpertisePageClient({ {pageData.faqs.length > 0 && } {relatedPages.length > 0 && } - - ); } diff --git a/components/expertise/ArchitectureSection.tsx b/components/expertise/ArchitectureSection.tsx new file mode 100644 index 0000000..862a063 --- /dev/null +++ b/components/expertise/ArchitectureSection.tsx @@ -0,0 +1,184 @@ +"use client"; + +import { motion } from "framer-motion"; +import { cn } from "@/lib/utils"; +import Image from "next/image"; + +interface ArchitectureLayer { + name: string; + description: string; +} + +interface ArchitectureSectionProps { + title?: string; + subtitle?: string; + diagramSrc?: string; + diagramAlt?: string; + layers: ArchitectureLayer[]; +} + +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.1, + delayChildren: 0.2, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, x: -16 }, + visible: { + opacity: 1, + x: 0, + transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] as const }, + }, +}; + +export function ArchitectureSection({ + title = "Our Technical Approach", + subtitle, + diagramSrc, + diagramAlt = "Architecture diagram", + layers, +}: ArchitectureSectionProps) { + return ( +

+
+ {/* Section header */} + +

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+ + {/* Two-column layout */} +
+ {/* Left side - Diagram */} + + {diagramSrc ? ( + {diagramAlt} + ) : ( + /* Conceptual architecture diagram - 4 layers with inward dependencies */ +
+
+ {/* Outermost layer - API */} +
+ + API + + {/* Inward arrow - top */} + + + +
+ {/* Second layer - Infrastructure */} +
+ + Infrastructure + + {/* Inward arrow - top */} + + + +
+ {/* Third layer - Application */} +
+ + Application + + {/* Inward arrow - top */} + + + +
+ {/* Innermost layer - Domain (protected core) */} +
+ + Domain + +
+
+

+ Dependencies point inward to protect core business logic. +

+
+ )} +
+ + {/* Right side - Layer descriptions */} + + {layers.map((layer, index) => ( + +
+
+ + {index + 1} + +
+
+

+ {layer.name} +

+

+ {layer.description} +

+
+
+
+ ))} +
+
+
+
+ ); +} diff --git a/components/expertise/CapabilitiesGrid.tsx b/components/expertise/CapabilitiesGrid.tsx index 37fd01b..3136bb8 100644 --- a/components/expertise/CapabilitiesGrid.tsx +++ b/components/expertise/CapabilitiesGrid.tsx @@ -2,6 +2,7 @@ import { motion } from "framer-motion"; import { ReactNode } from "react"; +import { LinkedText } from "@/components/ui/LinkedText"; interface Capability { icon: ReactNode; @@ -87,7 +88,7 @@ export function CapabilitiesGrid({ {capability.title}

- {capability.description} +

))} diff --git a/components/expertise/EngagementModels.tsx b/components/expertise/EngagementModels.tsx new file mode 100644 index 0000000..5c628df --- /dev/null +++ b/components/expertise/EngagementModels.tsx @@ -0,0 +1,123 @@ +"use client"; + +import { motion } from "framer-motion"; +import { cn } from "@/lib/utils"; + +interface EngagementModel { + title: string; + description: string; + bestFor: string; +} + +interface EngagementModelsProps { + title?: string; + subtitle?: string; + models: EngagementModel[]; +} + +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.1, + delayChildren: 0.2, + }, + }, +}; + +const cardVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] as const }, + }, +}; + +export function EngagementModels({ + title = "How Clients Work With Us", + subtitle, + models, +}: EngagementModelsProps) { + return ( +
+
+ {/* Section header */} + +

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+ + {/* Models grid */} + + {models.map((model, index) => ( + + {/* Subtle gradient on hover */} +
+ +
+ {/* Number badge */} +
+ {index + 1} +
+ + {/* Content */} +

+ {model.title} +

+

+ {model.description} +

+ + {/* Best for tag */} +
+ + Best for: + + + {model.bestFor} + +
+
+ + ))} + +
+
+ ); +} diff --git a/components/expertise/ExpertiseCTAWithTestimonial.tsx b/components/expertise/ExpertiseCTAWithTestimonial.tsx new file mode 100644 index 0000000..a2ddb21 --- /dev/null +++ b/components/expertise/ExpertiseCTAWithTestimonial.tsx @@ -0,0 +1,148 @@ +"use client"; + +import { motion } from "framer-motion"; +import Link from "next/link"; +import { Button } from "@/components/ui"; +import { cn } from "@/lib/utils"; + +interface Testimonial { + name: string; + role: string; + company: string; + quote: string; +} + +interface ExpertiseCTAWithTestimonialProps { + headline: string; + description: string; + buttonText?: string; + buttonLink?: string; + supportingNote?: string; + testimonial: Testimonial; +} + +export function ExpertiseCTAWithTestimonial({ + headline, + description, + buttonText = "Schedule a Call", + buttonLink = "/contact-us", + supportingNote, + testimonial, +}: ExpertiseCTAWithTestimonialProps) { + return ( +
+ {/* Top border */} +
+ +
+
+ {/* Left side - CTA */} + +

+ {headline} +

+ +

+ {description} +

+ + + + + + {supportingNote && ( +

+ {supportingNote} +

+ )} +
+ + {/* Right side - Testimonial */} + + {/* Quote mark */} +
+
+ + + +
+
+ +
+

+ “{testimonial.quote}” +

+ +
+ {/* Avatar placeholder */} +
+ + {testimonial.name + .split(" ") + .map((n) => n[0]) + .join("")} + +
+ +
+ + + {testimonial.name} + + + {testimonial.role}, {testimonial.company} + + +
+
+
+
+
+
+
+ ); +} diff --git a/components/expertise/ExpertiseHero.tsx b/components/expertise/ExpertiseHero.tsx index 272b0ad..0abab5a 100644 --- a/components/expertise/ExpertiseHero.tsx +++ b/components/expertise/ExpertiseHero.tsx @@ -5,8 +5,8 @@ import { PageHero } from "@/components/ui"; interface ExpertiseHeroProps { badge: string; headline: string; - headlineAccent: string; - tagline: string; + headlineAccent?: string; + tagline?: string; description: string; primaryCTA?: { text: string; @@ -25,7 +25,7 @@ export function ExpertiseHero({ tagline, description, primaryCTA = { text: "Talk to the Team", href: "#book-call" }, - secondaryCTA = { text: "View Case Studies", href: "/work" }, + secondaryCTA, }: ExpertiseHeroProps) { return ( +
+ {/* Section header */} + +

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+ + {/* Vertical timeline */} + + {/* Timeline line */} +
+ +
+ {steps.map((step, index) => ( + + {/* Step number circle */} +
+ + {index + 1} + +
+ + {/* Step content card */} +
+

+ {step.title} +

+

+ {step.description} +

+
+
+ ))} +
+ + + {/* Closing note */} + {closingNote && ( + + {closingNote} + + )} +
+
+ ); +} diff --git a/components/expertise/PhilosophySection.tsx b/components/expertise/PhilosophySection.tsx new file mode 100644 index 0000000..e83cb69 --- /dev/null +++ b/components/expertise/PhilosophySection.tsx @@ -0,0 +1,65 @@ +"use client"; + +import { motion } from "framer-motion"; +import { cn } from "@/lib/utils"; + +interface PhilosophyBlock { + title: string; + description: string; +} + +interface PhilosophySectionProps { + title: string; + subtitle?: string; + blocks: PhilosophyBlock[]; +} + +export function PhilosophySection({ + title, + subtitle, + blocks, +}: PhilosophySectionProps) { + return ( +
+
+ {/* Section header */} + +

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+ + {/* Philosophy blocks */} +
+ {blocks.map((block, index) => ( + +

+ {block.title} +

+

+ {block.description} +

+
+ ))} +
+
+
+ ); +} diff --git a/components/expertise/RiskReversal.tsx b/components/expertise/RiskReversal.tsx new file mode 100644 index 0000000..dd4a071 --- /dev/null +++ b/components/expertise/RiskReversal.tsx @@ -0,0 +1,255 @@ +"use client"; + +import { motion } from "framer-motion"; +import { cn } from "@/lib/utils"; + +interface RiskReversalItem { + title: string; + description: string; +} + +interface RiskReversalProps { + title?: string; + subtitle?: string; + items: RiskReversalItem[]; + closingNote?: string; + variant?: "grid" | "split"; + leftTriggers?: string[]; + rightBlocks?: RiskReversalItem[]; +} + +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.1, + delayChildren: 0.2, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.4, ease: [0.16, 1, 0.3, 1] as const }, + }, +}; + +export function RiskReversal({ + title = "When Teams Bring Us In", + subtitle, + items, + closingNote, + variant = "grid", + leftTriggers, + rightBlocks, +}: RiskReversalProps) { + // Split layout variant + if (variant === "split" && leftTriggers && rightBlocks) { + return ( +
+
+ {/* Section header */} + +

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+ + {/* Split layout */} +
+ {/* Left side - Trigger statements (editorial) */} + +

+ When teams reach out +

+ {leftTriggers.map((trigger, index) => ( + + +

+ {trigger} +

+
+ ))} +
+ + {/* Right side - Risk reduction blocks (compact) */} + +

+ How we reduce risk +

+ {rightBlocks.map((block, index) => ( + + +
+ + {block.title} + + + + {block.description} + +
+
+ ))} +
+
+ + {/* Closing note */} + {closingNote && ( + +

+ {closingNote} +

+
+ )} +
+
+ ); + } + + // Default grid layout + return ( +
+
+ {/* Section header */} + +

+ {title} +

+ {subtitle && ( +

+ {subtitle} +

+ )} +
+ + {/* Items grid */} + + {items.map((item, index) => ( + + {/* Subtle gradient on hover */} +
+ +
+ {/* Checkmark icon */} +
+ + + +
+ + {/* Content */} +

+ {item.title} +

+

+ {item.description} +

+
+ + ))} + + + {/* Closing note */} + {closingNote && ( + +
+

+ {closingNote} +

+
+
+ )} +
+
+ ); +} diff --git a/components/expertise/TechStack.tsx b/components/expertise/TechStack.tsx index 4e83930..3fcfd11 100644 --- a/components/expertise/TechStack.tsx +++ b/components/expertise/TechStack.tsx @@ -2,16 +2,24 @@ import { motion } from "framer-motion"; import { TechIcon, hasTechIcon } from "@/lib/tech-icons"; +import { LinkedText } from "@/components/ui/LinkedText"; interface Technology { name: string; icon?: React.ReactNode; } +interface TechGroup { + category: string; + items: string[]; +} + interface TechStackProps { title?: string; subtitle?: string; - technologies: Technology[]; + technologies?: Technology[]; + groups?: TechGroup[]; + variant?: "grid" | "grouped"; } const containerVariants = { @@ -38,7 +46,9 @@ const itemVariants = { export function TechStack({ title = "Technologies We Use", subtitle, - technologies, + technologies = [], + groups, + variant = "grid", }: TechStackProps) { return (
@@ -59,44 +69,77 @@ export function TechStack({ )} - {/* Tech grid */} - - {technologies.map((tech, index) => ( - - {/* Icon */} - {tech.icon ? ( -
- {tech.icon} + {/* Grouped chips variant */} + {variant === "grouped" && groups && ( + +
+ {groups.map((group, index) => ( +
+

+ {group.category} +

+
+ {group.items.map((item, itemIndex) => ( + + + + ))} +
- ) : hasTechIcon(tech.name) ? ( -
- -
- ) : ( -
- - {tech.name.charAt(0)} - -
- )} + ))} +
+
+ )} - {/* Tech name */} - - {tech.name} - - - ))} - + {/* Tech grid (default) */} + {variant === "grid" && technologies && technologies.length > 0 && ( + + {technologies.map((tech, index) => ( + + {/* Icon */} + {tech.icon ? ( +
+ {tech.icon} +
+ ) : hasTechIcon(tech.name) ? ( +
+ +
+ ) : ( +
+ + {tech.name.charAt(0)} + +
+ )} + + {/* Tech name */} + + {tech.name} + +
+ ))} +
+ )}
); diff --git a/components/expertise/WhoWeWorkWith.tsx b/components/expertise/WhoWeWorkWith.tsx index ba32862..6902cca 100644 --- a/components/expertise/WhoWeWorkWith.tsx +++ b/components/expertise/WhoWeWorkWith.tsx @@ -1,20 +1,35 @@ "use client"; -import { motion } from "framer-motion"; -import { ReactNode } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { ReactNode, useState } from "react"; import { cn } from "@/lib/utils"; +import { LinkedText } from "@/components/ui/LinkedText"; interface TargetAudience { icon: ReactNode; + title: string; + subtitle?: string; + description?: string; + bullets?: string[]; +} + +interface CommonApplicationItem { title: string; description: string; } +interface CommonApplications { + title: string; + items: (string | CommonApplicationItem)[]; +} + interface WhoWeWorkWithProps { title?: string; subtitle?: string; audiences: TargetAudience[]; closingStatement?: string; + commonApplications?: CommonApplications; + variant?: "cards" | "tabs"; } const containerVariants = { @@ -42,7 +57,11 @@ export function WhoWeWorkWith({ subtitle, audiences, closingStatement, + commonApplications, + variant = "cards", }: WhoWeWorkWithProps) { + const [activeTab, setActiveTab] = useState(0); + return (
@@ -64,61 +83,185 @@ export function WhoWeWorkWith({ )} - {/* Audience cards */} - - {audiences.map((audience, index) => ( - + {/* Tab buttons */} +
+ {audiences.map((audience, index) => ( + + ))} +
+ + {/* Tab content */} +
- {/* Subtle gradient glow on hover */} -
+ + + {audiences[activeTab].subtitle && ( +

+ {audiences[activeTab].subtitle} +

+ )} + {audiences[activeTab].bullets && ( +
    + {audiences[activeTab].bullets.map((bullet, i) => ( +
  • + + {bullet} +
  • + ))} +
+ )} +
+
+
+ + )} -
- {/* Icon container */} -
+ {audiences.map((audience, index) => ( + + {/* Subtle gradient glow on hover */} +
+ +
+ {/* Icon container */} +
+
{audience.icon}
+
+ + {/* Content */} +

+ {audience.title} +

+ {audience.subtitle && ( +

{audience.subtitle}

)} - > -
{audience.icon}
+ {audience.bullets ? ( +
    + {audience.bullets.map((bullet, i) => ( +
  • + + {bullet} +
  • + ))} +
+ ) : audience.description ? ( +

+ {audience.description} +

+ ) : null}
+ + ))} + + )} - {/* Content */} -

- {audience.title} -

-

- {audience.description} -

+ {/* Common Applications - 2-column bullet list */} + {commonApplications && ( + +
+

+ {commonApplications.title} +

+
+ {commonApplications.items.map((item, index) => { + const isObject = typeof item === "object"; + const title = isObject ? item.title : item; + const description = isObject ? item.description : undefined; + + return ( +
+ + + + {description && ( + <> + {": "} + + + )} + +
+ ); + })}
- - ))} - +
+
+ )} - {/* Closing statement */} - {closingStatement && ( + {/* Legacy closing statement (fallback) */} + {closingStatement && !commonApplications && (

- Companies choose Procedure because: + {reasonsTitle}

    {reasons.map((reason, index) => ( diff --git a/components/expertise/index.ts b/components/expertise/index.ts index 4d1e9cc..cdb3eb4 100644 --- a/components/expertise/index.ts +++ b/components/expertise/index.ts @@ -13,3 +13,9 @@ export { ProcessTimeline } from "./ProcessTimeline"; export { UseCasesGrid } from "./UseCasesGrid"; export { WhyChooseProcedure } from "./WhyChooseProcedure"; export { QualityMatters } from "./QualityMatters"; +export { ArchitectureSection } from "./ArchitectureSection"; +export { EngagementModels } from "./EngagementModels"; +export { RiskReversal } from "./RiskReversal"; +export { ExpertiseCTAWithTestimonial } from "./ExpertiseCTAWithTestimonial"; +export { PhilosophySection } from "./PhilosophySection"; +export { HowItWorks } from "./HowItWorks"; diff --git a/components/sections/Stats.tsx b/components/sections/Stats.tsx index e92509d..83f50e2 100644 --- a/components/sections/Stats.tsx +++ b/components/sections/Stats.tsx @@ -2,14 +2,29 @@ import { LazyMotion, m } from "@/components/ui/LazyMotion"; -const stats = [ +const defaultStats = [ { value: "100+", label: "Products Shipped to Production" }, { value: "5", label: "Days to First Deployment" }, { value: "98%", label: "Client Retention Rate" }, { value: "3+", label: "Years Average Partnership" }, ]; -export function Stats() { +interface Stat { + value: string; + label: string; +} + +interface StatsProps { + title?: string; + subtitle?: string; + stats?: Stat[]; +} + +export function Stats({ + title = "Proven results from embedded engineering", + subtitle, + stats = defaultStats, +}: StatsProps) { return (
    @@ -29,8 +44,13 @@ export function Stats() { className="text-center mb-10 sm:mb-12" >

    - Proven results from embedded engineering + {title}

    + {subtitle && ( +

    + {subtitle} +

    + )}
    diff --git a/components/ui/LinkedText.tsx b/components/ui/LinkedText.tsx new file mode 100644 index 0000000..4abfe1a --- /dev/null +++ b/components/ui/LinkedText.tsx @@ -0,0 +1,68 @@ +import Link from "next/link"; +import { Fragment } from "react"; + +/** + * Parses markdown-style links [text](url) in a string and renders them + * as Next.js Link components. Non-link text is rendered as plain text. + * + * Usage: + */ +export function LinkedText({ + text, + className, +}: { + text: string; + className?: string; +}) { + const parts = parseLinkedText(text); + + if (parts.length === 1 && parts[0].type === "text") { + return <>{text}; + } + + return ( + <> + {parts.map((part, i) => + part.type === "link" ? ( + + {part.text} + + ) : ( + {part.text} + ), + )} + + ); +} + +type TextPart = + | { type: "text"; text: string } + | { type: "link"; text: string; href: string }; + +function parseLinkedText(input: string): TextPart[] { + const regex = /\[([^\]]+)\]\(([^)]+)\)/g; + const parts: TextPart[] = []; + let lastIndex = 0; + let match: RegExpExecArray | null; + + while ((match = regex.exec(input)) !== null) { + if (match.index > lastIndex) { + parts.push({ type: "text", text: input.slice(lastIndex, match.index) }); + } + parts.push({ type: "link", text: match[1], href: match[2] }); + lastIndex = match.index + match[0].length; + } + + if (lastIndex < input.length) { + parts.push({ type: "text", text: input.slice(lastIndex) }); + } + + return parts; +} diff --git a/content/services/ai-agents.mdx b/content/services/ai-agents.mdx index 5510768..0aed5ad 100644 --- a/content/services/ai-agents.mdx +++ b/content/services/ai-agents.mdx @@ -38,7 +38,7 @@ relatedExpertise: - backend-development - ai-security faqs: - - question: "What's the difference between an AI agent and a chatbot?" + - question: "What is the difference between an AI agent and a chatbot?" answer: "Chatbots respond to queries. Agents take action. An AI agent can research information, update databases, send emails, schedule meetings, and execute multi-step workflows autonomously—not just suggest what you should do." - question: "How do you ensure AI agents are safe in production?" answer: "We implement multiple safety layers: action constraints that limit what agents can do, sandboxed execution environments, approval workflows for sensitive actions, comprehensive logging, and rollback capabilities when things go wrong." @@ -46,6 +46,8 @@ faqs: answer: "Yes. Our engineers specialize in building integration layers that connect modern AI capabilities with existing enterprise systems—even those without modern APIs." - question: "How long until we have a working agent?" answer: "Most clients see a working prototype within the first week. Production deployment typically takes 2-4 weeks, depending on the complexity of your workflows and integration requirements." + - question: "What kind of tasks are best suited for AI agents?" + answer: "AI agents excel at tasks that are repetitive but require judgment—research and data gathering, document processing, customer inquiry routing, lead qualification, and multi-system workflows. If a task involves multiple steps, uses several tools, and currently requires human decision-making at each stage, it's a strong candidate for an AI agent." cta: title: "Ready to Deploy AI Agents?" description: "Talk to our team about automating your complex workflows with AI agents. We'll show you what's possible—and what's production-ready today." diff --git a/content/services/ai-engineering.mdx b/content/services/ai-engineering.mdx index bae6c9b..8eb4d1b 100644 --- a/content/services/ai-engineering.mdx +++ b/content/services/ai-engineering.mdx @@ -1,6 +1,6 @@ --- title: "AI Engineering Services" -headline: "AI Engineering Services" +headline: "Enterprise AI Engineering" headlineAccent: "Production-Ready AI Systems" tagline: "Build, deploy, and scale reliable AI systems." description: | @@ -19,7 +19,7 @@ capabilities: description: "Implement CI/CD for models, automated evaluation, versioning, monitoring, and rollback strategies." icon: "code" - title: "AI Application Development" - description: "Embed AI capabilities into web, mobile, and backend systems — search, recommendations, copilots, automation, and analytics." + description: "Embed AI into web, mobile, and backend systems — from semantic search to personalized recommendations and real-time decision engines." icon: "smartphone" - title: "AI System Monitoring & Optimization" description: "Track model accuracy, latency, cost, drift, and reliability in production environments." @@ -62,25 +62,26 @@ process: - number: 4 title: "Monitoring & Continuous Improvement" description: "Deploying with monitoring, evaluation, and optimization systems in place." +useCasesSubtitle: "Real-world applications we help teams build and scale" useCases: - icon: "search" title: "Intelligent Search & Recommendations" - description: "AI-powered search and recommendation systems" + description: "Hybrid search combining keyword and vector retrieval, with ranking models that learn from user behavior" - icon: "brain" title: "AI Copilots & Productivity Tools" - description: "Internal AI assistants and workflow automation" + description: "Domain-specific assistants that accelerate workflows, answer questions from internal knowledge, and automate repetitive tasks" - icon: "chart" title: "Predictive Analytics & Forecasting" - description: "Data-driven predictions and business intelligence" + description: "Demand forecasting, churn prediction, and resource optimization models that inform business decisions" - icon: "document" title: "Document Processing & Extraction" - description: "Information extraction and document understanding" + description: "Automated extraction, classification, and summarization for contracts, invoices, and unstructured data" - icon: "shield" title: "Fraud Detection & Anomaly Detection" - description: "Real-time anomaly detection and risk assessment" + description: "Scoring models that identify suspicious patterns in transactions, logins, and user behavior" - icon: "users" title: "Conversational AI & Automation" - description: "Chatbots and conversational workflow automation" + description: "Customer-facing chatbots and voice agents with context retention and multi-turn dialogue capabilities" whyChoose: reasons: - "Strong focus on production AI, not prototypes" @@ -131,13 +132,13 @@ faqs: - question: "What's the difference between AI engineering and AI consulting?" answer: "AI engineering focuses on building and operating AI systems in production, while consulting focuses on strategy and recommendations. We are engineering-focused." - question: "Do you work with existing AI systems?" - answer: "Yes. We help modernize, optimize, secure, and scale existing AI and ML systems, including legacy deployments." + answer: "Absolutely. We specialize in modernizing legacy ML infrastructure, optimizing model performance, and bringing security and observability to systems already in production." - question: "Can you support LLM-based applications?" - answer: "Yes. We build, integrate, deploy, and operate LLM-powered systems, including copilots, search, and automation tools." + answer: "LLM integration is a core strength. We build retrieval-augmented generation (RAG) systems, fine-tune models for domain-specific tasks, and deploy LLM-powered features with proper guardrails and cost controls." - question: "Do you provide post-deployment support?" - answer: "Yes. We offer ongoing monitoring, optimization, and operational support for AI systems in production." + answer: "Production is where our work truly begins. We provide ongoing monitoring, performance optimization, incident response, and continuous model improvement as your system evolves." - question: "Do you work with startups and enterprises?" - answer: "Yes. We support both startups building AI-first products and enterprises integrating AI into existing systems with compliance requirements." + answer: "Both. Startups benefit from our speed and pragmatic architecture decisions. Enterprises trust us to navigate compliance, security reviews, and integration with existing infrastructure." cta: title: "Talk to Our AI Engineering Team" description: "Discuss your AI system requirements, existing infrastructure, or production challenges with our engineering team. Let's build reliable AI systems together." @@ -148,10 +149,8 @@ seo: description: "Premium AI engineering services for production AI systems. Model development, MLOps, data pipelines, and AI application development from experienced engineers." --- -## Get Started With Procedure +## Your AI System, Built for Production -Whether you need AI system architecture, model development, MLOps, or AI application integration — we're here to help. +Most AI projects fail between prototype and production. We bridge that gap with engineering discipline — reliable data pipelines, observable model serving, and infrastructure that scales with your business. -**→ [Schedule a call with our AI engineering team](/contact-us)** - -This is AI engineering for production reliability, security, and business impact. +**→ [Talk to an AI engineer](/contact-us)** diff --git a/content/services/dotnet-development.mdx b/content/services/dotnet-development.mdx new file mode 100644 index 0000000..83a7a18 --- /dev/null +++ b/content/services/dotnet-development.mdx @@ -0,0 +1,202 @@ +--- +title: ".NET Development Services" +headline: "Custom .NET Development Services for Mission-Critical Systems" +tagline: "Production-grade .NET applications that scale, integrate cleanly, and stay maintainable for years. Certified engineers who work as your team, not a detached vendor." +description: "We design and build production-grade .NET applications that scale under real-world load, integrate cleanly with enterprise ecosystems, and remain maintainable over years, not just initial release cycles." +capabilities: + - title: "Custom .NET Application Development" + description: "Enterprise-grade web applications, APIs, and [backend systems](/services/backend-development) using ASP.NET Core, C#, and Entity Framework. Architected for security and long-term maintainability." + icon: "api" + - title: ".NET Modernization & Migration" + description: "Migrate from .NET Framework 4.x to .NET 8 without production downtime. Incremental strategies, including strangler fig and containerization, to reduce risk while unlocking modern performance." + icon: "workflow" + - title: ".NET Microservices Architecture" + description: "Distributed .NET systems with clear service boundaries, independent deployments, and built-in resilience. Monolith decomposition done right." + icon: "layers" + - title: "Cloud-Native .NET Development" + description: "[Cloud-native .NET applications](/services/cloud) for Azure, AWS, or GCP. Infrastructure-as-code, CI/CD pipelines, and observability baked in from day one." + icon: "cloud" + - title: ".NET Performance Optimization" + description: "Diagnose and fix performance bottlenecks in existing .NET applications. Memory profiling, query optimization, caching strategies, async tuning." + icon: "chart" + - title: ".NET Consulting & Advisory" + description: "Architectural reviews, codebase assessments, and technical direction from engineers with production experience. Validate decisions before major investments." + icon: "building" +technologies: + - .NET 8 + - ASP.NET Core + - C# + - Entity Framework Core + - Azure + - SQL Server + - PostgreSQL + - Redis + - Docker + - Kubernetes + - MediatR + - Serilog +relatedExpertise: + - backend-development + - cloud + - kubernetes +whoWeWorkWith: + title: "When to Choose a .NET Development Company" + audiences: + - icon: "rocket" + title: "For Founders & Business Leaders" + subtitle: "Consider .NET when:" + bullets: + - "Enterprise customers will scrutinize your product for security and compliance" + - "You need predictable scaling without re-architecting every 18 months" + - "You want a stack with 20+ years of Microsoft backing and a large talent pool" + - "Your target customers already run on Microsoft ecosystems" + - icon: "code" + title: "For CTOs & Engineering Leaders" + subtitle: ".NET makes sense when:" + bullets: + - "Strong typing and compile-time safety matter for complex domain logic" + - "Performance requirements demand a runtime that competes with Go and Rust" + - "Your team values mature tooling: Visual Studio, Rider, robust debugging" + - "LTS releases align with your maintenance and upgrade cycles" + - icon: "target" + title: "For Product Leaders & Platform Owners" + subtitle: ".NET is strategic when:" + bullets: + - "Building internal platforms that need to outlast individual team tenures" + - "Backward compatibility matters: .NET's migration path is predictable" + - "You need enterprise integrations (Active Directory, SQL Server, Dynamics)" + - "Multiple deployment targets: cloud, on-prem, hybrid, edge" + commonApplications: + title: "What Teams Build With .NET" + items: + - title: "Enterprise Applications" + description: "ERP extensions, CRM integrations, workflow automation, internal tools" + - title: "API Backends" + description: "High-throughput REST APIs, gRPC services, event-driven systems" + - title: "[SaaS Platforms](/industries/saas)" + description: "Multi-tenant apps, subscription billing, customer portals" + - title: "Legacy Modernization" + description: ".NET Framework migrations, monolith decomposition" + - title: "Regulated Industries" + description: "[Financial services](/industries/financial-services), [healthcare](/industries/healthcare), compliance-heavy systems" + - title: "Real-Time & Background Processing" + description: "SignalR dashboards, scheduled jobs, queue-based workers, ETL pipelines" +philosophy: + title: "Our Philosophy on Building with .NET" + subtitle: "We approach .NET development as long-term system engineering, not short-term delivery. Every decision is made with production reality, system ownership, and future evolution in mind." + blocks: + - title: "Product Thinking Over Task Execution" + description: "We design .NET systems around business workflows, operational constraints, and real usage patterns, not feature lists or time-based delivery. The goal is systems that work in practice, not just on paper." + - title: "Ownership Is the Default" + description: "Every .NET system is built so internal teams can understand, operate, and extend it independently. Clear architecture decisions, documentation, and test coverage are treated as core deliverables, not optional extras." + - title: "A High, Non-Negotiable Quality Bar" + description: "Quality is not a phase. Code health, testability, and maintainability are enforced consistently so .NET systems remain reliable as they grow in complexity and usage." + - title: "Designed for Long-Term Evolution" + description: "We build .NET systems to evolve over years, not sprints. Architecture choices favor clarity, extensibility, and predictable change over short-term convenience." + - title: "Intentional Technical Debt Management" + description: "Trade-offs are made consciously, documented clearly, and revisited deliberately. Technical debt is managed as a strategic decision, not an accident that compounds over time." +architecture: + title: "How We Architect .NET Applications" + subtitle: "Clean Architecture principles: business logic independent of frameworks, databases, and delivery mechanisms. When .NET 10 arrives or you swap databases, your core code doesn't change." + layers: + - name: "Domain Layer" + description: "Encapsulates core business rules and domain models in stable logic, isolated from frameworks and infrastructure." + - name: "Application Layer" + description: "Coordinates use cases and workflows through clear boundaries without embedding technical concerns." + - name: "Infrastructure Layer" + description: "Contains external dependencies such as databases, messaging, and integrations behind abstractions." + - name: "API Layer" + description: "Acts as a thin interface for external communication, keeping business logic independent of delivery mechanisms." +engagementModels: + title: "Engagement Models" + subtitle: "Designed to align ownership, risk, and delivery responsibility with your product's needs." + models: + - title: "Dedicated .NET Team" + description: "Full-time engineers as an extension of your organization. Shared accountability for outcomes. Teams typically range from 2–8 engineers based on project scope." + bestFor: "Long-lived products, complex platforms, scaling capacity" + - title: "Project-Based .NET Delivery" + description: "Fixed-scope engagement with clear deliverables, timeline, and budget." + bestFor: "Modernization, MVP development, defined feature builds" + - title: ".NET Consulting & Advisory" + description: "Targeted expertise: architecture reviews, migration planning, performance audits." + bestFor: "Technical due diligence, pre-investment validation" + - title: "Ongoing .NET Product Ownership" + description: "Full responsibility for your .NET product: development, maintenance, operations." + bestFor: "Non-technical founders, teams focused on business growth" +howItWorks: + title: "How .NET Engagements Work at Procedure" + subtitle: "From first conversation to production code. Here's what to expect. No surprises, no long procurement cycles." + steps: + - title: "Discovery Call" + description: "A 30-minute conversation with a .NET engineer, not a sales rep. We'll understand your system, goals, and constraints. You'll get an honest assessment of whether we're the right fit. No obligation." + - title: "Technical Scoping" + description: "We define the engagement scope together: architecture review, team requirements, timeline, and deliverables. For larger projects, we conduct a paid discovery sprint (1–2 weeks) to validate assumptions before committing to a full build." + - title: "Pilot Engagement" + description: "Start small. A 2–4 week pilot on real code lets both sides evaluate fit: technical quality, communication rhythm, and working style. No long-term contract required at this stage." + - title: "Team Deployment & Delivery" + description: "Your dedicated .NET engineers are onboarded into your tools, workflows, and standups. Weekly syncs, transparent progress tracking, and direct access to your team. No layers of project managers in between." + - title: "Scale or Exit: Your Call" + description: "Every milestone leaves you with working, documented software. Scale the team up as confidence grows, or wrap up cleanly. You own 100% of the code, documentation, and infrastructure. Always." + closingNote: "Most teams go from first call to deployed engineers in under 3 weeks." +riskReversal: + title: "Why Teams Choose Procedure for .NET Development" + subtitle: "We're not the cheapest option. We're the option when the system matters too much to get wrong." + variant: "split" + leftTriggers: + - "Legacy .NET Framework system blocking cloud migration" + - "Previous vendor left code but no documentation" + - "Internal team stretched, need senior .NET expertise fast" + - "Architecture needs validation before major investment" + - "Need a partner who owns outcomes, not just tasks" + rightBlocks: + - title: "Discovery first" + description: "Honest assessment before you commit" + - title: "Pilot before expansion" + description: "Start contained, prove fit on real code" + - title: "No vendor lock-in" + description: "You own 100% of code, docs, and infra" + - title: "Transparent communication" + description: "Weekly syncs, full visibility" + - title: "Exit-ready always" + description: "Every milestone leaves working software" + closingNote: "No long-term contract required to begin. Discovery and pilot engagements available as starting points." +ctaTestimonial: + name: "Engineering Leader" + role: "Director of Engineering" + company: "Fintech Platform" + quote: "Modernized our legacy .NET platform while feature delivery continued. The team handled risk thoughtfully and operated like senior engineers embedded in our organization." +faqs: + - question: "What is the typical cost of .NET development services?" + answer: ".NET development services at Procedure.tech range from $5,000 for discovery engagements to $500,000+ for full enterprise applications, depending on scope and engagement model. Discovery engagements typically run $5,000–$15,000 over 1–2 weeks. MVPs range from $50,000–$150,000 over 6–12 weeks. Full enterprise applications range from $150,000–$500,000+ over 4–12 months. Dedicated teams run $25,000–$80,000/month. We provide detailed estimates after discovery with no hidden fees." + - question: "How long does .NET development take?" + answer: "Timelines depend on complexity. Simple APIs take 4–6 weeks. MVPs typically take 8–12 weeks. Full enterprise applications require 4–8 months for initial release. Legacy modernization projects span 3–12 months depending on system size. We work in sprints with continuous releases so you see progress early." + - question: "Do you offer .NET staff augmentation?" + answer: "Yes. Senior .NET engineers who integrate with your team: your repos, your processes, your standups. This works well when you have technical leadership but need capacity. For teams needing technical direction, a dedicated team model is usually a better fit." + - question: "What industries have you built .NET systems for?" + answer: "Financial services (payment processing, trading, regulatory reporting), healthcare (patient portals, claims, HIPAA-compliant systems), SaaS (multi-tenant platforms, subscription billing), and enterprise (internal tools, workflow automation, ERP integrations). Our engineers adapt quickly to new domains." + - question: "How do you compare to other .NET development companies?" + answer: "We're not the largest or cheapest. What's different: senior engineers only, no juniors learning on your project. Ownership mindset, outcomes, not just features. Transparent communication, you always know what's happening. No lock-in, you own everything, easy to leave. US + India presence, timezone coverage and cost efficiency." + - question: "Is .NET suitable for enterprise and mission-critical systems?" + answer: "Yes. .NET is widely adopted for enterprise applications due to its strong type system, high-throughput runtime, and long-term Microsoft support (LTS releases supported 3+ years). The ecosystem includes mature libraries for security, data access, and enterprise integration. Organizations like Stack Overflow and major financial institutions run core systems on .NET." + - question: "Can modern .NET applications scale with growing demand?" + answer: "Yes. Modern .NET is designed for both horizontal and vertical scaling. ASP.NET Core handles high request volumes with minimal overhead through async-first architecture. The platform supports microservices patterns, container orchestration, and distributed systems. Performance benchmarks place .NET among the fastest web frameworks available." + - question: "Do you work with existing or legacy .NET systems?" + answer: "Yes. Much of our work involves existing systems: modernizing .NET Framework applications, refactoring monoliths, or migrating to modern runtimes. We use incremental approaches like strangler fig patterns so teams continue shipping features while modernization happens in parallel, without large-scale rewrites." + - question: "How risky is migrating from .NET Framework to modern .NET?" + answer: "What reduces risk: Microsoft's .NET Upgrade Assistant automates mechanical work. Incremental strategies (strangler fig) let you migrate piece by piece. Side-by-side deployment allows old and new to coexist. What increases risk: heavy Windows-specific APIs (WCF, legacy WinForms), tightly coupled architecture, and missing tests (we often write tests first). Most migrations complete in 3–6 months without production incidents." + - question: "Is .NET suitable for cloud-native and cross-platform applications?" + answer: "Yes. Modern .NET runs on Windows, Linux, and macOS, and is commonly deployed in Docker containers orchestrated through Kubernetes. Azure, AWS, and GCP all offer first-class .NET support. The runtime is optimized for containerized environments with fast startup and low memory footprint." + - question: "How do you ensure long-term maintainability of .NET systems?" + answer: "Through Clean Architecture principles that separate business logic from infrastructure, intentional dependency management with abstractions, and comprehensive test coverage. Documentation includes architecture decisions, deployment procedures, and runbooks. The goal is systems that internal teams can understand and extend independently." + - question: "When should teams seek external .NET expertise?" + answer: "When systems become business-critical and architectural decisions carry long-term consequences. When modernization is needed but internal teams lack bandwidth. When previous development left fragile code needing stabilization. Or when stakeholders need independent validation before committing resources." +cta: + title: "Ready to Discuss Your .NET Project?" + description: "Talk directly with engineers, not sales. We'll assess fit and give honest next steps." + buttonText: "Request a .NET Architecture Review" + buttonLink: "/contact-us" + supportingNote: "No obligation. No pressure. Clear technical direction." +seo: + title: ".NET Development Services | C# & ASP.NET Core Experts | Procedure.tech" + description: "Enterprise .NET development services from Procedure. Scalable .NET applications, legacy .NET modernization, .NET microservices architecture, Azure deployment. Production-grade systems for fintech and healthcare." +--- diff --git a/lib/content-types.ts b/lib/content-types.ts index 5b61f8a..cafb4c9 100644 --- a/lib/content-types.ts +++ b/lib/content-types.ts @@ -34,6 +34,7 @@ export interface CTABlock { description?: string; buttonText: string; buttonLink: string; + supportingNote?: string; } // ============================================================================= @@ -137,12 +138,19 @@ export interface ExpertiseFrontmatter extends BaseFrontmatter { cta?: CTABlock; // Optional frontend-specific sections whoWeWorkWith?: { + title?: string; audiences: Array<{ icon: string; title: string; - description: string; + subtitle?: string; + description?: string; + bullets?: string[]; }>; closingStatement?: string; + commonApplications?: { + title: string; + items: string[]; + }; }; process?: Array<{ number: number; @@ -150,18 +158,31 @@ export interface ExpertiseFrontmatter extends BaseFrontmatter { description: string; icon?: string; }>; + useCasesSubtitle?: string; useCases?: Array<{ icon: string; title: string; description: string; }>; whyChoose?: { + title?: string; + subtitle?: string; + reasonsTitle?: string; reasons: string[]; + outcomesTitle?: string; outcomes: Array<{ value: string; label: string; }>; }; + philosophy?: { + title: string; + subtitle?: string; + blocks: Array<{ + title: string; + description: string; + }>; + }; qualityMatters?: { costs: Array<{ title: string; @@ -171,6 +192,54 @@ export interface ExpertiseFrontmatter extends BaseFrontmatter { title: string; }>; }; + architecture?: { + title: string; + subtitle?: string; + diagramSrc?: string; + layers: Array<{ + name: string; + description: string; + }>; + }; + howItWorks?: { + title?: string; + subtitle?: string; + steps: Array<{ + title: string; + description: string; + }>; + closingNote?: string; + }; + engagementModels?: { + title?: string; + subtitle?: string; + models: Array<{ + title: string; + description: string; + bestFor: string; + }>; + }; + riskReversal?: { + title?: string; + subtitle?: string; + items?: Array<{ + title: string; + description: string; + }>; + closingNote?: string; + variant?: "grid" | "split"; + leftTriggers?: string[]; + rightBlocks?: Array<{ + title: string; + description: string; + }>; + }; + ctaTestimonial?: { + name: string; + role: string; + company: string; + quote: string; + }; } // ============================================================================= diff --git a/lib/content.ts b/lib/content.ts index 6a24b08..368ee5e 100644 --- a/lib/content.ts +++ b/lib/content.ts @@ -537,6 +537,9 @@ export interface ExpertisePageForListing { cta: { headline: string; description: string; + buttonText?: string; + buttonLink?: string; + supportingNote?: string; }; faqs: Array<{ question: string; @@ -549,12 +552,19 @@ export interface ExpertisePageForListing { quote: string; }>; whoWeWorkWith?: { + title?: string; audiences: Array<{ icon: string; title: string; - description: string; + subtitle?: string; + description?: string; + bullets?: string[]; }>; closingStatement?: string; + commonApplications?: { + title: string; + items: (string | { title: string; description: string })[]; + }; }; process?: Array<{ number: number; @@ -562,18 +572,31 @@ export interface ExpertisePageForListing { description: string; icon?: string; }>; + useCasesSubtitle?: string; useCases?: Array<{ icon: string; title: string; description: string; }>; whyChoose?: { + title?: string; + subtitle?: string; + reasonsTitle?: string; reasons: string[]; + outcomesTitle?: string; outcomes: Array<{ value: string; label: string; }>; }; + philosophy?: { + title: string; + subtitle?: string; + blocks: Array<{ + title: string; + description: string; + }>; + }; qualityMatters?: { costs: Array<{ title: string; @@ -583,6 +606,54 @@ export interface ExpertisePageForListing { title: string; }>; }; + architecture?: { + title: string; + subtitle?: string; + diagramSrc?: string; + layers: Array<{ + name: string; + description: string; + }>; + }; + howItWorks?: { + title?: string; + subtitle?: string; + steps: Array<{ + title: string; + description: string; + }>; + closingNote?: string; + }; + engagementModels?: { + title?: string; + subtitle?: string; + models: Array<{ + title: string; + description: string; + bestFor: string; + }>; + }; + riskReversal?: { + title?: string; + subtitle?: string; + items?: Array<{ + title: string; + description: string; + }>; + closingNote?: string; + variant?: "grid" | "split"; + leftTriggers?: string[]; + rightBlocks?: Array<{ + title: string; + description: string; + }>; + }; + ctaTestimonial?: { + name: string; + role: string; + company: string; + quote: string; + }; relatedExpertise: string[]; } @@ -677,14 +748,24 @@ export function getExpertiseForListing( description: frontmatter.cta?.description || "Talk to our engineers about your project.", + buttonText: frontmatter.cta?.buttonText, + buttonLink: frontmatter.cta?.buttonLink, + supportingNote: frontmatter.cta?.supportingNote, }, faqs: frontmatter.faqs || [], testimonials: frontmatter.testimonials || [], whoWeWorkWith: frontmatter.whoWeWorkWith, process: frontmatter.process, + useCasesSubtitle: frontmatter.useCasesSubtitle, useCases: frontmatter.useCases, whyChoose: frontmatter.whyChoose, + philosophy: frontmatter.philosophy, qualityMatters: frontmatter.qualityMatters, + architecture: frontmatter.architecture, + howItWorks: frontmatter.howItWorks, + engagementModels: frontmatter.engagementModels, + riskReversal: frontmatter.riskReversal, + ctaTestimonial: frontmatter.ctaTestimonial, relatedExpertise: frontmatter.relatedExpertise || [], }; }