7 Commits

Author SHA1 Message Date
kudinDmitriyUp
70dbf05d84 Bob AI: Add service detail pages (dynamic route /services/:slug) 2026-07-03 10:46:07 +00:00
4c6ceaac59 Merge version_4_1783075093266 into main
Merge version_4_1783075093266 into main
2026-07-03 10:40:40 +00:00
kudinDmitriyUp
9abc8a390c Bob AI: Update the website with the following industrial-modern desi 2026-07-03 10:40:02 +00:00
d7d129cf24 Merge version_3_1783062879841 into main
Merge version_3_1783062879841 into main
2026-07-03 07:16:47 +00:00
kudinDmitriyUp
2344b9a08a Bob AI: Populate src/pages/BlogPage.tsx (snippet builder, 2 sections) 2026-07-03 07:16:08 +00:00
kudinDmitriyUp
7f85f3fe94 Bob AI: Add blog page 2026-07-03 07:15:32 +00:00
1d55d3f241 Merge version_2_1783062361385 into main
Merge version_2_1783062361385 into main
2026-07-03 07:08:54 +00:00
8 changed files with 86 additions and 51 deletions

View File

@@ -2,12 +2,16 @@ import { Routes, Route } from 'react-router-dom';
import Layout from './components/Layout';
import HomePage from './pages/HomePage';
import BlogPage from "@/pages/BlogPage";
import ServiceDetailPage from './pages/ServiceDetailPage';
export default function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<HomePage />} />
<Route path="/blog" element={<BlogPage />} />
</Route>
<Route path="/services/:slug" element={<ServiceDetailPage />} />
</Routes>
);
}

View File

