Skip to content

Commit be4a316

Browse files
sktbrdclaude
andcommitted
feat(home): promote the /newhome build to /, park the old one at /oldhome
The homepage rebuild has been reviewed section by section on its own route. Swap it in: /newhome becomes /, and the page it replaces moves to /oldhome as a noindex rollback reference until the new one has proven itself. The metadata does NOT travel with the pages. `generateMetadata` — translated title/description, canonical, the EN/pt-BR/x-default hreflang set, OG and Twitter — stays on `/`, because /newhome shipped as `robots: noindex` with a placeholder title and moving that verbatim would have deindexed the homepage. /oldhome gets its own noindex instead, so two pages never claim canonical "/". /newhome 301s to / in both locales — no SEO weight to preserve, but the link was passed around during review. Components and messages stay under `newhome/`: renaming them would collide with the `home/` components /oldhome still uses. That rename is the cleanup for whoever deletes /oldhome. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 06d3288 commit be4a316

4 files changed

Lines changed: 234 additions & 201 deletions

File tree

next.config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@ const nextConfig: NextConfig = {
102102
destination: "/auctions",
103103
permanent: true,
104104
},
105+
// /newhome was the homepage rebuild's staging route before it took over
106+
// `/`. It carried no SEO weight (it shipped noindex), but the link was
107+
// handed around during review, so it lands on the real homepage instead
108+
// of a 404. Both locales, since localePrefix is "as-needed" and only
109+
// pt-BR carries a prefix.
110+
{
111+
source: "/newhome",
112+
destination: "/",
113+
permanent: true,
114+
},
115+
{
116+
source: "/pt-br/newhome",
117+
destination: "/pt-br",
118+
permanent: true,
119+
},
105120
// Blog post trailing slash cleanup (generated from markdown files)
106121
...blogRedirects,
107122
];

src/app/[locale]/newhome/page.tsx

Lines changed: 0 additions & 101 deletions
This file was deleted.

src/app/[locale]/oldhome/page.tsx

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { Suspense } from "react";
2+
import type { Metadata } from "next";
3+
import { getTranslations, setRequestLocale } from "next-intl/server";
4+
import { FAQ } from "@/components/common/FAQ";
5+
import { ContractsList } from "@/components/contracts-list";
6+
import { AuctionSpotlight } from "@/components/hero/AuctionSpotlight";
7+
import { ActivityFeedSection } from "@/components/home/ActivityFeedSection";
8+
import { AnimatedDescription } from "@/components/home/AnimatedDescription";
9+
import { HeroStatsValues } from "@/components/home/HeroStatsValues";
10+
import { HomeStaticContent } from "@/components/home/HomeStaticContent";
11+
import { PoweredByMorpheus } from "@/components/home/PoweredByMorpheus";
12+
import { RecentProposalsSection } from "@/components/home/RecentProposalsSection";
13+
import {
14+
ActivityFeedSkeleton,
15+
HeroStatsSkeleton,
16+
RecentProposalsSkeleton,
17+
} from "@/components/skeletons/home-skeletons";
18+
import { Gnar3DTVClient } from "@/components/tv/Gnar3DTVClient";
19+
import { HeroTVObserver } from "@/components/tv/HeroTVObserver";
20+
import { Link } from "@/i18n/navigation";
21+
22+
export const revalidate = 300;
23+
24+
// Deliberately NOT the homepage's metadata. This page served `/` until the
25+
// /newhome build replaced it, and its `generateMetadata` moved with the route —
26+
// canonical, hreflang and the translated title now live in [locale]/page.tsx.
27+
// Leaving a second page claiming `canonical: "/"` would make the site compete
28+
// with itself for its own homepage.
29+
//
30+
// noindex because this is a rollback reference, not a destination: it is absent
31+
// from the sitemap and from the nav, and it should be deleted once the new
32+
// homepage has proven itself. Deleting it is also what unblocks renaming
33+
// `components/newhome/` to `home/`.
34+
export const metadata: Metadata = {
35+
title: "Gnars — previous homepage",
36+
robots: { index: false, follow: false },
37+
};
38+
39+
export default async function OldHome({ params }: { params: Promise<{ locale: string }> }) {
40+
const { locale } = await params;
41+
setRequestLocale(locale);
42+
43+
const t = await getTranslations("home");
44+
45+
return (
46+
<div className="flex flex-1 flex-col">
47+
{/* Hero Section - Static content renders immediately */}
48+
<section className="relative overflow-hidden">
49+
<div className="relative bg-background z-10 py-8 md:py-10 lg:py-12">
50+
<div className="mx-auto max-w-6xl">
51+
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2 lg:gap-12">
52+
{/* Left Column - Brand & Stats */}
53+
<div className="flex flex-col justify-center space-y-6">
54+
<div className="space-y-4">
55+
<h1 className="text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl">
56+
<span className="bg-gradient-to-r from-foreground to-foreground/80 bg-clip-text text-transparent">
57+
{t("hero.title")}
58+
</span>
59+
<span className="sr-only">{t("hero.srOnly")}</span>
60+
</h1>
61+
<AnimatedDescription />
62+
</div>
63+
64+
{/* Stats - Only this part streams in */}
65+
<Suspense fallback={<HeroStatsSkeleton />}>
66+
<HeroStatsValues />
67+
</Suspense>
68+
</div>
69+
70+
{/* Right Column - 3D TV (Client Component) */}
71+
<HeroTVObserver>
72+
<div className="flex items-center justify-center">
73+
<Gnar3DTVClient autoRotate={true} />
74+
</div>
75+
</HeroTVObserver>
76+
</div>
77+
</div>
78+
</div>
79+
</section>
80+
81+
{/* Community × community — Gnars is a Morpheus Builder (gated on the subnet goal) */}
82+
<Suspense fallback={null}>
83+
<PoweredByMorpheus />
84+
</Suspense>
85+
86+
{/* Dashboard Grid */}
87+
<div className="flex flex-1 flex-col gap-6 py-8">
88+
{/* SEO-only context */}
89+
<section className="sr-only">
90+
<h2>{t("seo.whatIsGnars")}</h2>
91+
<p>{t("seo.body1")}</p>
92+
<p>{t("seo.body2")}</p>
93+
<p>
94+
Learn more about <Link href="/about">{t("seo.linkAbout")}</Link>, explore{" "}
95+
<Link href="/proposals">{t("seo.linkProposals")}</Link>, or view{" "}
96+
<Link href="/auctions">{t("seo.linkAuctions")}</Link>.
97+
</p>
98+
</section>
99+
100+
{/* Recent Proposals Section */}
101+
<section>
102+
<Suspense fallback={<RecentProposalsSkeleton />}>
103+
<RecentProposalsSection limit={6} />
104+
</Suspense>
105+
</section>
106+
107+
{/* Auction + Activity Feed - Side by side on desktop */}
108+
<section className="grid grid-cols-1 lg:grid-cols-2 gap-6">
109+
{/* Auction Spotlight - determines row height on desktop */}
110+
<AuctionSpotlight />
111+
112+
{/* Activity Feed - fixed height on mobile, matches auction on desktop via absolute */}
113+
<div className="relative h-[500px] lg:h-auto">
114+
<div className="lg:absolute lg:inset-0 h-full">
115+
<Suspense fallback={<ActivityFeedSkeleton responsive />}>
116+
<ActivityFeedSection daysBack={30} responsive singleColumn />
117+
</Suspense>
118+
</div>
119+
</div>
120+
</section>
121+
122+
{/* Static/Client-side content: Charts, Auctions */}
123+
<HomeStaticContent />
124+
125+
{/* FAQ Section */}
126+
<section>
127+
<FAQ />
128+
</section>
129+
130+
{/* Smart Contracts */}
131+
<section>
132+
<ContractsList />
133+
</section>
134+
</div>
135+
</div>
136+
);
137+
}

0 commit comments

Comments
 (0)