Files
tm-landing/app/marketing/layout.tsx
T
AmirReza Jamali a78726303a refactor(seo): Improve page metadata and HTML semantics
This commit updates the page metadata (title and description) from the default Next.js placeholders to be descriptive of the Opp lens application, improving SEO.

Additionally, it refactors the HTML structure for better semantics and accessibility:
- Replaced generic `div` and fragment tags with appropriate semantic elements like `main`, `article`, `li`, and `small`.
- Corrected the heading hierarchy for better document structure.
- Fixed image source paths by making them absolute to prevent broken images.
2025-10-26 10:38:46 +03:30

179 lines
4.8 KiB
TypeScript

import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import Image from "next/image";
import Link from "next/link";
import { ToastContainer, Zoom } from "react-toastify";
import FooterForm from "../_components/FooterForm";
import "../globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Opp lens - AI-Powered Tender Management",
description:
"Democratizing Tender Access for SMEs with AI-powered tender discovery and preparation.",
icons: {
icon: "/fav-icon.svg",
},
};
function ContactInfo({
icon,
contact,
href,
ariaLabel,
contactIconSrc,
}: {
icon: string;
contact: string;
href?: string;
ariaLabel: string;
contactIconSrc?: string;
}) {
return (
<li className="flex gap-3 my-3 text-white">
<Image
src={icon}
width={24}
height={24}
alt=""
aria-hidden="true"
/>
{href ? (
<a
href={href}
className="cursor-pointer min-w-fit"
aria-label={ariaLabel}>
{contact}
</a>
) : (
<p className="flex gap-3">
{!!contactIconSrc && (
<Image
src={contactIconSrc}
width={20}
height={20}
alt="flag"
/>
)}
{contact}
</p>
)}
</li>
);
}
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const contactInfo = [
{
icon: "/Message.svg",
contact: "info@opplens.com",
href: "mailto:info@opplens.com",
ariaLabel: "Email us at info@opplens.com",
},
{
icon: "/Phone.svg",
contact: "(+46) - 761581526",
href: "tel:+46761581526",
ariaLabel: "Call us at +46 761581526",
},
{
icon: "/Location.svg",
contact: "Stockholm, Sweden",
ariaLabel: "Our location in Stockholm, Sweden",
contactIconSrc: "/sweden.svg",
},
];
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased flex flex-col min-h-screen bg-[url('/header-bg.svg')] bg-top-right bg-no-repeat bg-contain`}>
<header className="flex justify-center pt-8 md:justify-between items-center pb-4 container px-4 py-4 m-auto">
<Link
href="/"
aria-label="Opp lens home">
<Image
src="/main-logo.svg"
alt="Opp lens logo"
width={180}
height={30}
priority
/>
</Link>
</header>
<ToastContainer
position="top-right"
autoClose={2500}
theme={"colored"}
transition={Zoom}
hideProgressBar
newestOnTop
closeOnClick
pauseOnFocusLoss
draggable
pauseOnHover
/>
<main className="container px-4 py-4 m-auto flex-grow">{children}</main>
<footer className="relative h-full bg-[url('/footer-bg.svg')] bg-cover bg-no-repeat mt-96">
<div
className="absolute w-full -top-[355px] md:-top-72 h-[600px] z-[-10] bg-[url('/bottom-bg.svg')] bg-contain bg-no-repeat bg-right"
aria-hidden="true"
/>
<FooterForm />
<div className="relative z-10 container px-4 py-4 m-auto flex flex-col justify-center items-center mt-96 ">
<div className="flex justify-between flex-col md:flex-row gap-14 w-full md:w-1/2">
<div className="flex flex-col gap-10">
<Image
src={"/footer-logo.svg"}
alt="Opp lens logo"
width={180}
height={30}
priority
/>
<div>
<p className="text-white my-2">
Democratizing Tender Access for SMEs.
</p>
<small className="text-white my-2">
© 2025 Opplens.com by PBL Partners AB. All Rights Reserved.
</small>
</div>
</div>
<address className="not-italic">
<ul>
{contactInfo.map((contact, index) => (
<ContactInfo
key={index}
icon={contact.icon}
contact={contact.contact}
href={contact.href}
ariaLabel={contact.ariaLabel}
contactIconSrc={contact.contactIconSrc}
/>
))}
</ul>
</address>
</div>
</div>
</footer>
</body>
</html>
);
}