diff --git a/.gitignore b/.gitignore index 486d912..5d698d9 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,6 @@ next-env.d.ts # Local backups of pre-optimized GLB source models (not served) .glb-originals/ + +# Scraped demo assets +demo.artureanec.com/ diff --git a/next.config.ts b/next.config.ts index e708fa1..3121097 100644 --- a/next.config.ts +++ b/next.config.ts @@ -5,7 +5,7 @@ const nextConfig: NextConfig = { turbopack: { root: path.resolve(__dirname), }, - output: "export", + // output: "export" removed to allow server actions // Required by the How It Works 3D experience. React StrictMode double-invokes // mount/effects in dev, which tears down and re-creates the WebGL context of // the heavy 32MB scene mid-initialization — the context is lost ("THREE. @@ -15,7 +15,6 @@ const nextConfig: NextConfig = { // any other page's runtime behavior. reactStrictMode: false, images: { - unoptimized: true, formats: ["image/avif", "image/webp"], }, }; diff --git a/public/images/Aravinth.png b/public/images/Aravinth.png deleted file mode 100644 index 2f8146c..0000000 Binary files a/public/images/Aravinth.png and /dev/null differ diff --git a/public/images/Fazul.png b/public/images/Fazul.png deleted file mode 100644 index 0464aca..0000000 Binary files a/public/images/Fazul.png and /dev/null differ diff --git a/public/images/Investor.png b/public/images/Investor.png deleted file mode 100644 index 3089f76..0000000 Binary files a/public/images/Investor.png and /dev/null differ diff --git a/public/images/Parthi.png b/public/images/Parthi.png deleted file mode 100644 index c958a53..0000000 Binary files a/public/images/Parthi.png and /dev/null differ diff --git a/public/images/Suriya.png b/public/images/Suriya.png deleted file mode 100644 index 3ffd5b0..0000000 Binary files a/public/images/Suriya.png and /dev/null differ diff --git a/public/images/about-bg.png b/public/images/about-bg.png deleted file mode 100644 index 626fe75..0000000 Binary files a/public/images/about-bg.png and /dev/null differ diff --git a/public/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.png b/public/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.png deleted file mode 100644 index b74d2e9..0000000 Binary files a/public/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.png and /dev/null differ diff --git a/public/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.webp b/public/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.webp deleted file mode 100644 index 15a6a0d..0000000 Binary files a/public/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.webp and /dev/null differ diff --git a/public/images/bg-404.png b/public/images/bg-404.png deleted file mode 100644 index 34bac05..0000000 Binary files a/public/images/bg-404.png and /dev/null differ diff --git a/public/images/bg-contacts.png b/public/images/bg-contacts.png deleted file mode 100644 index 3f131e1..0000000 Binary files a/public/images/bg-contacts.png and /dev/null differ diff --git a/public/images/bg-header-1.jpg b/public/images/bg-header-1.jpg deleted file mode 100644 index 20f4cd4..0000000 Binary files a/public/images/bg-header-1.jpg and /dev/null differ diff --git a/public/images/bg-header-3.jpeg b/public/images/bg-header-3.jpeg deleted file mode 100644 index 1f326e2..0000000 Binary files a/public/images/bg-header-3.jpeg and /dev/null differ diff --git a/public/images/bg-header-3.png b/public/images/bg-header-3.png deleted file mode 100644 index 9a14267..0000000 Binary files a/public/images/bg-header-3.png and /dev/null differ diff --git a/public/images/bg-header-5.png b/public/images/bg-header-5.png deleted file mode 100644 index d7ab42a..0000000 Binary files a/public/images/bg-header-5.png and /dev/null differ diff --git a/public/images/bg-map-about.png b/public/images/bg-map-about.png deleted file mode 100644 index b2f436a..0000000 Binary files a/public/images/bg-map-about.png and /dev/null differ diff --git a/public/images/bg-map-women.png b/public/images/bg-map-women.png deleted file mode 100644 index 8974f64..0000000 Binary files a/public/images/bg-map-women.png and /dev/null differ diff --git a/public/images/bg-slide-sidebar.jpg b/public/images/bg-slide-sidebar.jpg deleted file mode 100644 index c9c185d..0000000 Binary files a/public/images/bg-slide-sidebar.jpg and /dev/null differ diff --git a/public/images/blog-post-pic-14.jpeg b/public/images/blog-post-pic-14.jpeg deleted file mode 100644 index 4e04093..0000000 Binary files a/public/images/blog-post-pic-14.jpeg and /dev/null differ diff --git a/public/images/blog-post-pic-15.png b/public/images/blog-post-pic-15.png deleted file mode 100644 index 1d9b4fa..0000000 Binary files a/public/images/blog-post-pic-15.png and /dev/null differ diff --git a/public/images/blog-post-pic-17.png b/public/images/blog-post-pic-17.png deleted file mode 100644 index d613310..0000000 Binary files a/public/images/blog-post-pic-17.png and /dev/null differ diff --git a/public/images/blog-post-pic-18-840x840.jpg b/public/images/blog-post-pic-18-840x840.jpg deleted file mode 100644 index 8ff8360..0000000 Binary files a/public/images/blog-post-pic-18-840x840.jpg and /dev/null differ diff --git a/public/images/blog-post-pic-3.jpeg b/public/images/blog-post-pic-3.jpeg deleted file mode 100644 index fb974ba..0000000 Binary files a/public/images/blog-post-pic-3.jpeg and /dev/null differ diff --git a/public/images/blog-post-pic-31.png b/public/images/blog-post-pic-31.png deleted file mode 100644 index 6ff58cc..0000000 Binary files a/public/images/blog-post-pic-31.png and /dev/null differ diff --git a/public/images/blog-post-pic-4.jpeg b/public/images/blog-post-pic-4.jpeg deleted file mode 100644 index 52c1763..0000000 Binary files a/public/images/blog-post-pic-4.jpeg and /dev/null differ diff --git a/public/images/blog-post-pic-6.jpeg b/public/images/blog-post-pic-6.jpeg deleted file mode 100644 index 5c9251f..0000000 Binary files a/public/images/blog-post-pic-6.jpeg and /dev/null differ diff --git a/public/images/blog-post-pic-8.jpeg b/public/images/blog-post-pic-8.jpeg deleted file mode 100644 index 1376b0f..0000000 Binary files a/public/images/blog-post-pic-8.jpeg and /dev/null differ diff --git a/public/images/ev-paradox.png b/public/images/ev-paradox.png deleted file mode 100644 index 15707f2..0000000 Binary files a/public/images/ev-paradox.png and /dev/null differ diff --git a/public/images/ev.jpeg b/public/images/ev.jpeg deleted file mode 100644 index 472a2a4..0000000 Binary files a/public/images/ev.jpeg and /dev/null differ diff --git a/public/images/first-mile-approach.jpg b/public/images/first-mile-approach.jpg deleted file mode 100644 index bcc7a2a..0000000 Binary files a/public/images/first-mile-approach.jpg and /dev/null differ diff --git a/public/images/home-bg-1.png b/public/images/home-bg-1.png deleted file mode 100644 index 1e7768c..0000000 Binary files a/public/images/home-bg-1.png and /dev/null differ diff --git a/public/images/home1-bg2.png b/public/images/home1-bg2.png deleted file mode 100644 index 75cbf6e..0000000 Binary files a/public/images/home1-bg2.png and /dev/null differ diff --git a/public/images/home1-slide-1.png b/public/images/home1-slide-1.png deleted file mode 100644 index 828c01f..0000000 Binary files a/public/images/home1-slide-1.png and /dev/null differ diff --git a/public/images/home1-slide-2.png b/public/images/home1-slide-2.png deleted file mode 100644 index f85c31b..0000000 Binary files a/public/images/home1-slide-2.png and /dev/null differ diff --git a/public/images/home1alt-bg-2.png b/public/images/home1alt-bg-2.png deleted file mode 100644 index ceb4d86..0000000 Binary files a/public/images/home1alt-bg-2.png and /dev/null differ diff --git a/public/images/home2-banner-1.jpg b/public/images/home2-banner-1.jpg deleted file mode 100644 index 298babc..0000000 Binary files a/public/images/home2-banner-1.jpg and /dev/null differ diff --git a/public/images/home2-banner-3.jpg b/public/images/home2-banner-3.jpg deleted file mode 100644 index 98d5f2c..0000000 Binary files a/public/images/home2-banner-3.jpg and /dev/null differ diff --git a/public/images/home2-banner-4.png b/public/images/home2-banner-4.png deleted file mode 100644 index 78acc68..0000000 Binary files a/public/images/home2-banner-4.png and /dev/null differ diff --git a/public/images/home2-banner-5 b/public/images/home2-banner-5 deleted file mode 100644 index 9d83670..0000000 Binary files a/public/images/home2-banner-5 and /dev/null differ diff --git a/public/images/home2-pic-3.png b/public/images/home2-pic-3.png deleted file mode 100644 index 215148b..0000000 Binary files a/public/images/home2-pic-3.png and /dev/null differ diff --git a/public/images/home2-slide-1.jpg b/public/images/home2-slide-1.jpg deleted file mode 100644 index fdeb71d..0000000 Binary files a/public/images/home2-slide-1.jpg and /dev/null differ diff --git a/public/images/home2-slide-2.jpg b/public/images/home2-slide-2.jpg deleted file mode 100644 index 9cda61d..0000000 Binary files a/public/images/home2-slide-2.jpg and /dev/null differ diff --git a/public/images/home2alt-bg-1.jpeg b/public/images/home2alt-bg-1.jpeg deleted file mode 100644 index 34c3fe8..0000000 Binary files a/public/images/home2alt-bg-1.jpeg and /dev/null differ diff --git a/public/images/home2alt-bg-1.jpg b/public/images/home2alt-bg-1.jpg deleted file mode 100644 index 191954d..0000000 Binary files a/public/images/home2alt-bg-1.jpg and /dev/null differ diff --git a/public/images/home3-slide-1.jpg b/public/images/home3-slide-1.jpg deleted file mode 100644 index d7e92c4..0000000 Binary files a/public/images/home3-slide-1.jpg and /dev/null differ diff --git a/public/images/home3-slide-2.jpg b/public/images/home3-slide-2.jpg deleted file mode 100644 index b2b34c6..0000000 Binary files a/public/images/home3-slide-2.jpg and /dev/null differ diff --git a/public/images/home6-banner.jpg b/public/images/home6-banner.jpg deleted file mode 100644 index 0ff26a7..0000000 Binary files a/public/images/home6-banner.jpg and /dev/null differ diff --git a/public/images/home6-slide-1.jpg b/public/images/home6-slide-1.jpg deleted file mode 100644 index 60d8cee..0000000 Binary files a/public/images/home6-slide-1.jpg and /dev/null differ diff --git a/public/images/home6-slide-2.jpg b/public/images/home6-slide-2.jpg deleted file mode 100644 index 927b864..0000000 Binary files a/public/images/home6-slide-2.jpg and /dev/null differ diff --git a/public/images/last-mile-approach.jpg b/public/images/last-mile-approach.jpg deleted file mode 100644 index dd2d904..0000000 Binary files a/public/images/last-mile-approach.jpg and /dev/null differ diff --git a/public/images/mid-mile-approach.jpg b/public/images/mid-mile-approach.jpg deleted file mode 100644 index 0bb2252..0000000 Binary files a/public/images/mid-mile-approach.jpg and /dev/null differ diff --git a/public/images/mile-1.png b/public/images/mile-1.png deleted file mode 100644 index 0287905..0000000 Binary files a/public/images/mile-1.png and /dev/null differ diff --git a/public/images/miletruth-bg.png b/public/images/miletruth-bg.png deleted file mode 100644 index 5124af5..0000000 Binary files a/public/images/miletruth-bg.png and /dev/null differ diff --git a/public/images/premium-ev-van.png b/public/images/premium-ev-van.png deleted file mode 100644 index b108f07..0000000 Binary files a/public/images/premium-ev-van.png and /dev/null differ diff --git a/public/images/tab-pic-1-solution.jpeg b/public/images/tab-pic-1-solution.jpeg deleted file mode 100644 index 3eabb7c..0000000 Binary files a/public/images/tab-pic-1-solution.jpeg and /dev/null differ diff --git a/public/images/tab-pic-1.jpeg b/public/images/tab-pic-1.jpeg deleted file mode 100644 index 2ce3559..0000000 Binary files a/public/images/tab-pic-1.jpeg and /dev/null differ diff --git a/public/images/tab-pic-2-solution.jpeg b/public/images/tab-pic-2-solution.jpeg deleted file mode 100644 index 324efc7..0000000 Binary files a/public/images/tab-pic-2-solution.jpeg and /dev/null differ diff --git a/public/images/tab-pic-2.jpeg b/public/images/tab-pic-2.jpeg deleted file mode 100644 index a9a898c..0000000 Binary files a/public/images/tab-pic-2.jpeg and /dev/null differ diff --git a/public/images/tab-pic-3-solution.jpeg b/public/images/tab-pic-3-solution.jpeg deleted file mode 100644 index b288ba8..0000000 Binary files a/public/images/tab-pic-3-solution.jpeg and /dev/null differ diff --git a/public/images/tab-pic-3.jpeg b/public/images/tab-pic-3.jpeg deleted file mode 100644 index c3f5c16..0000000 Binary files a/public/images/tab-pic-3.jpeg and /dev/null differ diff --git a/scripts/fix_preload.mjs b/scripts/fix_preload.mjs new file mode 100644 index 0000000..ef5b96b --- /dev/null +++ b/scripts/fix_preload.mjs @@ -0,0 +1,49 @@ +import fs from 'fs'; +import path from 'path'; + +const files = [ + "src/components/sections/BlogsHero.tsx", + "src/components/sections/AboutHero.tsx", + "src/components/sections/SingleBlog.tsx", + "src/components/sections/ContactsHero.tsx", + "src/components/sections/IndexHero.tsx", + "src/components/sections/SolutionsHero.tsx", + "src/components/sections/MileTruthHero.tsx", + "src/components/sections/HowItWorksHero.tsx" +]; + +for (const f of files) { + let content = fs.readFileSync(f, 'utf8'); + + const match = content.match(//); + if (match) { + const href = match[1]; + + if (!content.includes('import { preload } from "react-dom"')) { + const lastImportIndex = content.lastIndexOf('import '); + const endOfLastImport = content.indexOf('\n', lastImportIndex); + content = content.substring(0, endOfLastImport + 1) + 'import { preload } from "react-dom";\n' + content.substring(endOfLastImport + 1); + } + + content = content.replace(match[0], ''); + + // Find the default export function + const fnMatch = content.match(/export default function\s+\w+\s*\([^)]*\)\s*\{/); + if (fnMatch) { + const insertIdx = fnMatch.index + fnMatch[0].length; + content = content.substring(0, insertIdx) + `\n preload("${href}", { as: "image" });` + content.substring(insertIdx); + } else { + // try non-default export + const fnMatch2 = content.match(/export function\s+\w+\s*\([^)]*\)\s*\{/); + if (fnMatch2) { + const insertIdx = fnMatch2.index + fnMatch2[0].length; + content = content.substring(0, insertIdx) + `\n preload("${href}", { as: "image" });` + content.substring(insertIdx); + } else { + console.log("Could not find function for " + f); + } + } + + fs.writeFileSync(f, content, 'utf8'); + console.log("Fixed " + f); + } +} diff --git a/src/actions/sendEmail.ts b/src/actions/sendEmail.ts index 7dd8c78..73b9654 100644 --- a/src/actions/sendEmail.ts +++ b/src/actions/sendEmail.ts @@ -2,52 +2,61 @@ import nodemailer from "nodemailer"; -export async function sendContactEmail(data: { +interface ContactFormData { fullName: string; email: string; subject: string; message: string; -}) { +} + +export async function sendEmailAction(data: ContactFormData) { const { fullName, email, subject, message } = data; - if (!fullName || !email || !subject || !message) { - return { success: false, error: "All fields are required." }; + if (!fullName || !email || !message) { + return { success: false, error: "Name, email, and message are required." }; } + let password = process.env.SMTP_PASSWORD || ""; + if (password.startsWith('"') && password.endsWith('"')) { + password = password.slice(1, -1); + } + // Remove spaces just in case + password = password.replace(/\s+/g, ""); + const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT) || 465, - secure: true, + secure: true, auth: { user: process.env.SMTP_USER, - pass: process.env.SMTP_PASSWORD, + pass: password, }, }); try { await transporter.sendMail({ - from: `"${fullName}" <${process.env.SMTP_USER}>`, - to: process.env.CONTACT_RECEIVER, - replyTo: email, - subject: `New Contact Form Submission: ${subject}`, + from: `"${fullName}" <${process.env.SMTP_USER}>`, + to: process.env.CONTACT_RECEIVER, + replyTo: email, + subject: `New Contact Form Submission: ${subject || "No Subject"}`, html: ` -
-

