mirror of
https://github.com/graphql-hive/console
synced 2026-05-23 17:18:23 +00:00
Landing page improvements
This commit is contained in:
parent
ee04854e2e
commit
734647090c
4 changed files with 299 additions and 233 deletions
|
|
@ -2,7 +2,7 @@ import { ReactNode } from 'react';
|
|||
|
||||
export function HeroTitle(props: { children: ReactNode }) {
|
||||
return (
|
||||
<h1 className="mx-auto max-w-screen-lg bg-gradient-to-r from-yellow-500 via-orange-400 to-yellow-500 bg-clip-text text-center text-5xl font-semibold text-transparent dark:from-yellow-400 dark:to-orange-500 sm:text-5xl lg:text-6xl">
|
||||
<h1 className="mx-auto max-w-screen-lg bg-gradient-to-r from-yellow-500 via-orange-400 to-yellow-500 bg-clip-text text-center text-5xl font-semibold text-transparent sm:text-5xl lg:text-6xl">
|
||||
{props.children}
|
||||
</h1>
|
||||
);
|
||||
|
|
@ -10,7 +10,7 @@ export function HeroTitle(props: { children: ReactNode }) {
|
|||
|
||||
export function HeroSubtitle(props: { children: ReactNode }) {
|
||||
return (
|
||||
<p className="mx-auto mt-6 max-w-screen-sm text-center text-lg text-gray-700 dark:text-gray-200 font-light">
|
||||
<p className="mx-auto mt-6 max-w-screen-sm text-center text-lg text-gray-700 font-light">
|
||||
{props.children}
|
||||
</p>
|
||||
);
|
||||
|
|
@ -26,8 +26,10 @@ export function HeroLinks(props: { children: ReactNode }) {
|
|||
|
||||
export function Hero(props: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="w-full relative">
|
||||
<div className="my-6 py-20 px-2 sm:py-24 lg:py-32 relative">{props.children}</div>
|
||||
<div className="w-full relative overflow-hidden bg-white">
|
||||
<div className="my-6 py-20 px-2 sm:py-24 lg:py-32">
|
||||
<div className="z-10 relative">{props.children}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,12 @@
|
|||
import { ReactNode } from 'react';
|
||||
import Link from 'next/link';
|
||||
import clsx from 'clsx';
|
||||
import { BookIcon } from './book-icon';
|
||||
|
||||
const classes = {
|
||||
root: clsx('flex flex-1 flex-row gap-6 md:flex-col lg:flex-row'),
|
||||
content: clsx('flex flex-col text-black dark:text-white'),
|
||||
title: clsx('text-xl font-semibold'),
|
||||
description: clsx('text-gray-600 dark:text-gray-400'),
|
||||
};
|
||||
|
||||
export function HighlightTextLink(props: { href: string; children: ReactNode }) {
|
||||
return (
|
||||
<Link
|
||||
href={props.href}
|
||||
className="underline underline-offset-2 transition text-yellow-500 hover:text-yellow-500/75 dark:text-yellow-600 dark:hover:text-yellow-500/100"
|
||||
className="underline underline-offset-2 transition text-yellow-500 hover:text-yellow-500/75 "
|
||||
>
|
||||
{props.children}
|
||||
</Link>
|
||||
|
|
@ -32,11 +24,11 @@ export function Highlights(props: {
|
|||
return (
|
||||
<div className="container mx-auto box-border flex flex-col justify-between gap-12 md:flex-row px-6 py-12">
|
||||
{props.items.map(({ title, description, icon, documentationLink }, i) => (
|
||||
<div className={classes.root} key={i}>
|
||||
<div className="h-16 w-16 shrink-0 text-yellow-500">{icon}</div>
|
||||
<div className={classes.content}>
|
||||
<h3 className={classes.title}>{title}</h3>
|
||||
<p className={classes.description}>{description}</p>
|
||||
<div className="flex flex-1 flex-row gap-6 md:flex-col lg:flex-row" key={i}>
|
||||
<div className="lg:h-16 lg:w-16 w-12 h-12 shrink-0 text-yellow-500">{icon}</div>
|
||||
<div className="flex flex-col text-black gap-y-2">
|
||||
<h3 className="lg:text-xl text-lg font-semibold">{title}</h3>
|
||||
<p className="text-gray-600">{description}</p>
|
||||
<Link
|
||||
href={documentationLink}
|
||||
className="mt-4 group inline-flex font-semibold items-center transition hover:underline underline-offset-8 gap-x-2 text-yellow-500"
|
||||
|
|
|
|||
|
|
@ -20,13 +20,12 @@ import registryVersionControlSystemImage from '../../public/features/registry/ve
|
|||
const classes = {
|
||||
link: cn(
|
||||
'inline-block rounded-lg bg-gray-100 px-6 py-3 font-medium text-gray-600 shadow-sm hover:bg-gray-200',
|
||||
'dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700',
|
||||
),
|
||||
feature: cn('w-full', 'even:bg-gray-50 even:dark:bg-gray-900', 'odd:bg-white odd:dark:bg-black'),
|
||||
feature: cn('w-full', 'even:bg-gray-50', 'odd:bg-white'),
|
||||
root: cn('flex flex-1 flex-row gap-6 md:flex-col lg:flex-row'),
|
||||
content: cn('flex flex-col text-black dark:text-white'),
|
||||
content: cn('flex flex-col text-black'),
|
||||
title: cn('text-xl font-semibold'),
|
||||
description: cn('text-gray-600 dark:text-gray-400'),
|
||||
description: cn('text-gray-600'),
|
||||
};
|
||||
|
||||
const gradients: [string, string][] = [
|
||||
|
|
@ -103,16 +102,30 @@ function Highlight(
|
|||
{props.documentationLink ? null : (
|
||||
<div
|
||||
className={cn(
|
||||
'absolute inset-0 rounded-lg',
|
||||
'active' in props && props.active ? 'opacity-20' : 'opacity-0 hover:opacity-10',
|
||||
'absolute inset-0 lg:border-l-4 lg:border-b-0 border-b-2',
|
||||
'active' in props && props.active ? 'opacity-100' : 'opacity-0 hover:opacity-50',
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: props.startColor,
|
||||
borderColor: props.startColor,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className={classes.content}>
|
||||
<h3 className={cn(classes.title, 'text-lg')}>{props.title}</h3>
|
||||
<div
|
||||
className={cn(
|
||||
classes.content,
|
||||
'lg:w-auto w-full',
|
||||
'onClick' in props ? 'gap-y-2' : 'gap-y-4',
|
||||
)}
|
||||
>
|
||||
<h3
|
||||
className={cn(
|
||||
classes.title,
|
||||
'lg:text-lg text-base',
|
||||
'onClick' in props ? 'text-center lg:text-left' : '',
|
||||
)}
|
||||
>
|
||||
{props.title}
|
||||
</h3>
|
||||
<p
|
||||
className={cn(
|
||||
classes.description,
|
||||
|
|
@ -161,92 +174,112 @@ function Feature(props: {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className={cn(classes.feature, 'relative overflow-hidden pb-28 pt-20 sm:py-32')}>
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative">
|
||||
<div className="max-w-2xl md:mx-auto md:text-center xl:max-w-none">
|
||||
<h2
|
||||
className="text-4xl font-semibold leading-normal tracking-tight bg-clip-text text-transparent"
|
||||
style={{ backgroundImage: `linear-gradient(-70deg, ${end}, ${start})` }}
|
||||
>
|
||||
{title}
|
||||
</h2>
|
||||
<div className="mt-6 text-lg tracking-tight text-gray-600 dark:text-gray-400">
|
||||
{description}
|
||||
<div className={cn(classes.feature, 'relative overflow-hidden')}>
|
||||
<div>
|
||||
<div
|
||||
className="w-full absolute h-[1px] top-0 opacity-25"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(90deg, ${end}, ${start})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute opacity-[0.15] w-[60vw] h-[255px] -left-[200px] -top-[200px] blur-3xl"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(180deg, ${end}, ${start})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute opacity-[0.15] w-[60vw] h-[255px] -right-[200px] -top-[200px] blur-3xl"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(180deg, ${start}, ${end})`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="pb-28 pt-20 sm:py-32">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative">
|
||||
<div className="max-w-2xl md:mx-auto md:text-center xl:max-w-none">
|
||||
<h2
|
||||
className="text-4xl font-semibold leading-normal tracking-tight bg-clip-text text-transparent"
|
||||
style={{ backgroundImage: `linear-gradient(-70deg, ${end}, ${start})` }}
|
||||
>
|
||||
{title}
|
||||
</h2>
|
||||
<div className="mt-6 text-lg tracking-tight text-gray-600">{description}</div>
|
||||
{documentationLink ? (
|
||||
<div className="pt-12">
|
||||
<Link
|
||||
href={documentationLink}
|
||||
className="group inline-flex font-semibold items-center transition hover:underline underline-offset-8 gap-x-2"
|
||||
style={{
|
||||
color: start,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<BookIcon size={16} />
|
||||
</div>
|
||||
<div>Learn more</div>
|
||||
</Link>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{documentationLink ? (
|
||||
<div className="pt-12">
|
||||
<Link
|
||||
href={documentationLink}
|
||||
className="group inline-flex font-semibold items-center transition hover:underline underline-offset-8 gap-x-2"
|
||||
style={{
|
||||
color: start,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<BookIcon size={16} />
|
||||
</div>
|
||||
<div>Learn more</div>
|
||||
</Link>
|
||||
{imagelessHighlights ? (
|
||||
<div className="flex flex-col lg:flex-row justify-center mt-16 pt-10 sm:gap-y-6 md:mt-20 lg:pt-0">
|
||||
{imagelessHighlights.map((highlight, i) => (
|
||||
<Highlight {...highlight} endColor={end} startColor={start} key={i} />
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{imagelessHighlights ? (
|
||||
<div className="flex flex-col lg:flex-row justify-center mt-16 pt-10 sm:gap-y-6 md:mt-20 lg:pt-0">
|
||||
{imagelessHighlights.map((highlight, i) => (
|
||||
<Highlight {...highlight} endColor={end} startColor={start} key={i} />
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{highlights ? (
|
||||
<div className="mt-0 lg:mt-16 grid grid-cols-1 items-center gap-y-2 pt-10 sm:gap-y-6 md:mt-20 lg:grid-cols-12 lg:pt-0">
|
||||
<div className="flex overflow-x-auto pb-4 sm:mx-0 sm:overflow-visible sm:pb-0 lg:col-span-5">
|
||||
<div>
|
||||
{highlights ? (
|
||||
<div className="flex lg:flex-col lg:gap-y-12 gap-x-0 flex-row">
|
||||
{highlights.map((highlight, i) => (
|
||||
<Highlight
|
||||
{...highlight}
|
||||
endColor={end}
|
||||
startColor={start}
|
||||
key={i}
|
||||
index={i}
|
||||
active={activeHighlight === i}
|
||||
onClick={setActiveHighlight}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden lg:block" />
|
||||
<div className="lg:col-span-6">
|
||||
{highlights.map((highlight, i) => (
|
||||
<div key={i} className={cn(activeHighlight === i ? 'block' : 'hidden')}>
|
||||
<div className="relative sm:px-6 lg:hidden">
|
||||
<p className="relative mx-auto max-w-2xl text-base sm:text-center">
|
||||
{highlight.description}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="mt-10 w-[45rem] sm:w-auto lg:mt-0 lg:w-[67.8125rem] rounded-lg"
|
||||
style={{ backgroundImage: `linear-gradient(-70deg, ${end}, ${start})` }}
|
||||
>
|
||||
<div className="lg:p-12 p-4">
|
||||
<div className="rounded-xl overflow-hidden">
|
||||
<Image
|
||||
{...highlight.image}
|
||||
className="w-full"
|
||||
style={{ color: 'transparent' }}
|
||||
alt={title}
|
||||
{highlights ? (
|
||||
<div className="mt-0 lg:mt-16 grid grid-cols-1 items-center gap-y-2 pt-10 sm:gap-y-6 md:mt-20 lg:grid-cols-12 lg:pt-0">
|
||||
<div className="w-full lg:w-auto flex overflow-x-auto pb-4 sm:mx-0 sm:overflow-visible sm:pb-0 lg:col-span-5">
|
||||
<div className="w-full">
|
||||
{highlights ? (
|
||||
<div className="flex lg:flex-col lg:gap-y-12 gap-x-0 flex-row justify-evenly">
|
||||
{highlights.map((highlight, i) => (
|
||||
<Highlight
|
||||
{...highlight}
|
||||
endColor={end}
|
||||
startColor={start}
|
||||
key={i}
|
||||
index={i}
|
||||
active={activeHighlight === i}
|
||||
onClick={setActiveHighlight}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden lg:block" />
|
||||
<div className="lg:col-span-6">
|
||||
{highlights.map((highlight, i) => (
|
||||
<div key={i} className={cn(activeHighlight === i ? 'block' : 'hidden')}>
|
||||
<div className="relative sm:px-6 lg:hidden">
|
||||
<p className="relative mx-auto max-w-2xl text-base sm:text-center">
|
||||
{highlight.description}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="mt-10 w-[45rem] sm:w-auto lg:mt-0 lg:w-[67.8125rem] rounded-lg"
|
||||
style={{ backgroundImage: `linear-gradient(-70deg, ${end}, ${start})` }}
|
||||
>
|
||||
<div className="lg:p-12 p-4">
|
||||
<div className="rounded-xl overflow-hidden">
|
||||
<Image
|
||||
{...highlight.image}
|
||||
className="w-full"
|
||||
style={{ color: 'transparent' }}
|
||||
alt={title}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
@ -270,7 +303,6 @@ export function IndexPage(): ReactElement {
|
|||
className={cn(
|
||||
'inline-block rounded-lg px-6 py-3 font-medium text-white shadow-sm',
|
||||
'bg-yellow-500 hover:bg-yellow-500/75',
|
||||
'dark:bg-yellow-600 dark:hover:bg-yellow-500/100',
|
||||
)}
|
||||
>
|
||||
Start for free
|
||||
|
|
@ -287,7 +319,10 @@ export function IndexPage(): ReactElement {
|
|||
</>
|
||||
</HeroLinks>
|
||||
</Hero>
|
||||
<div className="even:bg-gray-50 even:dark:bg-gray-900">
|
||||
<div className="even:bg-gray-50 relative">
|
||||
<div>
|
||||
<div className="w-full absolute h-[1px] top-0 opacity-25 bg-gradient-to-r from-gray-300 via-gray-500 to-gray-300" />
|
||||
</div>
|
||||
<StatsList>
|
||||
<StatsItem label="Happy users" value={2.9} suffix="K" decimal />
|
||||
<StatsItem label="Registered Schemas" value={120} suffix="K" />
|
||||
|
|
@ -327,48 +362,55 @@ export function IndexPage(): ReactElement {
|
|||
]}
|
||||
gradient={0}
|
||||
/>
|
||||
<div className={cn(classes.feature, 'py-24')}>
|
||||
<h2 className="text-3xl font-semibold leading-normal tracking-tight text-center mb-12">
|
||||
Perfect fit for your GraphQL Gateway
|
||||
</h2>
|
||||
<Highlights
|
||||
items={[
|
||||
{
|
||||
title: 'Manage your Gateway',
|
||||
description: (
|
||||
<>
|
||||
Connect to{' '}
|
||||
<HighlightTextLink href="/docs/get-started/apollo-federation">
|
||||
Apollo Federation
|
||||
</HighlightTextLink>
|
||||
,{' '}
|
||||
<HighlightTextLink href="/docs/integrations/graphql-mesh">
|
||||
GraphQL Mesh
|
||||
</HighlightTextLink>
|
||||
,{' '}
|
||||
<HighlightTextLink href="/docs/integrations/schema-stitching">
|
||||
Stitching
|
||||
</HighlightTextLink>{' '}
|
||||
and more.
|
||||
</>
|
||||
),
|
||||
icon: <FiServer strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/get-started/apollo-federation',
|
||||
},
|
||||
{
|
||||
title: 'Global Edge Network',
|
||||
description: 'Access the registry from any place on earth within milliseconds.',
|
||||
icon: <FiGlobe strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/features/high-availability-cdn',
|
||||
},
|
||||
{
|
||||
title: 'Apollo GraphOS alternative',
|
||||
description: 'GraphQL Hive is a drop-in replacement for Apollo GraphOS Studio.',
|
||||
icon: <FiPackage strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/get-started/apollo-federation',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<div className={cn(classes.feature, 'relative overflow-hidden')}>
|
||||
<div>
|
||||
<div className="w-full absolute h-[1px] top-0 opacity-25 bg-gradient-to-r from-gray-300 via-gray-500 to-gray-300" />
|
||||
<div className="absolute opacity-[0.15] w-[60vw] h-[255px] -left-[200px] -top-[200px] blur-3xl bg-gradient-to-b from-gray-50 to-gray-300" />
|
||||
<div className="absolute opacity-[0.15] w-[60vw] h-[255px] -right-[200px] -top-[200px] blur-3xl bg-gradient-to-b from-gray-300 to-gray-50" />
|
||||
</div>
|
||||
<div className="py-24">
|
||||
<h2 className="text-3xl font-semibold leading-normal tracking-tight text-center mb-12 text-black">
|
||||
Perfect fit for your GraphQL Gateway
|
||||
</h2>
|
||||
<Highlights
|
||||
items={[
|
||||
{
|
||||
title: 'Manage your Gateway',
|
||||
description: (
|
||||
<>
|
||||
Connect to{' '}
|
||||
<HighlightTextLink href="/docs/get-started/apollo-federation">
|
||||
Apollo Federation
|
||||
</HighlightTextLink>
|
||||
,{' '}
|
||||
<HighlightTextLink href="/docs/integrations/graphql-mesh">
|
||||
GraphQL Mesh
|
||||
</HighlightTextLink>
|
||||
,{' '}
|
||||
<HighlightTextLink href="/docs/integrations/schema-stitching">
|
||||
Stitching
|
||||
</HighlightTextLink>{' '}
|
||||
and more.
|
||||
</>
|
||||
),
|
||||
icon: <FiServer strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/get-started/apollo-federation',
|
||||
},
|
||||
{
|
||||
title: 'Global Edge Network',
|
||||
description: 'Access the registry from any place on earth within milliseconds.',
|
||||
icon: <FiGlobe strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/features/high-availability-cdn',
|
||||
},
|
||||
{
|
||||
title: 'Apollo GraphOS alternative',
|
||||
description: 'GraphQL Hive is a drop-in replacement for Apollo GraphOS Studio.',
|
||||
icon: <FiPackage strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/get-started/apollo-federation',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Feature
|
||||
title="GraphQL Observability"
|
||||
|
|
@ -425,93 +467,125 @@ export function IndexPage(): ReactElement {
|
|||
]}
|
||||
/>
|
||||
<div
|
||||
className={cn('py-24')}
|
||||
className="relative overflow-hidden"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(-70deg, ${gradients[4][1]}, ${gradients[4][0]})`,
|
||||
}}
|
||||
>
|
||||
<div className="mx-auto max-w-lg text-center text-white">
|
||||
<h2 className="text-3xl font-semibold leading-normal tracking-tight">
|
||||
Get started today
|
||||
</h2>
|
||||
<p className="mt-4 text-lg tracking-tight">
|
||||
Start with a free Hobby plan that fits perfectly most side projects or try our Pro
|
||||
plan with 30 days trial period.
|
||||
</p>
|
||||
<a
|
||||
href="https://app.graphql-hive.com"
|
||||
className={cn(
|
||||
'text-sm rounded-md px-6 py-3 mt-12 font-medium text-black shadow-sm',
|
||||
'bg-white hover:bg-blue-50',
|
||||
'inline-flex flex-row items-center gap-2',
|
||||
)}
|
||||
>
|
||||
<FiLogIn /> Enter Hive
|
||||
</a>
|
||||
<div>
|
||||
<div className="w-full absolute h-[1px] top-0 opacity-25 bg-blue-900" />
|
||||
</div>
|
||||
<div className="py-24">
|
||||
<div className="mx-auto max-w-lg text-center text-white">
|
||||
<h2 className="text-3xl font-semibold leading-normal tracking-tight">
|
||||
Get started today
|
||||
</h2>
|
||||
<p className="mt-4 text-lg tracking-tight">
|
||||
Start with a free Hobby plan that fits perfectly most side projects or try our Pro
|
||||
plan with 30 days trial period.
|
||||
</p>
|
||||
<a
|
||||
href="https://app.graphql-hive.com"
|
||||
className={cn(
|
||||
'text-sm rounded-md px-6 py-3 mt-12 font-medium text-black shadow-sm',
|
||||
'bg-white hover:bg-blue-50',
|
||||
'inline-flex flex-row items-center gap-2',
|
||||
)}
|
||||
>
|
||||
<FiLogIn /> Enter Hive
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn(classes.feature, 'py-24')}>
|
||||
<h2 className="text-3xl font-semibold leading-normal tracking-tight text-center mb-12">
|
||||
Fits your infrastructure
|
||||
</h2>
|
||||
<Highlights
|
||||
items={[
|
||||
{
|
||||
title: 'GitHub Integration',
|
||||
description: 'Our CLI integrates smoothly with GitHub Actions / repositories.',
|
||||
icon: <FiGithub strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/integrations/ci-cd#github-check-suites',
|
||||
},
|
||||
{
|
||||
title: 'Works with every CI/CD',
|
||||
description: 'Connect GraphQL Hive CLI to CI/CD of your choice.',
|
||||
icon: <FiTruck strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/integrations/ci-cd',
|
||||
},
|
||||
{
|
||||
title: 'On-premise or Cloud',
|
||||
description:
|
||||
'GraphQL Hive is MIT licensed, you can host it on your own infrastructure.',
|
||||
icon: <FiServer strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/self-hosting/get-started',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<div className={cn(classes.feature, 'relative overflow-hidden')}>
|
||||
<div>
|
||||
<div className="w-full absolute h-[1px] top-0 opacity-25 bg-gradient-to-r from-gray-300 via-gray-500 to-gray-300" />
|
||||
<div className="absolute opacity-[0.15] w-[60vw] h-[255px] -left-[200px] -top-[200px] blur-3xl bg-gradient-to-b from-gray-600 to-gray-900" />
|
||||
<div className="absolute opacity-[0.15] w-[60vw] h-[255px] -right-[200px] -top-[200px] blur-3xl bg-gradient-to-b from-gray-900 to-gray-600" />
|
||||
</div>
|
||||
<div className="py-24">
|
||||
<h2 className="text-3xl font-semibold leading-normal tracking-tight text-center mb-12 text-black">
|
||||
Fits your infrastructure
|
||||
</h2>
|
||||
<Highlights
|
||||
items={[
|
||||
{
|
||||
title: 'GitHub Integration',
|
||||
description: 'Our CLI integrates smoothly with GitHub Actions / repositories.',
|
||||
icon: <FiGithub strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/integrations/ci-cd#github-check-suites',
|
||||
},
|
||||
{
|
||||
title: 'Works with every CI/CD',
|
||||
description: 'Connect GraphQL Hive CLI to CI/CD of your choice.',
|
||||
icon: <FiTruck strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/integrations/ci-cd',
|
||||
},
|
||||
{
|
||||
title: 'On-premise or Cloud',
|
||||
description:
|
||||
'GraphQL Hive is MIT licensed, you can host it on your own infrastructure.',
|
||||
icon: <FiServer strokeWidth={1} className="h-full w-full" />,
|
||||
documentationLink: '/docs/self-hosting/get-started',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn(classes.feature, 'py-24')}>
|
||||
<div className="container mx-auto box-border flex flex-col gap-y-24 px-6">
|
||||
<div className="text-center">
|
||||
<h2
|
||||
className="mb-6 bg-clip-text text-5xl font-semibold leading-normal text-transparent dark:text-transparent"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(-70deg, ${gradients[3][1]}, ${gradients[3][0]})`,
|
||||
}}
|
||||
>
|
||||
Open-Source
|
||||
</h2>
|
||||
<p className="text-lg leading-7 text-gray-600 dark:text-gray-400">
|
||||
Built entirely in public.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mx-auto box-border grid max-w-screen-lg grid-cols-2 gap-12 px-6">
|
||||
{[
|
||||
{
|
||||
title: 'Public roadmap',
|
||||
description: 'Influence the future of GraphQL Hive.',
|
||||
},
|
||||
{
|
||||
title: 'Cloud and Self-Hosted',
|
||||
description: 'MIT licensed, host it on your own infrastructure.',
|
||||
},
|
||||
{
|
||||
title: 'Available for free',
|
||||
description: 'Free Hobby plan that fits perfectly for most side projects.',
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
description: 'Implement your own features with our help.',
|
||||
},
|
||||
].map(renderFeatures)}
|
||||
<div className={cn(classes.feature, 'relative overflow-hidden')}>
|
||||
<div>
|
||||
<div
|
||||
className="w-full absolute h-[1px] top-0 opacity-25"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(90deg, ${gradients[3][1]}, ${gradients[3][0]})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute opacity-[0.15] w-[60vw] h-[255px] -left-[200px] -top-[200px] blur-3xl"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(180deg, ${gradients[3][0]}, ${gradients[3][1]})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute opacity-[0.15] w-[60vw] h-[255px] -right-[200px] -top-[200px] blur-3xl"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(180deg, ${gradients[3][1]}, ${gradients[3][0]})`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="py-24">
|
||||
<div className="container mx-auto box-border flex flex-col gap-y-24 px-6">
|
||||
<div className="text-center">
|
||||
<h2
|
||||
className="mb-6 bg-clip-text text-5xl font-semibold leading-normal text-transparent"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(-70deg, ${gradients[3][1]}, ${gradients[3][0]})`,
|
||||
}}
|
||||
>
|
||||
Open-Source
|
||||
</h2>
|
||||
<p className="text-lg leading-7 text-gray-600">Built entirely in public.</p>
|
||||
</div>
|
||||
<div className="mx-auto box-border grid max-w-screen-lg grid-cols-2 gap-12 px-6">
|
||||
{[
|
||||
{
|
||||
title: 'Public roadmap',
|
||||
description: 'Influence the future of GraphQL Hive.',
|
||||
},
|
||||
{
|
||||
title: 'Cloud and Self-Hosted',
|
||||
description: 'MIT licensed, host it on your own infrastructure.',
|
||||
},
|
||||
{
|
||||
title: 'Available for free',
|
||||
description: 'Free Hobby plan that fits perfectly for most side projects.',
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
description: 'Implement your own features with our help.',
|
||||
},
|
||||
].map(renderFeatures)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export function StatsItem(props: {
|
|||
}) {
|
||||
return (
|
||||
<div>
|
||||
<div className="font-bold text-5xl text-center">
|
||||
<div className="font-bold text-5xl text-center text-black">
|
||||
<CountUp
|
||||
start={0}
|
||||
end={props.value}
|
||||
|
|
@ -22,9 +22,7 @@ export function StatsItem(props: {
|
|||
/>
|
||||
{props.suffix}+
|
||||
</div>
|
||||
<div className="text-gray-600 dark:text-gray-400 uppercase font-semibold text-center">
|
||||
{props.label}
|
||||
</div>
|
||||
<div className="text-gray-600 uppercase font-semibold text-center">{props.label}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue