Skip to content

Commit 119d7d4

Browse files
authored
Merge pull request #15544 from ethereum/staging
Back merge `staging` into `dev`
2 parents 54cc93b + 206da9c commit 119d7d4

Some content is hidden

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

75 files changed

+308
-239
lines changed

app/[locale]/roadmap/_components/ReleaseCarousel.tsx

Lines changed: 74 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
"use client"
22

3-
import { useEffect, useState } from "react"
3+
// TODO: Extract intl strings
4+
// TODO: Fix RTL compatibility; currenly forced to LTR flow
5+
import { useCallback, useEffect, useMemo, useState } from "react"
6+
import { useLocale } from "next-intl"
47

58
import { Image } from "@/components/Image"
69
import { ButtonLink } from "@/components/ui/buttons/Button"
@@ -16,45 +19,39 @@ import {
1619
import { cn } from "@/lib/utils/cn"
1720
import { formatDate } from "@/lib/utils/date"
1821

19-
import { releasesData } from "@/data/roadmap/releases"
22+
import { Release, releasesData } from "@/data/roadmap/releases"
2023

21-
const findLatestReleaseIndex = () => {
22-
const today = new Date()
23-
const twoMonthsFromNow = new Date()
24-
twoMonthsFromNow.setMonth(today.getMonth() + 2)
24+
const ReleaseCarousel = () => {
25+
const locale = useLocale()
2526

26-
// First try to find a release within the next 2 months
27-
const upcomingReleaseIndex = releasesData.findIndex((release) => {
28-
const releaseDate = new Date(release.releaseDate)
29-
return releaseDate > today && releaseDate <= twoMonthsFromNow
30-
})
27+
const [api1, setApi1] = useState<CarouselApi>()
28+
const [api2, setApi2] = useState<CarouselApi>()
3129

32-
// If no upcoming release found, find the most recent release up to today
33-
if (upcomingReleaseIndex === -1) {
34-
const pastReleases = releasesData.filter(
35-
(release) => new Date(release.releaseDate) <= today
36-
)
37-
if (pastReleases.length > 0) {
38-
const mostRecentRelease = pastReleases[pastReleases.length - 1]
39-
return releasesData.findIndex(
40-
(release) => release.releaseDate === mostRecentRelease.releaseDate
41-
)
42-
}
43-
}
30+
const startIndex = useMemo(() => {
31+
const now = new Date()
4432

45-
return upcomingReleaseIndex
46-
}
33+
// Production: has a releaseDate in the past
34+
const productionReleases = releasesData.filter((release) => {
35+
if (!("releaseDate" in release) || !release.releaseDate) return false
36+
const releaseDate = new Date(release.releaseDate)
37+
return releaseDate <= now
38+
})
4739

48-
const ReleaseCarousel = () => {
49-
const todayDate = new Date()
50-
const twoMonthsFromNow = new Date()
51-
twoMonthsFromNow.setMonth(todayDate.getMonth() + 2)
40+
// Upcoming: has a releaseDate, but is in the future
41+
const upcomingReleases = releasesData.filter((release) => {
42+
if (!("releaseDate" in release) || !release.releaseDate) return false
43+
const releaseDate = new Date(release.releaseDate)
44+
return releaseDate > now
45+
})
5246

53-
const [api1, setApi1] = useState<CarouselApi>()
54-
const [api2, setApi2] = useState<CarouselApi>()
55-
const [currentIndex, setCurrentIndex] = useState(() =>
56-
findLatestReleaseIndex()
57-
)
47+
// If upcoming releases exist, start index after production releases
48+
if (upcomingReleases.length > 0) return productionReleases.length
49+
50+
// If no upcoming releases, start at the last production release
51+
return productionReleases.length - 1
52+
}, [])
53+
54+
const [currentIndex, setCurrentIndex] = useState(startIndex)
5855

5956
useEffect(() => {
6057
if (!api1 || !api2) {
@@ -72,8 +69,29 @@ const ReleaseCarousel = () => {
7269
})
7370
}, [api1, api2])
7471

72+
const getStatus = useCallback((release: Release) => {
73+
if (!("releaseDate" in release) || !release.releaseDate) return "dev"
74+
if (new Date(release.releaseDate) <= new Date()) return "prod"
75+
return "soon"
76+
}, [])
77+
78+
const getDisplayDate = (release: Release): string => {
79+
if (!("releaseDate" in release || "plannedReleaseYear" in release))
80+
return ""
81+
82+
if ("plannedReleaseYear" in release && release.plannedReleaseYear)
83+
return new Intl.DateTimeFormat(locale, {
84+
year: "numeric",
85+
}).format(new Date(Number(release.plannedReleaseYear), 0, 1))
86+
87+
if ("releaseDate" in release && release.releaseDate)
88+
return formatDate(release.releaseDate)
89+
90+
return ""
91+
}
92+
7593
return (
76-
<div className="w-full max-w-[100vw] overflow-hidden">
94+
<div className="w-full max-w-[100vw] overflow-hidden" dir="ltr">
7795
<div className="mx-auto w-full max-w-screen-2xl px-4 sm:px-6">
7896
<div className="w-full rounded-2xl bg-background-highlight py-6">
7997
<div className="flex flex-col gap-6">
@@ -84,30 +102,23 @@ const ReleaseCarousel = () => {
84102
opts={{
85103
align: "center",
86104
containScroll: false,
105+
direction: "ltr",
87106
loop: false,
88-
startIndex: findLatestReleaseIndex(),
107+
startIndex,
89108
}}
90109
>
91110
<CarouselContent>
92111
{releasesData.map((release, index) => {
93-
const releaseDate = new Date(release.releaseDate)
94-
const nextRelease =
95-
releaseDate > todayDate && releaseDate <= twoMonthsFromNow
96-
const labelType =
97-
releaseDate < todayDate
98-
? 1
99-
: releaseDate < twoMonthsFromNow
100-
? 2
101-
: 3
102-
112+
const status = getStatus(release)
113+
const displayDate = getDisplayDate(release)
103114
return (
104115
<CarouselItem
105116
key={release.releaseName}
106117
className="w-full md:basis-1/3"
107118
>
108119
<div className="flex w-full flex-col items-center justify-center gap-3">
109120
<div className="mb-3 !h-6">
110-
{labelType === 1 && (
121+
{status === "prod" && (
111122
<div
112123
className={cn(
113124
"w-fit rounded-lg bg-primary-low-contrast px-2 py-1",
@@ -117,7 +128,7 @@ const ReleaseCarousel = () => {
117128
<p className="text-sm font-bold">In production</p>
118129
</div>
119130
)}
120-
{labelType === 2 && (
131+
{status === "soon" && (
121132
<div
122133
className={cn(
123134
"w-fit rounded-lg bg-warning-light px-2 py-1",
@@ -129,7 +140,7 @@ const ReleaseCarousel = () => {
129140
</p>
130141
</div>
131142
)}
132-
{labelType === 3 && (
143+
{status === "dev" && (
133144
<div
134145
className={cn(
135146
"w-fit rounded-lg bg-card-gradient-secondary-hover px-2 py-1",
@@ -142,14 +153,15 @@ const ReleaseCarousel = () => {
142153
</div>
143154
)}
144155
</div>
156+
{/* Line-circle-line decoration —•— */}
145157
<div className="flex w-full items-center justify-center text-center">
146158
<div
147159
className={cn(
148160
"flex h-1 flex-1",
149161
index !== 0
150-
? nextRelease
162+
? status === "soon"
151163
? "bg-gradient-to-r from-primary to-primary-low-contrast"
152-
: releaseDate.getTime() < todayDate.getTime()
164+
: status === "prod"
153165
? "bg-primary"
154166
: "bg-primary-low-contrast"
155167
: "bg-transparent"
@@ -158,21 +170,21 @@ const ReleaseCarousel = () => {
158170
<div
159171
className={cn(
160172
"h-7 w-7 rounded-full",
161-
releaseDate.getTime() < todayDate.getTime()
173+
status === "prod"
162174
? "bg-primary"
163175
: "bg-primary-low-contrast",
164-
nextRelease &&
176+
status === "soon" &&
165177
"border-2 border-primary bg-background"
166178
)}
167179
/>
168180
<div
169181
className={cn(
170182
"flex h-1 flex-1",
171-
index !== releasesData.length - 1
172-
? index < findLatestReleaseIndex()
173-
? "bg-primary"
174-
: "bg-primary-low-contrast"
175-
: "bg-transparent"
183+
index < startIndex
184+
? "bg-primary"
185+
: "bg-primary-low-contrast",
186+
index === releasesData.length - 1 &&
187+
"bg-transparent"
176188
)}
177189
/>
178190
</div>
@@ -181,7 +193,7 @@ const ReleaseCarousel = () => {
181193
{release.releaseName}
182194
</p>
183195
<p className="font-mono text-sm text-body-medium">
184-
{formatDate(release.releaseDate)}
196+
{displayDate}
185197
</p>
186198
</div>
187199
</div>
@@ -202,8 +214,9 @@ const ReleaseCarousel = () => {
202214
opts={{
203215
align: "center",
204216
containScroll: false,
217+
direction: "ltr",
205218
loop: false,
206-
startIndex: findLatestReleaseIndex(),
219+
startIndex,
207220
}}
208221
>
209222
<CarouselContent>
@@ -225,9 +238,7 @@ const ReleaseCarousel = () => {
225238
<h2 className="text-4xl font-bold lg:text-6xl">
226239
{release.releaseName}
227240
</h2>
228-
<p className="text-md">
229-
{formatDate(release.releaseDate)}
230-
</p>
241+
<p className="text-md">{getDisplayDate(release)}</p>
231242
</div>
232243

233244
<div>

public/content/community/grants/index.md

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,61 @@ This list is curated by our community. If there's something missing or incorrect
1515
These programs support the broad Ethereum ecosystem by offering grants to a wide scope of projects. These include solutions for scalability, community building, security, privacy, and more. These grants are not specific to any one Ethereum platform and are a good place to start if you're unsure.
1616

1717
- [EF Ecosystem Support Program](https://esp.ethereum.foundation) - _Funding open source projects that benefit Ethereum, with a particular focus on universal tools, infrastructure, research and public goods_
18-
- [Moloch DAO](https://www.molochdao.com/) - _Privacy, layer 2 scaling, client security, and more_
19-
- [DAO Grants](https://docs.google.com/spreadsheets/d/1XHc-p_MHNRdjacc8uOEjtPoWL86olP4GyxAJOFO0zxY/edit#gid=0) - _Google spreadsheet of organizations offering grants_
2018
- [Academic Grants](https://esp.ethereum.foundation/academic-grants) - _Grants to support Ethereum-related academic work_
19+
20+
## Grant list aggregators and platforms {#grant-list-aggregators}
21+
22+
These resources compile and organize various grant opportunities across the Ethereum ecosystem, making it easier to discover funding opportunities that match your project's needs. We've organized them by persona to help you get you started finding the most relevant resources based on your specific funding needs.
23+
24+
### For all grant seekers: Comprehensive directories {#comprehensive-directories}
25+
26+
These general platforms offer broad coverage of grants across the entire Web3 space and are useful starting points for anyone looking for funding:
27+
2128
- [Blockworks Grantfarm](https://blockworks.co/grants/programs) - _Blockworks has compiled a comprehensive directory of all grants, RFPs, and bug bounties._
29+
- [Find Blockchain Grants](https://findblockchaingrants.com/) - _Searchable database of blockchain grants_
30+
- [Grantr](https://grantr.app/) - _Platform for discovering and applying to Web3 grants_
31+
- [Blockchain Grants](https://www.blockchaingrants.org/) - _Directory of blockchain and crypto grants_
32+
33+
### For developers and builders {#for-developers-and-builders}
34+
35+
- [Web3 Grants](https://www.notion.so/Web3-Grants-dae38f9b5f524d36a15aaee1b6fa3089) - _Notion database of Web3 grant opportunities_
36+
- [Grant Programs Viewer](https://airtable.com/shr86elKgWTSCP4AY) - _Public Airtable database of grant programs_
37+
- [Web3 Grants Spreadsheet](https://docs.google.com/spreadsheets/d/1c8koZCI-GLnD8MG-eFcXPOBCNu1v8-aXIfwAAvc7AMc/edit#gid=0) - _Google spreadsheet of Web3 grant opportunities_
38+
39+
### For DeFi projects and financial applications {#for-defi-projects}
40+
41+
- [LlamaoGrants](https://wiki.defillama.com/wiki/LlamaoGrants) - _DeFi Llama's grant program directory_
42+
- [AlphaGrowth Grants](https://alphagrowth.io/crypto-web3-grants-list) - _Comprehensive list of crypto and Web3 grants_
43+
44+
### For DAO contributors and governance innovators {#for-dao-contributors}
45+
46+
Resources for community-driven projects and governance experiments:
47+
48+
- [DAO Grants](https://docs.google.com/spreadsheets/d/1XHc-p_MHNRdjacc8uOEjtPoWL86olP4GyxAJOFO0zxY/edit#gid=0) - _Google spreadsheet of organizations offering grants_
49+
- [MetaGov Database](https://docs.google.com/spreadsheets/d/1e5g-dlWWsK2DZoZGBgfxyfGNSddLk-V7sLEgfPjEhbA/edit#gid=780420708) - _Comprehensive Web3 grants map_
50+
51+
### For entrepreneurs and startups {#for-entrepreneurs-and-startups}
52+
53+
Resources for those building products and seeking investment beyond just grants:
2254

23-
## Project specific {#project-specific}
55+
- [Web3Native](https://www.web3native.co/) - _Directory of Web3 grants, investors, and accelerator programs_
56+
- [Cryptoneur Web3 Grants](https://www.cryptoneur.xyz/web3-grants) - _Platform for finding Web3 project funding_
57+
- [Pentacle Grants](https://pentacle.xyz/grants) - _Grant opportunities in the Web3 space_
2458

25-
These projects have created their own grants for projects aimed at developing and experimenting with their own technology.
59+
### Public goods and impact {#public-goods-and-impact}
2660

27-
- [Aave Grants Program](https://aavegrants.org/)_[Aave](https://aave.com/) grants DAO_
28-
- [Balancer](https://grants.balancer.community/)_[Balancer](https://balancer.fi/) ecosystem fund_
29-
- [Chainlink Grants Program](https://chain.link/community/grants) - _[Chainlink](https://chain.link/) community grants_
30-
- [Decentraland Grants Program](https://governance.decentraland.org/grants/)_[Decentraland](https://decentraland.org/) DAO Metaverse_
31-
- [Lido Ecosystem Grants Organisation (LEGO)](https://lido.fi/lego)_[Lido](https://lido.fi/) finance ecosystem_
32-
- [MetaMask Program](https://metamaskgrants.org/) - _[MetaMask](https://metamask.io/) employee-led grants DAO_
33-
- [SKALE Network Grants Program](https://skale.space/developers#grants) - _[SKALE Network](https://skale.space/) ecosystem_
34-
- [Swarm Foundation Grants Program](https://my.ethswarm.org/grants) - _[Swarm Foundation](https://www.ethswarm.org/) ecosystem_
35-
- [The Graph](https://thegraph.com/ecosystem/grants/)_[The Graph](https://thegraph.com/) ecosystem_
36-
- [Uniswap Grants Program](https://www.uniswapfoundation.org/approach)_[Uniswap](https://uniswap.org/) community_
61+
These programs focus on funding projects that benefit the broader community, public goods, and impact initiatives. These include grant providers, as well as donation platforms utilizing onchain funding allocation mechanisms including [quadratic funding](/defi/#quadratic-funding):
3762

38-
## Quadratic funding {#quadratic-funding}
63+
- [Gitcoin](https://www.gitcoin.co/program) - _Gitcoin Grants utilizes multiple capital allocation mechanisms to fund open source projects and public goods in the Ethereum ecosystem_
64+
- [Octant](https://octant.app/home) - _Public goods funding ecosystem that balances the common good and individual financial empowerment_
65+
- [Giveth](https://giveth.io/) - _Crypto donation platform enabling direct donations from for-good projects with zero added fees_
66+
- [Artizen](https://artizen.fund/) - _Helping creators match fund new projects at the frontier of art, science, technology and culture_
67+
- [Quadratic Accelerator](https://qacc.giveth.io/) - _Start-up accelerator program that uses quadratic funding to support projects that benefit the public good_
3968

40-
The open source roots of Ethereum have led to the growth of an interesting new fundraising model: quadratic funding. This has the potential to improve the way we fund all types of public goods in the future. Quadratic funding makes sure that the projects that receive the most funding are those with the most unique demand. In other words, projects that stand to improve the lives of the most people. [More on quadratic funding.](/defi/#quadratic-funding)
69+
### Additional resources {#additional-resources}
4170

42-
- [Gitcoin](https://gitcoin.co/grants)
43-
- [clr.fund](https://clr.fund/)
71+
- [Web3 Summits Grants](https://www.web3summits.io/grants) - _Grant opportunities from Web3 Summits_
72+
- [Anke's Directory](https://docs.google.com/spreadsheets/d/1IdCCG-U7cGsih_nCNt7Yo4wXstZdCip1UKWbCK0qCZk/edit#gid=938115517) - _Web3 grant program directory_
4473

4574
## Work in Ethereum {#work-in-ethereum}
4675

src/components/Homepage/useHome.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import type { CodeExample } from "@/lib/interfaces"
77

88
import { useBentoBox } from "@/components/Homepage/useBentoBox"
99
import BlockHeap from "@/components/icons/block-heap.svg"
10+
import BuildAppsIcon from "@/components/icons/build-apps.svg"
1011
import EthGlyphIcon from "@/components/icons/eth-glyph.svg"
1112
import EthTokenIcon from "@/components/icons/eth-token.svg"
1213
import PickWalletIcon from "@/components/icons/eth-wallet.svg"
13-
import ChooseNetworkIcon from "@/components/icons/network-layers.svg"
1414
import TryAppsIcon from "@/components/icons/phone-homescreen.svg"
1515
import RoadmapSign from "@/components/icons/roadmap-sign.svg"
1616
import Whitepaper from "@/components/icons/whitepaper.svg"
@@ -103,14 +103,6 @@ export const useHome = () => {
103103
className: "text-accent-a hover:text-accent-a-hover",
104104
eventName: "get eth",
105105
},
106-
{
107-
label: t("page-index:page-index-cta-networks-label"),
108-
description: t("page-index:page-index-cta-networks-description"),
109-
href: "/layer-2/", // TODO: Update with new networks page when ready
110-
Svg: ChooseNetworkIcon,
111-
className: "text-accent-b hover:text-accent-b-hover",
112-
eventName: "L2",
113-
},
114106
{
115107
label: t("page-index:page-index-cta-dapps-label"),
116108
description: t("page-index:page-index-cta-dapps-description"),
@@ -122,6 +114,14 @@ export const useHome = () => {
122114
),
123115
eventName: "dapps",
124116
},
117+
{
118+
label: t("page-index:page-index-cta-build-apps-label"),
119+
description: t("page-index:page-index-cta-build-apps-description"),
120+
href: "/developers/",
121+
Svg: BuildAppsIcon,
122+
className: "text-accent-b hover:text-accent-b-hover",
123+
eventName: "build apps",
124+
},
125125
]
126126

127127
const popularTopics = [

0 commit comments

Comments
 (0)