New Contact Form Submission

+
+

New Contact Form Submission

Name: ${fullName}

Email: ${email}

Subject: ${subject}

Message:

-
- ${message.replace(/\n/g, "
")} +
+ ${message.replace(/\n/g, "
")}
`, }); return { success: true }; - } catch (error) { + } catch (error: any) { console.error("Email send error:", error); - const errorMessage = error instanceof Error ? error.message : "Failed to send the email. Please try again later."; - return { success: false, error: errorMessage }; + const errorMessage = error instanceof Error ? error.message : String(error); + return { success: false, error: errorMessage || "Failed to send the email. Please try again later." }; } } diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts new file mode 100644 index 0000000..d5d805a --- /dev/null +++ b/src/app/sitemap.ts @@ -0,0 +1,32 @@ +import { MetadataRoute } from "next"; +import { blogPosts, SITE_URL } from "@/data/blog"; + +export default function sitemap(): MetadataRoute.Sitemap { + const staticRoutes = [ + "", + "/about", + "/contact", + "/blog", + "/air-freight", + "/first-mile-delivery", + "/mid-mile-delivery", + "/last-mile-delivery", + "/ev-logistics", + "/strategy-optimization", + "/how-it-works", + ].map((route) => ({ + url: `${SITE_URL}${route}`, + lastModified: new Date().toISOString().split("T")[0], + changeFrequency: "weekly" as const, + priority: route === "" ? 1 : 0.8, + })); + + const postRoutes = blogPosts.map((post) => ({ + url: `${SITE_URL}/blog/${post.slug}`, + lastModified: post.date, + changeFrequency: "monthly" as const, + priority: 0.6, + })); + + return [...staticRoutes, ...postRoutes]; +} diff --git a/src/components/blog/BlogSearch.tsx b/src/components/blog/BlogSearch.tsx index f978cb3..4603901 100644 --- a/src/components/blog/BlogSearch.tsx +++ b/src/components/blog/BlogSearch.tsx @@ -65,7 +65,6 @@ export default function BlogSearch() { setOpen(true); }} onFocus={() => setOpen(true)} - aria-expanded={showPanel} aria-controls="dm-blog-search-results" />
@@ -337,8 +337,8 @@ export default function Footer() { {formStatus === "submitting" ? "Sending..." : "Send a message"} {formStatus === "success" && ( -
- Message sent successfully. +
+ Message sent successfully!
)} {formStatus === "error" && ( @@ -381,7 +381,7 @@ export default function Footer() {
- Doormile Tagline + Doormile Tagline
@@ -487,7 +487,7 @@ export default function Footer() { Privacy Policy
  • - Terms Service + Terms of Service
  • Cookie Policy diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index fc885c1..27ea8aa 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -19,8 +19,13 @@ const CURRENT_PAGE_MAP: Record = { "/how-it-works": "how-it-works", "/miletruth": "miletruth", "/solutions": "solutions", + "/about": "about", "/about-us": "about", "/blog": "blogs", + "/contact": "contact", + "/privacy-policy": "privacy-policy", + "/terms-of-service": "terms-of-service", + "/cookie-policy": "cookie-policy", }; // Mirror of header.php $current_page_aliases (lines 37-44) @@ -31,6 +36,10 @@ const CURRENT_PAGE_ALIASES: Record = { solutions: ["solutions"], about: ["about", "about-us", "women"], blogs: ["blogs"], + contact: ["contact"], + "privacy-policy": ["privacy-policy"], + "terms-of-service": ["terms-of-service"], + "cookie-policy": ["cookie-policy"], }; export default function Header() { @@ -38,7 +47,10 @@ export default function Header() { const { isMenuOpen, isSidebarOpen, toggleMenu, toggleSidebar, closeAll } = useHeaderUI(); const isHome = pathname === "/"; - const currentPage = CURRENT_PAGE_MAP[pathname] ?? ""; + let currentPage = CURRENT_PAGE_MAP[pathname] ?? ""; + if (pathname.startsWith("/blog/")) { + currentPage = "blogs"; + } // Mirror of header.php $dm_header_active (lines 45-47) const dmHeaderActive = (key: string) => @@ -409,8 +421,8 @@ export default function Header() {
    - doormile-logo - doormile-logo + doormile-logo + doormile-logo
    diff --git a/src/components/logisticsbrain/LogisticsBrainSection.tsx b/src/components/logisticsbrain/LogisticsBrainSection.tsx index c9f9f0d..c787d83 100644 --- a/src/components/logisticsbrain/LogisticsBrainSection.tsx +++ b/src/components/logisticsbrain/LogisticsBrainSection.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useRef, useState, useSyncExternalStore } from "react"; +import React, { useRef, useState, useEffect } from "react"; import dynamic from "next/dynamic"; import { motion, useMotionValue, useTransform, type MotionValue } from "framer-motion"; import gsap from "gsap"; diff --git a/src/components/map/OfficeMap.tsx b/src/components/map/OfficeMap.tsx index 471b1e7..4e557a5 100644 --- a/src/components/map/OfficeMap.tsx +++ b/src/components/map/OfficeMap.tsx @@ -228,7 +228,7 @@ export default function OfficeMap() { {OFFICE_LOCATIONS.map((office) => { const isFocused = focus?.id === office.id; - const isHovered = hoveredOfficeId === office.id; + return ( ; f // construction-time prop on , so update it imperatively here. useEffect(() => { if ("fov" in camera) { + // eslint-disable-next-line react-hooks/immutability (camera as THREE_PerspectiveCamera).fov = framing.fov; (camera as THREE_PerspectiveCamera).updateProjectionMatrix(); } diff --git a/src/components/sections/AboutHero.tsx b/src/components/sections/AboutHero.tsx index 9720d03..79d8a48 100644 --- a/src/components/sections/AboutHero.tsx +++ b/src/components/sections/AboutHero.tsx @@ -1,9 +1,11 @@ import React from "react"; +import { preload } from "react-dom"; export default function AboutHero() { + preload("/images/about-bg.webp", { as: "image" }); return ( <> - +