feat(landing): add researchers trust band
This commit is contained in:
parent
5c866585de
commit
507f4018d6
|
|
@ -9,6 +9,7 @@ import {
|
|||
getHeroTimelineItems,
|
||||
getLandingMetrics,
|
||||
TRUSTED_COMPANIES,
|
||||
TRUSTED_RESEARCH_INSTITUTIONS,
|
||||
} from '~/lib/landing-data'
|
||||
|
||||
type LocaleParams = { locale?: string }
|
||||
|
|
@ -27,7 +28,11 @@ export default async function Home({
|
|||
return (
|
||||
<>
|
||||
<LandingHero items={heroItems} />
|
||||
<TrustedBy companies={TRUSTED_COMPANIES} metrics={metrics} />
|
||||
<TrustedBy
|
||||
companies={TRUSTED_COMPANIES}
|
||||
researchers={TRUSTED_RESEARCH_INSTITUTIONS}
|
||||
metrics={metrics}
|
||||
/>
|
||||
<Features discoverSources={DISCOVER_FALLBACK} />
|
||||
{/* <ViewsShowcase /> */}
|
||||
{/* <Audience /> */}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import type { LandingMetrics, TrustedCompany } from '~/lib/landing-data'
|
|||
|
||||
type TrustedByProps = {
|
||||
companies: TrustedCompany[]
|
||||
researchers: TrustedCompany[]
|
||||
metrics: LandingMetrics
|
||||
}
|
||||
|
||||
|
|
@ -18,6 +19,7 @@ const formatCompact = (value: number) => compactFormatter.format(value)
|
|||
|
||||
export const TrustedBy: Component<TrustedByProps> = ({
|
||||
companies,
|
||||
researchers,
|
||||
metrics,
|
||||
}) => {
|
||||
const trustedT = useTranslations('landing.trustedBy')
|
||||
|
|
@ -34,34 +36,36 @@ export const TrustedBy: Component<TrustedByProps> = ({
|
|||
},
|
||||
]
|
||||
|
||||
const renderTrustRow = (items: TrustedCompany[], eyebrow: string) => (
|
||||
<div className="flex flex-col items-center gap-5 text-center">
|
||||
<p className="text-[11px] font-medium uppercase tracking-[0.28em] text-accent/90">
|
||||
{eyebrow}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap items-center justify-center gap-x-8 gap-y-4">
|
||||
{items.map((item) => (
|
||||
<div key={item.name} className="inline-flex items-center gap-2.5">
|
||||
<div className="flex size-8 items-center justify-center rounded-full bg-background-secondary p-1">
|
||||
<img
|
||||
src={`https://icons.folo.is/${item.host}`}
|
||||
alt={item.name}
|
||||
className="size-full rounded-full object-cover grayscale"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
<span className="text-sm font-medium text-text">{item.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<section className="mx-auto mt-14 w-full max-w-[var(--container-max-width-2xl)] px-4 md:mt-16 lg:mt-20">
|
||||
<div className="flex flex-col gap-16">
|
||||
<div className="flex flex-col items-center gap-5 text-center">
|
||||
<p className="text-[11px] font-medium uppercase tracking-[0.28em] text-accent/90">
|
||||
{trustedT('eyebrow')}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap items-center justify-center gap-x-8 gap-y-4">
|
||||
{companies.map((company) => (
|
||||
<div
|
||||
key={company.name}
|
||||
className="inline-flex items-center gap-2.5"
|
||||
>
|
||||
<div className="flex size-8 items-center justify-center rounded-full bg-background-secondary p-1">
|
||||
<img
|
||||
src={`https://icons.folo.is/${company.host}`}
|
||||
alt={company.name}
|
||||
className="size-full rounded-full object-cover grayscale"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
<span className="text-sm font-medium text-text">
|
||||
{company.name}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex flex-col gap-8">
|
||||
{renderTrustRow(companies, trustedT('eyebrow'))}
|
||||
{renderTrustRow(researchers, trustedT('researchersEyebrow'))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center gap-4 text-center">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { TRUSTED_RESEARCH_INSTITUTIONS } from './landing-data'
|
||||
|
||||
describe('TRUSTED_RESEARCH_INSTITUTIONS', () => {
|
||||
it('keeps the QS-sorted top 10 institutions stable', () => {
|
||||
expect(TRUSTED_RESEARCH_INSTITUTIONS).toHaveLength(10)
|
||||
expect(TRUSTED_RESEARCH_INSTITUTIONS.map((item) => item.name)).toEqual([
|
||||
'MIT',
|
||||
'Stanford',
|
||||
'Oxford',
|
||||
'Harvard',
|
||||
'Cambridge',
|
||||
'NUS',
|
||||
'UCL',
|
||||
'NTU Singapore',
|
||||
'Peking University',
|
||||
'UPenn',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
@ -343,6 +343,19 @@ export const TRUSTED_COMPANIES: TrustedCompany[] = [
|
|||
{ name: 'NVIDIA', host: 'nvidia.com', users: 4 },
|
||||
]
|
||||
|
||||
export const TRUSTED_RESEARCH_INSTITUTIONS: TrustedCompany[] = [
|
||||
{ name: 'MIT', host: 'mit.edu', users: 1 },
|
||||
{ name: 'Stanford', host: 'stanford.edu', users: 2 },
|
||||
{ name: 'Oxford', host: 'ox.ac.uk', users: 1 },
|
||||
{ name: 'Harvard', host: 'harvard.edu', users: 4 },
|
||||
{ name: 'Cambridge', host: 'cam.ac.uk', users: 1 },
|
||||
{ name: 'NUS', host: 'nus.edu.sg', users: 11 },
|
||||
{ name: 'UCL', host: 'ucl.ac.uk', users: 2 },
|
||||
{ name: 'NTU Singapore', host: 'ntu.edu.sg', users: 6 },
|
||||
{ name: 'Peking University', host: 'pku.edu.cn', users: 41 },
|
||||
{ name: 'UPenn', host: 'upenn.edu', users: 5 },
|
||||
]
|
||||
|
||||
const LANDING_METRICS_FALLBACK: LandingMetrics = {
|
||||
feeds: 1267577,
|
||||
entries: 300849952,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
},
|
||||
"trustedBy": {
|
||||
"eyebrow": "Trusted by teams at",
|
||||
"researchersEyebrow": "Trusted by researchers at",
|
||||
"headline": "Teams already using Folo.",
|
||||
"body": "We sampled production work-email registrations to find the companies that have already started reading with Folo."
|
||||
},
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
},
|
||||
"trustedBy": {
|
||||
"eyebrow": "導入が進むチーム",
|
||||
"researchersEyebrow": "導入が進む研究者",
|
||||
"headline": "すでに Folo を使うチームがあります。",
|
||||
"body": "本番環境の業務用メール登録サンプルをもとに、Folo を使い始めている企業を抽出しました。"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
},
|
||||
"trustedBy": {
|
||||
"eyebrow": "已被这些团队采用",
|
||||
"researchersEyebrow": "已被这些研究者采用",
|
||||
"headline": "已经有团队在用 Folo。",
|
||||
"body": "我们基于生产环境中的工作邮箱注册样本,整理出了这些已经开始使用 Folo 的公司。"
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue