Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
fd98754
fix(website): scroll the document instead of a nested container
heyradcode Aug 9, 2026
c52e699
refactor(website): extract a real design token layer
heyradcode Aug 9, 2026
492f908
feat(website): add scroll-reveal motion primitives
heyradcode Aug 9, 2026
b615653
fix(website): assign section washes explicitly instead of by nth-of-type
heyradcode Aug 9, 2026
aeb97bc
feat: serve the hero background through next/image
heyradcode Aug 9, 2026
0dbecda
fix(website): correct the heading hierarchy
heyradcode Aug 9, 2026
66ab234
feat(website): replace the header bar with a floating glass nav
heyradcode Aug 9, 2026
e1e5f5a
feat(website): rebuild the hero around a featured companion
heyradcode Aug 9, 2026
5d61967
refactor(website): drop the featured companion from the hero
heyradcode Aug 9, 2026
e4ef14e
feat(website): draw the how-it-works rail and ignite nodes in sequence
heyradcode Aug 9, 2026
dd0bb7d
ebsite): rebuild features as a bento grid with cursor spotlight
heyradcode Aug 9, 2026
24e24c6
feat(website): animate the rarity chart and give pets rarity auras
heyradcode Aug 9, 2026
4e6def3
feat(website): count the stats up and rebuild the CTA as a glass panel
heyradcode Aug 9, 2026
c6024a7
feat(website): drive the roadmap rail from the data
heyradcode Aug 9, 2026
2826c56
feat(website): animate the FAQ disclosure and fix the marquee duplicate
heyradcode Aug 9, 2026
22bd298
feat(website): polish the community and footer sections
heyradcode Aug 9, 2026
dc278b3
refactor(website): centralise landing copy into the content module
heyradcode Aug 9, 2026
1ac2465
feat(website): rewrite the landing copy to claims that check out
heyradcode Aug 9, 2026
8442040
feat(website): add full metadata, OG image, robots and sitemap
heyradcode Aug 9, 2026
0aa1378
ui(website): round the navbar CTA into a pill
heyradcode Aug 9, 2026
3be395d
refactor(website): align landing copy with what the project actually …
heyradcode Aug 9, 2026
862888e
fix(website): make the nav indicator actually slide
heyradcode Aug 9, 2026
9225b35
feat(website): show real generated pet art in the roster
heyradcode Aug 9, 2026
acef77a
feat(website): restore the interaction glyphs on feature cards
heyradcode Aug 9, 2026
fbe209e
feat(website): make the roadmap a road that draws as you scroll
heyradcode Aug 9, 2026
4e75f36
feat(website): turn the roadmap into a pinned scroll-linked scene
heyradcode Aug 9, 2026
389daf1
feat(website): stage the roadmap as a phase-tinted cosmos scene
heyradcode Aug 9, 2026
e55dd0a
fix(website): rebuild the roadmap scene in real 3D and fix its layout…
heyradcode Aug 9, 2026
fbc1441
fix(website): keep roadmap gates out of the card band and enlarge the…
heyradcode Aug 9, 2026
34968c1
feat(website): rebuild how-it-works as a 3D slab wall
heyradcode Aug 9, 2026
1543c83
feat(website): turn the pet roster into a scroll-synced 3D carousel
heyradcode Aug 9, 2026
7a7f5b2
fix(website): slow the pets carousel and the roadmap drive
heyradcode Aug 9, 2026
01dde45
feat(website): pin the pets showcase and keep its heading on screen
heyradcode Aug 9, 2026
42a5984
fix(website): unfreeze the pets carousel and move the rarity bar into…
heyradcode Aug 9, 2026
a79081f
fix(website): publish --track-progress from the scene hook
heyradcode Aug 9, 2026
8697155
refactor(website): drop the 3D treatment from how-it-works
heyradcode Aug 9, 2026
c74cbd5
fix(website): land nav anchors clear of the header
heyradcode Aug 9, 2026
002c185
fix(website): resolve the hydration mismatch and land nav anchors exa…
heyradcode Aug 9, 2026
5bca14a
fix(website): land nav anchors on section content, not the padding ab…
heyradcode Aug 9, 2026
ddc210d
fix(website): give the header one height so anchors land exactly
heyradcode Aug 9, 2026
9df9e3c
fix(website): make pinned scenes own the viewport so anchors land clean
heyradcode Aug 9, 2026
bb6d055
feat(website): make the FAQ an exclusive accordion
heyradcode Aug 9, 2026
d341920
perf(website): cache the per-frame layout reads in the scroll hooks
heyradcode Aug 9, 2026
7c6cb45
refactor(website): extract section navigation out of the header
heyradcode Aug 9, 2026
5c64f2c
refactor(website): extract shared math, media and rAF helpers
heyradcode Aug 9, 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
10 changes: 9 additions & 1 deletion website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ Next.js landing page (`website/`). The playable app lives in `frontend/`.
pnpm dev:web
```

Copy `env.example` to `.env.local` and set `NEXT_PUBLIC_APP_URL` to your local or deployed app URL.
Copy `env.example` to `.env.local` and set:

- `NEXT_PUBLIC_APP_URL` — the local or deployed **app** URL, used by the "Play Now" CTA.
- `NEXT_PUBLIC_SITE_URL` — the public origin of **this site**, used for canonical
URLs, `sitemap.xml`, `robots.txt` and Open Graph tags. It defaults to
`http://localhost:3002`, so a production deploy that leaves it unset publishes a
canonical tag and sitemap pointing at localhost. The two are different domains;
do not reuse `NEXT_PUBLIC_APP_URL` here.

