Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c160a7a
feat(landing): rebuild homepage as persona manifesto — card beat high…
0xkkonrad Aug 12, 2026
50b3b7f
fix(landing): apply review round — marquee word lists own the strips,…
0xkkonrad Aug 13, 2026
2336937
Merge remote-tracking branch 'origin/dev' into feat/lp-refresh
0xkkonrad Aug 13, 2026
1360e9e
feat(landing): rebuild the homepage as the approved v3 fold order
0xkkonrad Aug 13, 2026
26fb7dd
fix(landing): make the door fold's card tilt actually apply
0xkkonrad Aug 13, 2026
54c1c97
feat(landing): put brand marks on the problem cards
0xkkonrad Aug 13, 2026
9e1d308
feat(landing): send the homepage's own words somewhere
0xkkonrad Aug 13, 2026
2f60cbf
feat(landing): swap in Konrad's card art, cut the door fold's body
0xkkonrad Aug 13, 2026
c73c6d4
feat(landing): link the partner logos, calm the link styling
0xkkonrad Aug 13, 2026
3b2ae4e
feat(landing): continue each FAQ into its article, right-align learn …
0xkkonrad Aug 13, 2026
ad7a9e4
refactor(landing): make the problem-card marks vector
0xkkonrad Aug 13, 2026
e7a97d5
fix(landing): stop the hover lift clipping a logo tile's top border
0xkkonrad Aug 13, 2026
a9fb1b1
fix(landing): give the country lockups the partner-tile treatment
0xkkonrad Aug 14, 2026
d93758c
Merge pull request #2692 from peanutprotocol/fix/qrpay-lockup-house-t…
0xkkonrad Aug 14, 2026
7408986
fix(landing): drop the settles footnote, rename footer Jobs to Career
0xkkonrad Aug 14, 2026
cb10001
fix(landing): qr-pay lockups — original flags, marks straight on the …
0xkkonrad Aug 14, 2026
993777d
feat(landing): compliance disclaimer under the door-fold CTA
0xkkonrad Aug 14, 2026
9e0e69d
fix(landing): keep the hero CTA inside the first fold on laptop viewp…
0xkkonrad Aug 18, 2026
4c31ed6
fix(landing): scale the hero mascot with the artwork on short viewports
0xkkonrad Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions redirects.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@
"destination": "/",
"permanent": true
},
{
"source": "/lp/card",
"destination": "/shhhhh",
"permanent": true
},
{
"source": "/sh",
"destination": "/card",
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate-valid-links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function main() {
// Static pages
lines.push('## Static Pages')
lines.push('')
for (const p of ['/', '/careers', '/exchange', '/privacy', '/terms', '/lp/card']) {
for (const p of ['/', '/careers', '/exchange', '/privacy', '/terms']) {
lines.push(`- \`${p}\``)
}
lines.push('')
Expand Down
2 changes: 1 addition & 1 deletion scripts/ping-indexnow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async function getAllPaths(): Promise<string[]> {
const { SUPPORTED_LOCALES } = await import('../src/i18n/types')
const { listContentSlugs } = await import('../src/lib/content')

const paths: string[] = ['/', '/lp/card', '/careers', '/exchange', '/privacy', '/terms']
const paths: string[] = ['/', '/shhhhh', '/careers', '/exchange', '/privacy', '/terms']

for (const locale of SUPPORTED_LOCALES) {
for (const country of Object.keys(COUNTRIES_SEO)) {
Expand Down
2 changes: 1 addition & 1 deletion scripts/verify-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function discoverRoutes(): Set<string> {
const routes = new Set<string>()

// Static pages
for (const p of ['/', '/careers', '/exchange', '/privacy', '/terms', '/lp/card']) {
for (const p of ['/', '/careers', '/exchange', '/privacy', '/terms']) {
routes.add(p)
}

Expand Down
867 changes: 0 additions & 867 deletions src/app/lp/card/CardLandingPage.tsx

This file was deleted.

25 changes: 0 additions & 25 deletions src/app/lp/card/page.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/app/robots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export default function robots(): MetadataRoute.Robots {
'/privacy',
'/terms',
'/exchange',
'/lp/card',
// SEO routes (all locale-prefixed)
...SUPPORTED_LOCALES.map((l) => `/${l}/`),
],
Expand Down
23 changes: 4 additions & 19 deletions src/app/shhhhh/ShhhhhLandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import posthog from 'posthog-js'
import { useTranslations } from 'next-intl'
import { Button } from '@/components/0_Bruddle/Button'
import { Marquee } from '@/components/LandingPage'
import { ScarcityCounter } from '@/components/LandingPage/ScarcityCounter'
import { useAuth } from '@/context/authContext'
import { PixelatedCardFace } from '@/components/Card/share-asset/PixelatedCardFace'
import { inflateWaitlistPosition } from '@/components/Card/doorTally.utils'
Expand Down Expand Up @@ -68,24 +69,6 @@ const badges: Array<{ code: string; name: string; src: string }> = [
const ctaButtonClassName =
'!w-auto bg-white px-7 py-3 text-base font-extrabold hover:bg-white/90 md:px-9 md:py-8 md:text-xl'

function ScarcityCounter() {
const t = useTranslations('shhhhh.hero')
const [count, setCount] = useState(21)
useEffect(() => {
const timer = setTimeout(() => setCount(20), 2500)
return () => clearTimeout(timer)
}, [])
return (
<motion.span
className="mx-1 inline-block whitespace-nowrap bg-n-1 px-2 py-0.5 text-[0.92em] font-extraBlack uppercase tracking-wider text-primary-1"
animate={count === 20 ? { scale: [1, 1.18, 1] } : {}}
transition={{ duration: 0.5, ease: 'easeOut' }}
>
{t('onlyCount', { count })}
</motion.span>
)
}

function StickyShhhhhCTA({ onClick }: { onClick: () => void }) {
const t = useTranslations('shhhhh.hero')
const [visible, setVisible] = useState(false)
Expand Down Expand Up @@ -302,7 +285,9 @@ export default function ShhhhhLandingPage() {
{t('hero.tagline')}
</p>
<p className="font-roboto-flex mt-6 max-w-xl text-xl leading-relaxed md:text-2xl">
{t.rich('hero.body', { counter: () => <ScarcityCounter /> })}
{t.rich('hero.body', {
counter: () => <ScarcityCounter label={(count) => t('hero.onlyCount', { count })} />,
})}
</p>
{isJoined ? (
<div className="mt-8 flex justify-center md:justify-start">
Expand Down
2 changes: 1 addition & 1 deletion src/app/shhhhh/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ShhhhhLandingPage from './ShhhhhLandingPage'
export const metadata = generateMeta({
title: 'Shhhhh. | The peanut card is out, quietly.',
description:
'A non-custodial card accepted at over 150 million Visa-accepting merchants. We are letting beta users in slowly — about 20 a week.',
'A non-custodial card accepted at over 150 million Visa-accepting merchants. We are letting beta users in slowly — about 50 a week.',
keywords: 'peanut card, non-custodial card, visa-accepting merchants, closed beta, stablecoins',
canonical: '/shhhhh',
})
Expand Down
6 changes: 3 additions & 3 deletions src/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ async function generateSitemap(): Promise<MetadataRoute.Sitemap> {
// Homepage
{ path: '', priority: 1.0, changeFrequency: 'weekly' },

// Product pages
{ path: '/lp/card', priority: 0.9, changeFrequency: 'weekly' },

// Public pages
{ path: '/careers', priority: 0.7, changeFrequency: 'monthly' },
{ path: '/exchange', priority: 0.7, changeFrequency: 'weekly' },
// The only card landing URL left — /lp/card is a 308 to it, so the
// target has to be listed.
{ path: '/shhhhh', priority: 0.7, changeFrequency: 'weekly' },

// Legal — the bare /privacy and /terms are redirects; list the real URLs.
{ path: '/en/privacy', priority: 0.5, changeFrequency: 'yearly' },
Expand Down
2 changes: 1 addition & 1 deletion src/assets/icons/pix-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading