cd471695b7
This commit introduces the first version of the Opp lens landing page, replacing the default Next.js starter content. The new page is designed to attract SMEs by showcasing the AI-powered tender management platform. It includes several key sections: - A hero section with a clear value proposition. - Sections detailing the problem, how the platform works, its features, and its benefits. - A call-to-action form for users to sign up for early access. - A comprehensive footer with contact and social media links. Key changes include: - **`app/page.tsx`**: Completely rewritten to build the landing page structure and content. - **`app/globals.css`**: Updated with a new dark theme, custom brand colors, and a gradient text utility class for headings. - **Dependencies**: Added `axios` to handle the early access form submission. - **SEO**: Implemented detailed metadata for improved search engine visibility.
265 lines
7.3 KiB
TypeScript
265 lines
7.3 KiB
TypeScript
import { Metadata } from "next";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Opp lens - AI-Powered Tender Management for SMEs | Win More Tenders",
|
|
description:
|
|
"Automated tender management platform for SMEs. Find tailored tenders, automate document handling, and get real-time alerts. Win more opportunities with less effort.",
|
|
keywords:
|
|
"tender management, AI tender search, SME tenders, public procurement, automated bidding, tender alerts",
|
|
authors: [{ name: "PBL Partners AB" }],
|
|
openGraph: {
|
|
title: "Opp lens - AI-Powered Tender Management",
|
|
description: "Win more tenders automatically with our AI-powered platform",
|
|
type: "website",
|
|
locale: "en_US",
|
|
siteName: "Opp lens",
|
|
},
|
|
icons: {
|
|
icon: "/fav-icon.svg",
|
|
},
|
|
};
|
|
|
|
export default function Home() {
|
|
const centerFrameItems = [
|
|
{
|
|
header: 200,
|
|
text: "Users",
|
|
description: `Lacking the time, dedicated staff, and
|
|
expertise to constantly monitor the market
|
|
and prepare high-quality bids.`,
|
|
},
|
|
{
|
|
header: 520,
|
|
text: "Contracts",
|
|
description: `Navigating complex requirements and
|
|
processes designed for large corporations
|
|
with dedicated tender departments.`,
|
|
},
|
|
{
|
|
header: 1500,
|
|
text: "Tenders",
|
|
description: `Did you know 68% of SMEs in Sweden
|
|
rarely or never win public tenders? It's time
|
|
to change that.`,
|
|
},
|
|
];
|
|
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",
|
|
},
|
|
];
|
|
return (
|
|
<div className="container px-4 py-4 m-auto">
|
|
<header className="flex justify-between items-center border-b md:border-none border-gray-300 pb-4">
|
|
<Link
|
|
href="/"
|
|
aria-label="Opp lens home">
|
|
<Image
|
|
src="/main-logo.svg"
|
|
alt="Opp lens logo"
|
|
width={180}
|
|
height={30}
|
|
priority
|
|
/>
|
|
</Link>
|
|
<div className="flex gap-5 items-center">
|
|
<nav
|
|
className="hidden md:flex"
|
|
aria-label="Main navigation">
|
|
<HeaderButtons />
|
|
</nav>
|
|
<label
|
|
htmlFor="language"
|
|
className="sr-only">
|
|
Select language
|
|
</label>
|
|
<select
|
|
name="language"
|
|
id="language"
|
|
aria-label="Language selector">
|
|
<option value="en">English</option>
|
|
</select>
|
|
</div>
|
|
</header>
|
|
<nav
|
|
className="block md:hidden"
|
|
aria-label="Mobile navigation">
|
|
<HeaderButtons />
|
|
</nav>
|
|
<main className="mt-8 flex flex-col justify-center items-center gap-14">
|
|
<section
|
|
className="flex"
|
|
aria-labelledby="hero-heading">
|
|
<div className="flex flex-col">
|
|
<h1
|
|
className="gradient-text md:!text-left md:!text-8xl md:mb-10"
|
|
id="hero-heading">
|
|
AI-Powered
|
|
</h1>
|
|
<Image
|
|
className="block md:hidden"
|
|
src={"/images/mobile.png"}
|
|
alt="Opp lens platform interface on mobile device"
|
|
width={520}
|
|
height={280}
|
|
priority
|
|
/>
|
|
<div className="w-full flex flex-col gap-6 text-xl">
|
|
<h2 className="text-(--primary) font-bold text-5xl md:!mb-10">
|
|
Tender Management
|
|
</h2>
|
|
<h3 className="font-bold">Win more tenders, automatically!</h3>
|
|
<p className="text-(--gray-primary)">
|
|
Our platform finds tenders tailored to your business, automates
|
|
document handling, and sends real-time alerts. Win more
|
|
opportunities with less effort and zero manual search.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<Image
|
|
className="hidden md:block"
|
|
src={"/images/mobile.png"}
|
|
alt="Opp lens platform interface on desktop"
|
|
width={550}
|
|
height={480}
|
|
priority
|
|
/>
|
|
</section>
|
|
<section
|
|
className="flex flex-col gap-4 text-center md:flex-row"
|
|
aria-labelledby="statistics-heading">
|
|
<h2
|
|
id="statistics-heading"
|
|
className="sr-only">
|
|
Platform Statistics
|
|
</h2>
|
|
{centerFrameItems.map((item, index) => (
|
|
<CenterFrame
|
|
key={index}
|
|
header={item.header}
|
|
text={item.text}
|
|
description={item.description}
|
|
/>
|
|
))}
|
|
</section>
|
|
</main>
|
|
<footer className="mt-14">
|
|
<div className="flex justify-center items-center border-t pt-5 border-gray-300">
|
|
<Image
|
|
src="/main-logo.svg"
|
|
alt="Opp lens logo"
|
|
width={180}
|
|
height={30}
|
|
/>
|
|
</div>
|
|
<address className="md:flex md:justify-evenly w-full mt-14 px-5 not-italic">
|
|
{contactInfo.map((item) => (
|
|
<ContactInfo
|
|
key={item.contact}
|
|
contact={item.contact}
|
|
href={item.href}
|
|
icon={item.icon}
|
|
ariaLabel={item.ariaLabel}
|
|
/>
|
|
))}
|
|
</address>
|
|
<div className="flex justify-center items-center">
|
|
<p className="text-center text-(--gray-primary) mt-5 leading-10">
|
|
Stockholm, Sweden © 2025 Opplens.com by PBL Partners AB. All Rights
|
|
Reserved. Democratizing Tender Access for SMEs.
|
|
</p>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function HeaderButtons() {
|
|
return (
|
|
<div className="flex justify-between items-center gap-5 mt-4 md:mt-0">
|
|
<Link
|
|
href={"/contact-us"}
|
|
className="text-(--primary)">
|
|
Contact us
|
|
</Link>
|
|
<Link
|
|
href={"/login"}
|
|
className="bg-(--primary) text-white px-12 py-3 rounded-full">
|
|
Login
|
|
</Link>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function CenterFrame({
|
|
header,
|
|
text,
|
|
description,
|
|
}: {
|
|
header: number;
|
|
text: string;
|
|
description: string;
|
|
}) {
|
|
return (
|
|
<article className="flex flex-col justify-center items-center gap-4">
|
|
<p
|
|
className="gradient-text"
|
|
aria-label={`${header} ${text}`}>
|
|
<strong>{header}</strong>
|
|
</p>
|
|
<h3 className="text-2xl font-semibold">{text}</h3>
|
|
<p className="text-(--gray-primary)">{description}</p>
|
|
</article>
|
|
);
|
|
}
|
|
|
|
function ContactInfo({
|
|
icon,
|
|
contact,
|
|
href,
|
|
ariaLabel,
|
|
}: {
|
|
icon: string;
|
|
contact: string;
|
|
href?: string;
|
|
ariaLabel: string;
|
|
}) {
|
|
return (
|
|
<div className="flex gap-3 my-3">
|
|
<Image
|
|
src={icon}
|
|
width={24}
|
|
height={24}
|
|
alt=""
|
|
aria-hidden="true"
|
|
/>
|
|
{href ? (
|
|
<a
|
|
href={href}
|
|
className="cursor-pointer"
|
|
aria-label={ariaLabel}>
|
|
{contact}
|
|
</a>
|
|
) : (
|
|
<p>{contact}</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|