diff --git a/apps/web/app/(base-org)/developers/verifications/page.tsx b/apps/web/app/(base-org)/developers/verifications/page.tsx
new file mode 100644
index 00000000000..8bfafbd05be
--- /dev/null
+++ b/apps/web/app/(base-org)/developers/verifications/page.tsx
@@ -0,0 +1,79 @@
+import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types';
+import Container from 'apps/web/src/components/base-org/Container';
+import Title from 'apps/web/src/components/base-org/typography/Title';
+import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
+import { ButtonWithLinkAndEventLogging } from 'apps/web/src/components/Button/ButtonWithLinkAndEventLogging';
+import { CtaBanner } from 'apps/web/src/components/Developers/Shared/CtaBanner';
+import { Customers } from 'apps/web/src/components/Developers/Verifications/Customers';
+import { InfoCards } from 'apps/web/src/components/Developers/Verifications/InfoCards';
+import { ValueProps } from 'apps/web/src/components/Developers/Verifications/ValueProps';
+import verification from 'apps/web/src/components/Developers/Verifications/verification.svg';
+import Image, { StaticImageData } from 'next/image';
+
+export default async function Verifications() {
+ return (
+
+
+ {/* Header */}
+
+
+
+
+ Verifications
+
+
+
+ Identify your high-quality users
+
+
+ Identify your high-quality users
+
+
+ Verifications is the link that lets you verify over 500,000+ connected wallets and
+ Coinbase accounts of specific attributes.
+
+
+
+
+ Start building
+
+
+
+
+
+
+
+
+ Get started
+
+ }
+ />
+
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Shared/Card.tsx b/apps/web/src/components/Developers/Shared/Card.tsx
new file mode 100644
index 00000000000..737893495cb
--- /dev/null
+++ b/apps/web/src/components/Developers/Shared/Card.tsx
@@ -0,0 +1,30 @@
+import Title from 'apps/web/src/components/base-org/typography/Title';
+import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
+import { ReactNode } from 'react';
+
+type CardProps = {
+ icon: ReactNode;
+ title: string;
+ description: string;
+ iconClassName: string;
+ className?: string;
+};
+export function Card({
+ icon,
+ title,
+ description,
+ iconClassName = 'text-white',
+ className,
+}: CardProps) {
+ return (
+
+
{icon}
+
+ {title}
+
+
+ {description}
+
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Shared/CtaBanner.tsx b/apps/web/src/components/Developers/Shared/CtaBanner.tsx
new file mode 100644
index 00000000000..f88d16b692a
--- /dev/null
+++ b/apps/web/src/components/Developers/Shared/CtaBanner.tsx
@@ -0,0 +1,27 @@
+'use client';
+
+import { ReactNode } from 'react';
+import Title from 'apps/web/src/components/base-org/typography/Title';
+import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
+
+type CtaBannerProps = {
+ title: string;
+ description: string;
+ cta?: ReactNode;
+};
+
+export function CtaBanner({ title, description, cta }: CtaBannerProps) {
+ return (
+
+
+
+ {title}
+
+
+ {description}
+
+
{cta}
+
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Shared/Marquee.tsx b/apps/web/src/components/Developers/Shared/Marquee.tsx
new file mode 100644
index 00000000000..3b8a6b6aff8
--- /dev/null
+++ b/apps/web/src/components/Developers/Shared/Marquee.tsx
@@ -0,0 +1,73 @@
+import { cn } from 'base-ui/utils/cn';
+import { ComponentPropsWithoutRef } from 'react';
+
+export type MarqueeProps = ComponentPropsWithoutRef<'div'> & {
+ /**
+ * Optional CSS class name to apply custom styles
+ */
+ className?: string;
+ /**
+ * Whether to reverse the animation direction
+ * @default false
+ */
+ reverse?: boolean;
+ /**
+ * Whether to pause the animation on hover
+ * @default false
+ */
+ pauseOnHover?: boolean;
+ /**
+ * Content to be displayed in the marquee
+ */
+ children: React.ReactNode;
+ /**
+ * Whether to animate vertically instead of horizontally
+ * @default false
+ */
+ vertical?: boolean;
+ /**
+ * Number of times to repeat the content
+ * @default 4
+ */
+ repeat?: number;
+};
+
+export function Marquee({
+ className,
+ reverse = false,
+ pauseOnHover = false,
+ children,
+ vertical = false,
+ repeat = 4,
+ ...props
+}: MarqueeProps) {
+ return (
+
+ {Array(repeat)
+ .fill(0)
+ .map(() => (
+
+ {children}
+
+ ))}
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Shared/ValueProp.tsx b/apps/web/src/components/Developers/Shared/ValueProp.tsx
new file mode 100644
index 00000000000..aebe6e8aee0
--- /dev/null
+++ b/apps/web/src/components/Developers/Shared/ValueProp.tsx
@@ -0,0 +1,39 @@
+import Title from 'apps/web/src/components/base-org/typography/Title';
+import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
+import Image, { type StaticImageData } from 'next/image';
+
+export type ValuePropProps = {
+ title: string;
+ description: string;
+ icon: StaticImageData;
+};
+
+export function ValueProp({ title, description, icon }: ValuePropProps) {
+ return (
+
+
+
+
+
+ {title}
+
+
+ {description}
+
+
+
+
+
+
+
+
+ {title}
+
+
+ {description}
+
+
+
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Verifications/Customers.tsx b/apps/web/src/components/Developers/Verifications/Customers.tsx
new file mode 100644
index 00000000000..629a56eebfa
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/Customers.tsx
@@ -0,0 +1,39 @@
+import Title from 'apps/web/src/components/base-org/typography/Title';
+import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
+import { Marquee } from 'apps/web/src/components/Developers/Shared/Marquee';
+import icebreaker from 'apps/web/src/components/Developers/Verifications/icebreaker.svg';
+import deform from 'apps/web/src/components/Developers/Verifications/deform.svg';
+import gitcoin from 'apps/web/src/components/Developers/Verifications/gitcoin.svg';
+import talentProtocol from 'apps/web/src/components/Developers/Verifications/talent-protocol.svg';
+import Image, { StaticImageData } from 'next/image';
+
+export function Customers() {
+ return (
+
+
+ Powering the most consumer-friendly applications onchain.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Verifications/InfoCards.tsx b/apps/web/src/components/Developers/Verifications/InfoCards.tsx
new file mode 100644
index 00000000000..fa561a30a27
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/InfoCards.tsx
@@ -0,0 +1,62 @@
+import { Card } from 'apps/web/src/components/Developers/Shared/Card';
+import key from 'apps/web/src/components/Developers/Verifications/key.svg';
+import identityCard from 'apps/web/src/components/Developers/Verifications/identityCard.svg';
+import complianceProduct from 'apps/web/src/components/Developers/Verifications/complianceProduct.svg';
+import Image, { StaticImageData } from 'next/image';
+
+const INFO_CARDS = [
+ {
+ icon: (
+
+ ),
+ title: 'Access control',
+ description:
+ 'Implement granular access control using verified Coinbase attestations. Perfect for gating features, content, or entire applications.',
+ },
+ {
+ icon: (
+
+ ),
+ title: 'Identity verification',
+ description:
+ 'Seamlessly verify user identities without handling sensitive data. Reduce fraud and enhance security in your DeFi applications.',
+ },
+ {
+ icon: (
+
+ ),
+ title: 'Compliance & reporting',
+ description:
+ 'Build compliant applications with verifiable attestations. Perfect for KYC requirements and regulatory reporting.',
+ },
+];
+
+export function InfoCards() {
+ return (
+
+ {INFO_CARDS.map((card) => {
+ return (
+
+ );
+ })}
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Verifications/ValueProps.tsx b/apps/web/src/components/Developers/Verifications/ValueProps.tsx
new file mode 100644
index 00000000000..a2f4cbabb8e
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/ValueProps.tsx
@@ -0,0 +1,51 @@
+import { ValueProp, ValuePropProps } from 'apps/web/src/components/Developers/Shared/ValueProp';
+import coinbase from 'apps/web/src/components/Developers/Verifications/coinbase.svg';
+import globe from 'apps/web/src/components/Developers/Verifications/globe.svg';
+import coinbaseOne from 'apps/web/src/components/Developers/Verifications/coinbaseOne.svg';
+import { StaticImageData } from 'next/image';
+import Title from 'apps/web/src/components/base-org/typography/Title';
+import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
+
+const VALUE_PROPS: ValuePropProps[] = [
+ {
+ title: 'Verified Account',
+ description: 'A Coinbase user with a valid Coinbase trading account. ',
+ icon: coinbase as StaticImageData,
+ },
+ {
+ title: 'Verified Country',
+ description: 'The user’s verified country of residence on Coinbase.',
+ icon: globe as StaticImageData,
+ },
+ {
+ title: 'Verified Coinbase One',
+ description: 'A Coinbase user with an active Coinbase One membership.',
+ icon: coinbaseOne as StaticImageData,
+ },
+];
+export function ValueProps() {
+ return (
+
+
+
+ Supported attestations.{' '}
+
+ Coinbase trust with a few lines of code.
+
+
+
+
+ {VALUE_PROPS.map((item: ValuePropProps) => {
+ return (
+
+ );
+ })}
+
+
+ );
+}
diff --git a/apps/web/src/components/Developers/Verifications/coinbase.svg b/apps/web/src/components/Developers/Verifications/coinbase.svg
new file mode 100644
index 00000000000..899ba157501
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/coinbase.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/coinbaseOne.svg b/apps/web/src/components/Developers/Verifications/coinbaseOne.svg
new file mode 100644
index 00000000000..8dc8b6236cc
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/coinbaseOne.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/complianceProduct.svg b/apps/web/src/components/Developers/Verifications/complianceProduct.svg
new file mode 100644
index 00000000000..c6c0e074231
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/complianceProduct.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/deform.svg b/apps/web/src/components/Developers/Verifications/deform.svg
new file mode 100644
index 00000000000..9d801225569
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/deform.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/gitcoin.svg b/apps/web/src/components/Developers/Verifications/gitcoin.svg
new file mode 100644
index 00000000000..71301711ae6
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/gitcoin.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/globe.svg b/apps/web/src/components/Developers/Verifications/globe.svg
new file mode 100644
index 00000000000..3d0bd932459
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/globe.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/icebreaker.svg b/apps/web/src/components/Developers/Verifications/icebreaker.svg
new file mode 100644
index 00000000000..8eb959758a9
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/icebreaker.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/identityCard.svg b/apps/web/src/components/Developers/Verifications/identityCard.svg
new file mode 100644
index 00000000000..06fc4ad1d9d
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/identityCard.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/key.svg b/apps/web/src/components/Developers/Verifications/key.svg
new file mode 100644
index 00000000000..89474680454
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/key.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/talent-protocol.svg b/apps/web/src/components/Developers/Verifications/talent-protocol.svg
new file mode 100644
index 00000000000..2f9371db715
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/talent-protocol.svg
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/components/Developers/Verifications/verification.svg b/apps/web/src/components/Developers/Verifications/verification.svg
new file mode 100644
index 00000000000..c6851e11a9f
--- /dev/null
+++ b/apps/web/src/components/Developers/Verifications/verification.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/apps/web/src/components/base-org/Button/index.tsx b/apps/web/src/components/base-org/Button/index.tsx
index 928a4c1dff3..313c7b29681 100644
--- a/apps/web/src/components/base-org/Button/index.tsx
+++ b/apps/web/src/components/base-org/Button/index.tsx
@@ -10,6 +10,7 @@ export type ButtonProps = ButtonHTMLAttributes & {
variant?: ButtonVariants;
size?: ButtonSizes;
iconName?: IconProps['name'];
+ iconSize?: IconProps['width'];
roundedFull?: boolean;
fullWidth?: boolean;
};
@@ -26,6 +27,9 @@ const variantStyles: Record = {
// White outlined
[ButtonVariants.Outlined]:
'bg-transparent text-white border border-white hover:bg-white hover:text-black active:bg-[#E3E7E9]',
+
+ // Secondary Outlined
+ [ButtonVariants.SecondaryOutline]: 'bg-transparent border border-gray-muted hover:border-white',
};
const sizeStyles: Record = {
@@ -51,6 +55,7 @@ export default function Button({
variant = ButtonVariants.Primary,
size = ButtonSizes.Medium,
iconName,
+ iconSize = sizeIconRatio[size],
roundedFull = false,
className,
fullWidth = false,
@@ -82,8 +87,6 @@ export default function Button({
className,
);
- const iconSize = sizeIconRatio[size];
-
return (
{children}
diff --git a/apps/web/src/components/base-org/Button/types.ts b/apps/web/src/components/base-org/Button/types.ts
index 854cce84374..3e65cdebb97 100644
--- a/apps/web/src/components/base-org/Button/types.ts
+++ b/apps/web/src/components/base-org/Button/types.ts
@@ -2,6 +2,7 @@ export enum ButtonVariants {
Primary = 'primary',
Secondary = 'secondary',
Outlined = 'outlined',
+ SecondaryOutline = 'secondary-outline',
}
export enum ButtonSizes {
diff --git a/apps/web/tailwind.config.js b/apps/web/tailwind.config.js
index 49610ace7e6..99eef26e74b 100644
--- a/apps/web/tailwind.config.js
+++ b/apps/web/tailwind.config.js
@@ -531,6 +531,14 @@ module.exports = {
'0%': { transform: 'translateX(0)' },
'100%': { transform: 'translateX(-50%)' },
},
+ marquee: {
+ from: { transform: 'translateX(0)' },
+ to: { transform: 'translateX(calc(-100% - var(--gap)))' },
+ },
+ 'marquee-vertical': {
+ from: { transform: 'translateY(0)' },
+ to: { transform: 'translateY(calc(-100% - var(--gap)))' },
+ },
progress: {
'0%': { width: '0%' },
@@ -576,6 +584,8 @@ module.exports = {
longslide: 'longslide 2s linear infinite',
verticalSlide: 'verticalSlide 2s linear infinite',
pulsate: 'pulsate 2s linear infinite',
+ marquee: 'marquee var(--duration) linear infinite',
+ 'marquee-vertical': 'marquee-vertical var(--duration) linear infinite',
},
zIndex: {
1: '1',
diff --git a/libs/base-ui/utils/cn.ts b/libs/base-ui/utils/cn.ts
new file mode 100644
index 00000000000..9ad0df4269e
--- /dev/null
+++ b/libs/base-ui/utils/cn.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}