Skip to content

Commit c705bb8

Browse files
authored
Merge pull request #15114 from ethereum/app-router-pages
App router pages
2 parents 52ec3eb + 304c88f commit c705bb8

File tree

95 files changed

+2317
-2674
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+2317
-2674
lines changed

Diff for: .storybook/manager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { addons } from "@storybook/manager-api"
22

3-
import favicon from "../public/images/favicon.png"
3+
import favicon from "../public/images/eth-home-icon.png"
44

55
import theme from "./theme"
66

Diff for: .storybook/preview-head.html

-3
This file was deleted.

Diff for: .storybook/preview.tsx

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import isChromatic from "chromatic/isChromatic"
22
import { MotionGlobalConfig } from "framer-motion"
3+
import { IBM_Plex_Mono, Inter } from "next/font/google"
34
import type { Preview } from "@storybook/react"
45

56
import ThemeProvider from "@/components/ThemeProvider"
@@ -9,11 +10,24 @@ import nextIntl, { baseLocales } from "./next-intl"
910
import { withNextThemes } from "./withNextThemes"
1011

1112
import "../src/styles/global.css"
12-
import "../src/styles/fonts.css"
1313
import "../src/styles/docsearch.css"
1414

1515
import "@docsearch/css"
1616

17+
const inter = Inter({
18+
subsets: ["latin"],
19+
display: "swap",
20+
variable: "--font-inter",
21+
preload: true,
22+
})
23+
24+
const ibmPlexMono = IBM_Plex_Mono({
25+
subsets: ["latin"],
26+
weight: ["400"],
27+
display: "swap",
28+
variable: "--font-mono",
29+
})
30+
1731
MotionGlobalConfig.skipAnimations = isChromatic()
1832

1933
export const breakpointSet: [token: string, value: string][] = [
@@ -39,11 +53,13 @@ const preview: Preview = {
3953
defaultTheme: "light",
4054
}),
4155
(Story) => (
42-
<ThemeProvider>
43-
<TooltipProvider>
44-
<Story />
45-
</TooltipProvider>
46-
</ThemeProvider>
56+
<div className={`${inter.variable} ${ibmPlexMono.variable}`}>
57+
<ThemeProvider>
58+
<TooltipProvider>
59+
<Story />
60+
</TooltipProvider>
61+
</ThemeProvider>
62+
</div>
4763
),
4864
],
4965
parameters: {

Diff for: src/pages/[locale]/index.tsx renamed to app/[locale]/_components/home.tsx

+13-135
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
"use client"
2+
13
import { Fragment, lazy, Suspense } from "react"
2-
import type { GetStaticProps, InferGetStaticPropsType } from "next"
34
import { FaDiscord, FaGithub } from "react-icons/fa6"
45
import { IoMdCopy } from "react-icons/io"
56
import { MdCheck } from "react-icons/md"
@@ -8,10 +9,9 @@ import type {
89
AllMetricData,
910
BasePageProps,
1011
CommunityBlog,
11-
Lang,
12-
Params,
1312
RSSItem,
1413
} from "@/lib/types"
14+
import { CommunityEvent } from "@/lib/interfaces"
1515

1616
import { ChevronNext } from "@/components/Chevron"
1717
import CodeModal from "@/components/CodeModal"
@@ -24,8 +24,13 @@ import Calendar from "@/components/icons/calendar.svg"
2424
import CalendarAdd from "@/components/icons/calendar-add.svg"
2525
import { Image } from "@/components/Image"
2626
import MainArticle from "@/components/MainArticle"
27-
import PageMetadata from "@/components/PageMetadata"
2827
import { TranslatathonBanner } from "@/components/Translatathon/TranslatathonBanner"
28+
import {
29+
Accordion,
30+
AccordionContent,
31+
AccordionItem,
32+
AccordionTrigger,
33+
} from "@/components/ui/accordion"
2934
import { Button, ButtonLink } from "@/components/ui/buttons/Button"
3035
import SvgButtonLink, {
3136
type SvgButtonLinkProps,
@@ -56,43 +61,13 @@ import {
5661
import WindowBox from "@/components/WindowBox"
5762

5863
import { cn } from "@/lib/utils/cn"
59-
import { dataLoader } from "@/lib/utils/data/dataLoader"
6064
import { isValidDate } from "@/lib/utils/date"
61-
import { existsNamespace } from "@/lib/utils/existsNamespace"
62-
import { getLastDeployDate } from "@/lib/utils/getLastDeployDate"
6365
import { trackCustomEvent } from "@/lib/utils/matomo"
64-
import { polishRSSList } from "@/lib/utils/rss"
6566
import { breakpointAsNumber } from "@/lib/utils/screen"
66-
import { getLocaleTimestamp } from "@/lib/utils/time"
67-
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
68-
69-
import {
70-
BASE_TIME_UNIT,
71-
BLOG_FEEDS,
72-
BLOGS_WITHOUT_FEED,
73-
CALENDAR_DISPLAY_COUNT,
74-
DEFAULT_LOCALE,
75-
GITHUB_REPO_URL,
76-
LOCALES_CODES,
77-
RSS_DISPLAY_COUNT,
78-
} from "@/lib/constants"
7967

80-
import {
81-
Accordion,
82-
AccordionContent,
83-
AccordionItem,
84-
AccordionTrigger,
85-
} from "../../components/ui/accordion"
68+
import { GITHUB_REPO_URL } from "@/lib/constants"
8669

8770
import { useClipboard } from "@/hooks/useClipboard"
88-
import loadNamespaces from "@/i18n/loadNamespaces"
89-
import { fetchCommunityEvents } from "@/lib/api/calendarEvents"
90-
import { fetchEthPrice } from "@/lib/api/fetchEthPrice"
91-
import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie"
92-
import { fetchAttestantPosts } from "@/lib/api/fetchPosts"
93-
import { fetchRSS } from "@/lib/api/fetchRSS"
94-
import { fetchTotalEthStaked } from "@/lib/api/fetchTotalEthStaked"
95-
import { fetchTotalValueLocked } from "@/lib/api/fetchTotalValueLocked"
9671
import EventFallback from "@/public/images/events/event-placeholder.png"
9772
import BuildersImage from "@/public/images/heroes/developers-hub-hero.jpg"
9873
import ActivityImage from "@/public/images/heroes/layer-2-hub-hero.jpg"
@@ -111,110 +86,17 @@ const Codeblock = lazy(() =>
11186

11287
const StatsBoxGrid = lazy(() => import("@/components/StatsBoxGrid"))
11388

114-
// API calls
115-
const fetchXmlBlogFeeds = async () => {
116-
return await fetchRSS(BLOG_FEEDS)
117-
}
118-
11989
type Props = BasePageProps & {
90+
calendar: CommunityEvent[]
12091
metricResults: AllMetricData
12192
rssData: { rssItems: RSSItem[]; blogLinks: CommunityBlog[] }
12293
}
12394

124-
// In seconds
125-
const REVALIDATE_TIME = BASE_TIME_UNIT * 1
126-
127-
const loadData = dataLoader(
128-
[
129-
["ethPrice", fetchEthPrice],
130-
["totalEthStaked", fetchTotalEthStaked],
131-
["totalValueLocked", fetchTotalValueLocked],
132-
["growThePieData", fetchGrowThePie],
133-
["communityEvents", fetchCommunityEvents],
134-
["attestantPosts", fetchAttestantPosts],
135-
["rssData", fetchXmlBlogFeeds],
136-
],
137-
REVALIDATE_TIME * 1000
138-
)
139-
140-
export async function getStaticPaths() {
141-
return {
142-
paths: LOCALES_CODES.map((locale) => ({ params: { locale } })),
143-
fallback: false,
144-
}
145-
}
146-
147-
export const getStaticProps = (async ({ params }) => {
148-
const { locale = DEFAULT_LOCALE } = params || {}
149-
150-
const [
151-
ethPrice,
152-
totalEthStaked,
153-
totalValueLocked,
154-
growThePieData,
155-
communityEvents,
156-
attestantPosts,
157-
xmlBlogs,
158-
] = await loadData()
159-
160-
const metricResults: AllMetricData = {
161-
ethPrice,
162-
totalEthStaked,
163-
totalValueLocked,
164-
txCount: growThePieData.txCount,
165-
txCostsMedianUsd: growThePieData.txCostsMedianUsd,
166-
}
167-
168-
const calendar = communityEvents.upcomingEventData
169-
.sort((a, b) => {
170-
const dateA = isValidDate(a.date) ? new Date(a.date).getTime() : -Infinity
171-
const dateB = isValidDate(b.date) ? new Date(b.date).getTime() : -Infinity
172-
return dateA - dateB
173-
})
174-
.slice(0, CALENDAR_DISPLAY_COUNT)
175-
176-
// load i18n required namespaces for the given page
177-
const requiredNamespaces = getRequiredNamespacesForPage("/")
178-
179-
// check if the translated page content file exists for locale
180-
const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[0])
181-
182-
// load last deploy date to pass to Footer in RootLayout
183-
const lastDeployDate = getLastDeployDate()
184-
const lastDeployLocaleTimestamp = getLocaleTimestamp(
185-
locale as Lang,
186-
lastDeployDate
187-
)
188-
189-
// RSS feed items
190-
const polishedRssItems = polishRSSList(attestantPosts, ...xmlBlogs)
191-
const rssItems = polishedRssItems.slice(0, RSS_DISPLAY_COUNT)
192-
193-
const blogLinks = polishedRssItems.map(({ source, sourceUrl }) => ({
194-
name: source,
195-
href: sourceUrl,
196-
})) as CommunityBlog[]
197-
blogLinks.push(...BLOGS_WITHOUT_FEED)
198-
199-
const messages = await loadNamespaces(locale, requiredNamespaces)
200-
201-
return {
202-
props: {
203-
messages,
204-
calendar,
205-
contentNotTranslated,
206-
lastDeployLocaleTimestamp,
207-
metricResults,
208-
rssData: { rssItems, blogLinks },
209-
},
210-
}
211-
}) satisfies GetStaticProps<Props, Params>
212-
21395
const HomePage = ({
21496
calendar,
21597
metricResults,
21698
rssData: { rssItems, blogLinks },
217-
}: InferGetStaticPropsType<typeof getStaticProps>) => {
99+
}: Props) => {
218100
const {
219101
t,
220102
locale,
@@ -236,10 +118,6 @@ const HomePage = ({
236118

237119
return (
238120
<MainArticle className="flex w-full flex-col items-center" dir={dir}>
239-
<PageMetadata
240-
title={t("page-index:page-index-meta-title")}
241-
description={t("page-index:page-index-meta-description")}
242-
/>
243121
<TranslatathonBanner />
244122
<HomeHero heroImg={Hero} className="w-full" />
245123
<div className="w-full space-y-32 px-4 md:mx-6 lg:space-y-48">
@@ -504,7 +382,7 @@ const HomePage = ({
504382
<button
505383
key={title}
506384
className={cn(
507-
"flex flex-col gap-y-0.5 border-t px-6 py-4 text-start hover:bg-background-highlight max-md:hidden",
385+
"flex flex-col gap-y-0.5 border-t px-6 py-4 hover:bg-background-highlight max-md:hidden",
508386
isModalOpen &&
509387
idx === activeCode &&
510388
"bg-background-highlight"

Diff for: src/pages/[locale]/assets.tsx renamed to app/[locale]/assets/_components/assets.tsx

+3-46
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1+
"use client"
2+
13
import { HTMLAttributes } from "react"
2-
import type { GetStaticProps } from "next/types"
34

4-
import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types"
5+
import type { ChildOnlyProp } from "@/lib/types"
56

67
import AssetDownload from "@/components/AssetDownload"
78
import FeedbackCard from "@/components/FeedbackCard"
89
import { Image } from "@/components/Image"
910
import MainArticle from "@/components/MainArticle"
10-
import PageMetadata from "@/components/PageMetadata"
1111
import { Center, Flex } from "@/components/ui/flex"
1212
import InlineLink from "@/components/ui/Link"
1313

14-
import { existsNamespace } from "@/lib/utils/existsNamespace"
15-
import { getLastDeployDate } from "@/lib/utils/getLastDeployDate"
16-
import { getLocaleTimestamp } from "@/lib/utils/time"
1714
// import efLogo from "@/public/images/ef-logo.png"
1815
// import efLogoWhite from "@/public/images/ef-logo-white.png"
1916
// import ethDiamondBlackHero from "@/public/images/assets/eth-diamond-black.png"
@@ -24,13 +21,8 @@ import { getLocaleTimestamp } from "@/lib/utils/time"
2421
// import ethGifWaves from "@/public/images/eth-gif-waves.png"
2522
// import ethPortraitPurpleWhite from "@/public/images/assets/ethereum-logo-portrait-purple-white.png"
2623
// import leslieTheRhino from "@/public/images/upgrades/upgrade_rhino.png"
27-
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
28-
29-
import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
30-
3124
import useColorModeValue from "@/hooks/useColorModeValue"
3225
import { useTranslation } from "@/hooks/useTranslation"
33-
import loadNamespaces from "@/i18n/loadNamespaces"
3426
import ethDiamondBlack from "@/public/images/assets/eth-diamond-black.png"
3527
import ethDiamondBlackGray from "@/public/images/assets/eth-diamond-black-gray.png"
3628
import ethDiamondBlackWhite from "@/public/images/assets/eth-diamond-black-white.jpg"
@@ -98,37 +90,6 @@ const H3 = (props: ChildOnlyProp) => (
9890
<h3 className="mb-0 mt-10 leading-xs" {...props} />
9991
)
10092

101-
export async function getStaticPaths() {
102-
return {
103-
paths: LOCALES_CODES.map((locale) => ({ params: { locale } })),
104-
fallback: false,
105-
}
106-
}
107-
108-
export const getStaticProps = (async ({ params }) => {
109-
const { locale = DEFAULT_LOCALE } = params || {}
110-
111-
const requiredNamespaces = getRequiredNamespacesForPage("assets")
112-
113-
const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2])
114-
115-
const lastDeployDate = getLastDeployDate()
116-
const lastDeployLocaleTimestamp = getLocaleTimestamp(
117-
locale as Lang,
118-
lastDeployDate
119-
)
120-
121-
const messages = await loadNamespaces(locale, requiredNamespaces)
122-
123-
return {
124-
props: {
125-
messages,
126-
contentNotTranslated,
127-
lastDeployLocaleTimestamp,
128-
},
129-
}
130-
}) satisfies GetStaticProps<BasePageProps, Params>
131-
13293
const AssetsPage = () => {
13394
// Ignore locale in the URL for SVG path in public directory to fix broken link
13495
// SVG path changes from /en/images => /images
@@ -141,10 +102,6 @@ const AssetsPage = () => {
141102
)
142103
return (
143104
<Flex className="w-full flex-col">
144-
<PageMetadata
145-
title={t("page-assets-meta-title")}
146-
description={t("page-assets-meta-desc")}
147-
/>
148105
<MainArticle className="px-8 py-4">
149106
<Flex className="flex-col px-8 py-4">
150107
<Center>

0 commit comments

Comments
 (0)