feat: build initial landing page
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.
This commit is contained in:
+7
-17
@@ -4,23 +4,13 @@
|
||||
--background: #ffffff;
|
||||
--foreground: #171717;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
@theme {
|
||||
--background: #171717;
|
||||
--foreground: #ffffff;
|
||||
--gray-primary: #666;
|
||||
--primary: #0164ff;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #ededed;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
.gradient-text {
|
||||
@apply text-transparent bg-clip-text bg-[radial-gradient(circle,rgba(1,100,255,1)_0%,rgba(111,255,255,1)_100%)] w-fit text-6xl font-extrabold;
|
||||
}
|
||||
|
||||
+252
-91
@@ -1,103 +1,264 @@
|
||||
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="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
|
||||
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={180}
|
||||
height={38}
|
||||
priority
|
||||
/>
|
||||
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
|
||||
<li className="mb-2 tracking-[-.01em]">
|
||||
Get started by editing{" "}
|
||||
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
|
||||
app/page.tsx
|
||||
</code>
|
||||
.
|
||||
</li>
|
||||
<li className="tracking-[-.01em]">
|
||||
Save and see your changes instantly.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
||||
<a
|
||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
Deploy now
|
||||
</a>
|
||||
<a
|
||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read our docs
|
||||
</a>
|
||||
<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="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<footer className="mt-14">
|
||||
<div className="flex justify-center items-center border-t pt-5 border-gray-300">
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/file.svg"
|
||||
alt="File icon"
|
||||
width={16}
|
||||
height={16}
|
||||
src="/main-logo.svg"
|
||||
alt="Opp lens logo"
|
||||
width={180}
|
||||
height={30}
|
||||
/>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/window.svg"
|
||||
alt="Window icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Examples
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/globe.svg"
|
||||
alt="Globe icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Go to nextjs.org →
|
||||
</a>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user