@@ -22,7 +22,9 @@ export default function Layout() {
{
"name": "Contact",
"href": "#contact"
}
},
{ name: "Blog", href: "/blog" },
];
return (

17
src/data/services.ts Normal file
View File

@@ -0,0 +1,17 @@
export interface Service {
slug: string;
question: string;
answer: string;
body: string;
specs: Array<{ label: string; value: string }>;
}
export const services: Service[] = [
{"slug":"item-dd0sy","question":"Where is your primary service area?","answer":"We specialize in the Northern Cape mining and industrial regions, ensuring rapid local deployment.","body":"In today's crowded market, a strong brand is your most valuable asset. Our strategic brand consulting service digs deep into your company's core identity, market positioning, and target audience to uncover what truly sets you apart. We do not just look at logos and colors; we analyze your entire customer journey to ensure every touchpoint resonates with your unique value proposition.\n\nThrough a series of collaborative workshops and in-depth market research, our strategists build a comprehensive roadmap for your brand. You will receive actionable insights and a clear framework for future growth, empowering your team to communicate with confidence and consistency.","specs":[{"label":"Duration","value":"4-6 Weeks"},{"label":"Deliverable","value":"Strategy Playbook"},{"label":"Format","value":"Remote or In-person"},{"label":"Best For","value":"Rebrands and Startups"}]},
{"slug":"item-7zqu9","question":"Do you provide OEM maintenance?","answer":"Yes, we adhere strictly to OEM standards for all mechanical maintenance and repairs.","body":"Your website is the digital storefront of your business, and it needs to perform flawlessly across all devices. Our custom web development service delivers high-performance, secure, and scalable websites tailored specifically to your operational needs. We write clean, modern code that ensures lightning-fast load times and seamless user experiences, keeping your visitors engaged and driving conversions.\n\nWe specialize in integrating complex third-party APIs, custom content management systems, and robust e-commerce architectures. From the initial technical discovery phase to post-launch maintenance, our dedicated development team works closely with you to ensure your digital infrastructure is built to handle future growth and evolving market demands.","specs":[{"label":"Tech Stack","value":"React, Node.js, Python"},{"label":"Timeline","value":"8-12 Weeks"},{"label":"Support","value":"90 Days Post-launch"},{"label":"Hosting","value":"AWS or Vercel"}]},
{"slug":"item-qgrhu","question":"How do we request a project consultation?","answer":"Simply fill out our contact form below or call our office during business hours.","body":"Visibility is everything in the digital landscape. Our SEO and content optimization service is designed to elevate your search rankings and drive highly targeted organic traffic to your website. We start with a comprehensive technical audit to identify and fix underlying crawl issues, followed by deep keyword research to uncover high-intent search terms your competitors are missing.\n\nBeyond technical fixes, we revitalize your existing content and map out a strategic editorial calendar. By aligning your website's copy with proven search intent and optimizing on-page elements, we help you build sustainable, long-term authority in your industry. Watch your organic reach grow as we turn your website into a reliable lead generation engine.","specs":[{"label":"Audit Timeframe","value":"14 Days"},{"label":"Reporting","value":"Monthly Dashboard"},{"label":"Focus","value":"On-page & Technical SEO"},{"label":"Contract","value":"6-Month Minimum"}]},
];
export function findService(slug: string): Service | undefined {
return services.find((x) => x.slug === slug);
}

19
src/pages/BlogPage.tsx Normal file
View File

@@ -0,0 +1,19 @@
import Button from "@/components/ui/Button";
import HeroBackgroundSlot from "@/components/ui/HeroBackgroundSlot";
import TextAnimation from "@/components/ui/TextAnimation";
import ImageOrVideo from "@/components/ui/ImageOrVideo";
import ScrollReveal from "@/components/ui/ScrollReveal";
import AvatarGroup from "@/components/ui/AvatarGroup";
import { ArrowUpRight, Loader2 } from "lucide-react";
import GridOrCarousel from "@/components/ui/GridOrCarousel";
import { useButtonClick } from "@/hooks/useButtonClick";
import useBlogPosts from "@/hooks/useBlogPosts";
export default function BlogPage() {
return (
<>
<div data-webild-section="HeroBillboard"><section aria-label="Hero section" className="relative pt-25 pb-20 md:pt-30"><HeroBackgroundSlot /><div className="flex flex-col gap-12 md:gap-15 w-content-width mx-auto"><div className="flex flex-col items-center gap-3 text-center"><AvatarGroup avatarsSrc={["https://img.freepik.com/free-photo/portrait-successful-man-having-stubble-posing-with-broad-smile-keeping-arms-folded_171337-1267.jpg","https://img.freepik.com/free-photo/young-beautiful-woman-pink-warm-sweater-natural-look-smiling-portrait-isolated-long-hair_285396-896.jpg","https://img.freepik.com/free-photo/handsome-corporate-man-real-estate-agent-assistant-smiling-holding-hands-together-how-can-i-help-smiling-camera-standing-white-background_176420-45257.jpg"]} label="Written by our experts" className="mb-1" /><TextAnimation text="Insights & Best Practices" variant="fade-blur" gradientText={true} tag="h1" className="md:max-w-8/10 text-7xl 2xl:text-8xl leading-[1.15] font-semibold text-center text-balance" /><TextAnimation text="Stay updated with the latest industry trends, technical updates, and expert insights from the team at Record Engineering." variant="fade-blur" gradientText={false} tag="p" className="md:max-w-7/10 text-lg md:text-xl leading-snug text-balance" /><div className="flex flex-wrap justify-center gap-3 mt-2 md:mt-3"><Button text="Read Latest" href="#latest-posts" variant="primary" /><Button text="Subscribe" href="#subscribe" variant="secondary" animationDelay={0.1} /></div></div><ScrollReveal variant="slide-up" delay={0.2} className="w-full p-2 xl:p-3 2xl:p-4 card rounded overflow-hidden"><ImageOrVideo imageSrc="https://img.freepik.com/free-photo/close-up-engineer-working-blueprints_1098-18833.jpg" className="aspect-4/5 md:aspect-video" /></ScrollReveal></div></section></div>
<div data-webild-section="BlogMediaCards"><section aria-label="Blog section" className="py-20"><div className="w-content-width mx-auto flex justify-center"><Loader2 className="size-8 animate-spin text-foreground" strokeWidth={1.5} /></div></section></div>
</>
);
}

View File

@@ -10,9 +10,9 @@ export default function AboutSection(): React.JSX.Element {
<div id="about" data-section="about">
<SectionErrorBoundary name="about">
<AboutText
title="A proven partner in mining reliability. Record Engineering Pty Ltd combines local presence with technical precision to optimize lifecycle performance."
textAnimation="fade-blur"
/>
title="With a track record of over 60 years as a support services company in the mining industry, we make sure our performance always exceeds expectations. We are an agile company that adapts to the changing and challenging needs of our clients. We foster a culture of discipline, detail and dynamic determination that attracts high-performing employees and results in masterful delivery. Over the years, Record Engineering has grown considerably and evolved into a key player in the mining sector, becoming a leading supplier to numerous Original Equipment Manufacturers (OEMs) and major mining operations. In Kathu and the Northern Cape we operate primarily as an engineering services provider for mining machinery and direct project management at mining plants. Our engineering service spans assembly, rebuilds and component change-outs across all mining machinery — including yellow machines and telehandlers — as well as equipment sales, maintenance and plant-design-based support. Additional support is available through our fleet and mining rental range. With a high-quality, mine-ready fleet, this is a cost-effective solution to meet our clients' fleet requirements during repair and rehabilitation."
textAnimation="fade-blur"
/>
</SectionErrorBoundary>
</div>
);

View File

@@ -10,59 +10,21 @@ export default function HeroSection(): React.JSX.Element {
<div id="hero" data-section="hero">
<SectionErrorBoundary name="hero">
<HeroSplitVerticalMarquee
tag="Since 2012"
title="Engineering Excellence in the Northern Cape"
description="Trusted project management, OEM maintenance, and lifecycle contracts for mining and heavy industry. Providing reliable regional engineering solutions."
primaryButton={{
tag="Record Engineering (Pty) Ltd"
title="Engineering Excellence in the Heart of the Northern Cape"
description="Over 60 years of trusted support services to the mining industry. Project Management OEM Maintenance • Life Cycle Contracts"
primaryButton={{
text: "Explore Our Services",
href: "#services",
}}
secondaryButton={{
secondaryButton={{
text: "Contact Us",
href: "#contact",
}}
leftItems={[
{
imageSrc: "http://img.b2bpic.net/free-photo/old-weathered-house-with-mountain-range-background_53876-47060.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/computer-display-empty-facility-used-upgrading-solar-plant-machinery_482257-118310.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/aerial-view-front-end-loader-moving-soil-quarry_1308-190385.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/architecture-plan-blueprint-layout-work-concept_53876-124260.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/view-city-bridge-with-train-london_23-2149437440.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/businessman-working-desk_23-2147653318.jpg",
},
]}
rightItems={[
{
imageSrc: "http://img.b2bpic.net/free-photo/male-jeweler-working-shop_23-2150914170.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/grey-concrete-building-with-multiple-windows_250224-252.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/technician-optimizing-energy-supply-solar-panel-manufacturing-plant_482257-120594.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/abstract-city-building-shadows_23-2149283224.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/business-plan-corporate-development-process_53876-124514.jpg",
},
{
imageSrc: "http://img.b2bpic.net/free-photo/agricultural-silo_146671-19121.jpg",
},
]}
textAnimation="slide-up"
/>
leftItems={[{"imageSrc":"https://images.unsplash.com/photo-1578593172074-a669ea40f372?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1541888087525-0718006d81f5?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1504307651254-35680f356dfd?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581092160562-40aa08e78837?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581091226825-a6a2a5aee158?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581092335397-9583eb92d232?q=80&w=2070&auto=format&fit=crop"}]}
rightItems={[{"imageSrc":"https://images.unsplash.com/photo-1581092580497-e0d23cbdf1dc?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581092162384-8987c1d64718?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581091226033-d5c48150dbaa?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581092795360-fd1ca04f0952?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581092160607-ee22621dd758?q=80&w=2070&auto=format&fit=crop"},{"imageSrc":"https://images.unsplash.com/photo-1581092583537-20d51b4b4f1b?q=80&w=2070&auto=format&fit=crop"}]}
textAnimation="slide-up"
/>
</SectionErrorBoundary>
</div>
);

View File

@@ -0,0 +1,30 @@
import { useParams, Link, Navigate } from 'react-router-dom';
import { findService } from '@/data/services';
export default function ServiceDetailPage() {
const { slug } = useParams<{ slug: string }>();
const service = slug ? findService(slug) : undefined;
if (!service) return <Navigate to="/services" replace />;
return (
<div className="flex flex-col min-h-screen bg-background text-foreground">
<main className="flex-grow pt-24">
<div className="w-content-width mx-auto py-16 flex flex-col gap-8">
<Link to="/services" className="text-sm opacity-60 hover:opacity-100 w-fit"> Back to Services</Link>
<div className="flex flex-col gap-4 max-w-3xl">
<h1 className="text-5xl font-bold">{service.question}</h1>
{service.body && <div className="text-base leading-relaxed opacity-80 whitespace-pre-line">{service.body}</div>}
</div>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{service.answer != null && (<div className="flex flex-col"><span className="text-xs uppercase tracking-wide opacity-50">Answer</span><span className="text-base">{String(service.answer)}</span></div>)}
</div>
{Array.isArray(service.specs) && service.specs.length > 0 && (
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 border-t border-foreground/10 pt-6">
{service.specs.map((s, i) => (<div key={i} className="flex flex-col"><span className="text-xs uppercase tracking-wide opacity-50">{s.label}</span><span className="text-base">{s.value}</span></div>))}
</div>
)}
</div>
</main>
</div>
);
}

View File

@@ -6,4 +6,5 @@ export interface Route {
export const routes: Route[] = [
{ path: '/', label: 'Home', pageFile: 'HomePage' },
{ path: '/blog', label: 'Blog', pageFile: 'BlogPage' },
];