## Deploy to Vercel (GitHub Actions)

Expand Down Expand Up @@ -43,6 +50,7 @@ CI runs `vercel pull` / `vercel deploy` from the monorepo root so `pnpm-lock.yam
| `VERCEL_ORG_ID` | Secret | Team/user ID |
| `VERCEL_WEBSITE_PROJECT_ID` | Secret | This website project’s ID |
| `NEXT_PUBLIC_APP_URL` | Variable | Public URL of the `frontend` app |
| `NEXT_PUBLIC_SITE_URL` | Variable | Public URL of this marketing site (canonical, sitemap, OG) |

Workflow: none. `.github/workflows/website.yml` was removed in 49c5e63, and the
secrets table above plus the triggers below describe that workflow. They have
Expand Down
7 changes: 6 additions & 1 deletion website/env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# URL of the deployed Crypto Pets app (frontend) — used by the landing "Start Playing" CTA
# URL of the deployed Crypto Pets app (frontend) — used by the landing "Play Now" CTA
NEXT_PUBLIC_APP_URL=http://localhost:5173

# Public origin of THIS marketing site — used for canonical URLs, sitemap.xml,
# robots.txt and Open Graph tags. Must be set in production, or crawlers are
# handed localhost. Not the same as NEXT_PUBLIC_APP_URL above.
NEXT_PUBLIC_SITE_URL=http://localhost:3002
Binary file removed website/public/images/pets/cat.png
Binary file not shown.
Binary file added website/public/images/pets/cinder-streak.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed website/public/images/pets/dinosaur.png
Binary file not shown.
Binary file removed website/public/images/pets/dog.png
Binary file not shown.
Binary file removed website/public/images/pets/elephant.png
Binary file not shown.
Binary file added website/public/images/pets/ember-oracle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed website/public/images/pets/lion.png
Binary file not shown.
Binary file added website/public/images/pets/nova-brute.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed website/public/images/pets/owl.png
Binary file not shown.
Binary file added website/public/images/pets/starlit-prowler.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added website/public/images/pets/tidefang.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added website/public/images/pets/umbral-bulwark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 54 additions & 20 deletions website/public/llms.txt
Original file line number Diff line number Diff line change
@@ -1,25 +1,48 @@
# CryptoPets

> A fully on-chain creature collection and battle game. Mint, breed, train, and
> battle pet NFTs across Ethereum and Solana — playable on web and mobile.
> A creature collection and battle game where the pets are NFTs. Mint, breed,
> train and battle across Ethereum and Solana — on web and mobile.

This is the marketing landing site. The playable app lives at a separate URL
(see Links). Pets are NFTs held in the player's own wallet — mintable, tradable,
and transferable independent of the app.
(see Links). Pets and items are NFTs held in the player's own wallet — mintable,
tradable, and transferable independent of the app.

## Overview

- **What it is:** on-chain pet collection + tactical battle game (NFTs).
- **Chains:** Ethereum and Solana, with additional rollups planned through Q3.
- **Wallets:** MetaMask, Phantom, or social login.
- **What it is:** on-chain pet collection and tactical battle game (NFTs).
- **Chains:** Ethereum and Solana. Pets, breeding and battles run on both;
equipment and item NFTs are on Ethereum today.
- **Wallets:** MetaMask on Ethereum, Phantom on Solana.
- **Platforms:** web and mobile.

## Gameplay

- **Connect** any wallet (MetaMask, Phantom, social login).
- **Mint** a pet from the egg pool and roll for a rare trait.
- **Train** — level up, breed new bloodlines, unlock signature abilities.
- **Battle** rivals in the arena and climb the global leaderboard.
- **Connect** the wallet you already have.
- **Hatch** a starter pet whose traits come from on-chain randomness.
- **Raise** it — level up, train stats, equip gear, breed bloodlines, marry a
partner pet (which unlocks a private thread between the two owners).
- **Battle** rivals in the arena and climb the season leaderboard.

## Provably fair battles

- Defending requires a wallet-signed authorization naming the pet, the level band,
the exact rule set, a validity window and a daily cap. A pet cannot be dragged
into a fight its owner did not agree to.
- Each battle is seeded from a public randomness beacon round committed **before**
the fight resolves, so no party can grind the roll.
- Every result is a signed receipt over the exact inputs it used, and batches of
receipts are committed to a Merkle root written on chain.
- An open-source verifier replays any receipt independently and reports seven
checks separately: seed derivation, operator signature, beacon signature,
combat replay, progression, equipment and hash-chain continuity. It needs no
account and no access to the project's servers.

## Rewards

- Seasons pay CPET to the top of the leaderboard, claimed against an on-chain
Merkle root with per-wallet and per-season ceilings.
- CPET has a fixed supply and no mint function, so the total is checkable by
anyone and cannot be inflated later.

## Rarity tiers

Expand All @@ -30,24 +53,35 @@ and transferable independent of the app.

## Roadmap

- Q1 — Genesis Drop (shipped): genesis mint, socials, first 10k supply.
- Q2 — Arena (shipped): battle system v1, leaderboards, weekly tournaments.
- Q3 — Bloodlines (in progress): breeding, cross-chain support, new rarity tier.
- Q4 — Marketplace 2.0 (planned): native P2P trades, mobile app, guild system.
Phases, not dates.

- 01 Foundation (shipped): dual-chain minting, breeding and bloodlines, marriage,
level up, train, rename, transfer.
- 02 Provable Arena (shipped): beacon-seeded battles, signed and chain-anchored
receipts, open-source public verifier.
- 03 Progression (in progress): leaderboard and seasons, CPET season rewards,
equipment and item NFTs.
- 04 Expansion (planned): daily quests, team battles, pet and item marketplace.

## Built with

Ethereum, Solana, Base, Pyth Entropy, Switchboard, drand, Metaplex, The Graph.

## Links

- [Play the app](https://cryptopets.vercel.app)
- [Source code (GitHub)](https://github.com/radcrew/do-not-stop)
- [Features](/#features)
- [Receipt verifier](https://github.com/radcrew/do-not-stop/tree/main/verifier)
- [How to play](/#how)
- [Features](/#features)
- [Pets](/#pets)
- [Provably fair](/#proof)
- [Roadmap](/#roadmap)
- [FAQ](/#faq)

## Optional
## Notes

- Contracts are independently audited; audit reports are linked in the docs and
updated on every major release.
- Connecting a wallet is free; mint price varies per drop and is announced ahead
of time on community channels (Discord, Twitter).
of time on community channels.
- Pets and items are tradable assets and seasons pay rewards to the top of the
leaderboard. This is a game you own a piece of, not an income stream.
60 changes: 57 additions & 3 deletions website/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Metadata } from 'next';
import type { ReactNode } from 'react';
import { Inter, Orbitron } from 'next/font/google';

import { SITE_URL } from '@/lib/siteUrl';
import '../styles/globals.css';

const orbitron = Orbitron({
Expand All @@ -17,14 +18,67 @@ const inter = Inter({
display: 'swap',
});

const TITLE = 'Crypto Pets';
const DESCRIPTION =
'Collect, breed and battle NFT pets on Ethereum and Solana. Every battle settles from a committed seed and ships with a receipt anyone can replay.';

export const metadata: Metadata = {
title: 'Crypto Pets',
description: 'Collect, battle and breed unique on-chain pets in the ultimate Crypto Pets adventure.',
// Required for Next to resolve the relative URLs below into absolute ones.
metadataBase: new URL(SITE_URL),
title: {
default: TITLE,
template: '%s · Crypto Pets',
},
description: DESCRIPTION,
applicationName: 'Crypto Pets',
keywords: [
'NFT game',
'on-chain game',
'pet battler',
'Ethereum',
'Solana',
'provably fair',
'blockchain gaming',
],
alternates: { canonical: '/' },
openGraph: {
type: 'website',
url: '/',
siteName: 'Crypto Pets',
title: TITLE,
description: DESCRIPTION,
locale: 'en_US',
},
twitter: {
card: 'summary_large_image',
title: TITLE,
description: DESCRIPTION,
},
robots: {
index: true,
follow: true,
googleBot: { index: true, follow: true, 'max-image-preview': 'large' },
},
};

/* Runs before first paint. Reveal targets start hidden only once this class is
present, so a blocked or failed bundle degrades to a fully visible page
instead of a blank one below the fold. */
const REVEAL_GUARD = "document.documentElement.classList.add('js-reveal')";

export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={`${orbitron.variable} ${inter.variable}`}>
/* The guard above mutates this element's class list before React hydrates,
so the server markup and the client tree disagree on className by design.
Without this, that shows up as a hydration mismatch on every load. */
<html
lang="en"
className={`${orbitron.variable} ${inter.variable}`}
suppressHydrationWarning
>
<head>
<script dangerouslySetInnerHTML={{ __html: REVEAL_GUARD }} />
</head>
<body>{children}</body>
</html>
);
Expand Down
105 changes: 105 additions & 0 deletions website/src/app/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { ImageResponse } from 'next/og';

export const alt = 'Crypto Pets - collect, battle and breed on-chain pets';
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';

/**
* Generated at build time rather than checked in as a binary, so the card cannot
* drift out of sync with the copy it quotes.
*
* Satori (which renders this) supports only a subset of CSS: flexbox but not
* grid, and no `background-clip: text`. The neon gradient the page uses on its
* headline is therefore approximated here with solid accent colours and a
* gradient rule, rather than gradient-filled type.
*/
export default function OpengraphImage() {
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
padding: '72px 80px',
backgroundColor: '#050812',
backgroundImage:
'radial-gradient(900px circle at 15% 0%, rgba(155,100,255,0.30), transparent 55%), radial-gradient(760px circle at 92% 96%, rgba(41,168,255,0.24), transparent 55%)',
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
<div
style={{
width: 14,
height: 14,
borderRadius: 999,
backgroundColor: '#6cf6c5',
}}
/>
<div
style={{
fontSize: 24,
letterSpacing: 6,
textTransform: 'uppercase',
color: '#b6e2ff',
}}
>
On-Chain Pet Battler
</div>
</div>

<div style={{ display: 'flex', flexDirection: 'column' }}>
<div
style={{
fontSize: 82,
fontWeight: 800,
lineHeight: 1.05,
letterSpacing: -1,
color: '#f6f3ff',
}}
>
Collect, Battle &amp; Breed
</div>
<div
style={{
fontSize: 82,
fontWeight: 800,
lineHeight: 1.05,
letterSpacing: -1,
color: '#b58cff',
}}
>
Your Dream Pets
</div>
<div
style={{
width: 220,
height: 5,
marginTop: 28,
borderRadius: 4,
backgroundImage: 'linear-gradient(90deg, #7dd6ff, #b58cff 60%, #ff7bcb)',
}}
/>
</div>

<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'flex-end',
}}
>
<div style={{ fontSize: 30, color: 'rgba(195,210,255,0.82)', maxWidth: 720 }}>
Every battle settles from a committed seed, with a receipt anyone can replay.
</div>
<div style={{ fontSize: 26, color: '#7dd6ff', letterSpacing: 2 }}>
Ethereum · Solana
</div>
</div>
</div>
),
size,
);
}
4 changes: 2 additions & 2 deletions website/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
Hero,
HowItWorks,
Pets,
Proof,
Roadmap,
Stats,
Testimonials,
} from '@/components/landing';

const LandingPage = () => (
Expand All @@ -24,7 +24,7 @@ const LandingPage = () => (
<Stats />
<Cta />
<Roadmap />
<Testimonials />
<Proof />
<Faq />
<Backers />
<Community />
Expand Down
11 changes: 11 additions & 0 deletions website/src/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { MetadataRoute } from 'next';

import { SITE_URL } from '@/lib/siteUrl';

export default function robots(): MetadataRoute.Robots {
return {
rules: { userAgent: '*', allow: '/' },
sitemap: `${SITE_URL}/sitemap.xml`,
host: SITE_URL,
};
}
19 changes: 19 additions & 0 deletions website/src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { MetadataRoute } from 'next';

import { SITE_URL } from '@/lib/siteUrl';

/**
* One entry: the landing page is a single document. Its sections are anchors on
* that document, not separate URLs, and listing them would advertise pages that
* do not exist.
*/
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: SITE_URL,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
},
];
}
3 changes: 3 additions & 0 deletions website/src/app/twitter-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* Twitter reuses the Open Graph card; Next does not derive twitter:image from
opengraph-image on its own. */
export { default, size, contentType, alt } from './opengraph-image';
Loading
Loading