Skip to content

Commit 7af6156

Browse files
authored
Merge pull request #12464 from ethereum/contributing-gfi
Display GFI in /contributing page
2 parents 951f157 + 1fc5ee1 commit 7af6156

File tree

8 files changed

+194
-52
lines changed

8 files changed

+194
-52
lines changed

public/content/contributing/index.md

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,53 @@ lang: en
66

77
# Contributing to ethereum.org 🦄 {#contributing-to-ethereumorg}
88

9-
The ethereum.org website, like Ethereum more broadly, is an open-source project. So if you want to help improve [our portal to Ethereum](/about/), here's how you can help out.
9+
Ethereum.org is an open-source run project with **12 000+** contributors that help translate, write, design and maintain the website.
1010

11-
<InfoBanner shouldCenter emoji=":tada:">
12-
Claim your POAP token! If you contributed to ethereum.org in 2022, there's a unique POAP waiting for you.{" "}
13-
<a href="#poap">More on POAPs</a>
14-
</InfoBanner>
11+
We are a welcoming community that will help you grow and educate in the Ethereum ecosystem while also meaningfully contribute and get relevant practical experience!
1512

1613
## Ways to contribute {#ways-to-contribute}
1714

18-
- [Work on an open issue](https://github.com/ethereum/ethereum-org-website/issues)
19-
_– Work we've identified that needs doing_
20-
- [Join the translation program](/contributing/translation-program/)
21-
_– Help us bring ethereum.org to new languages_
22-
- [Help design the website](/contributing/design/)
23-
_– Designers of all levels can contribute to improve the website_
24-
- [Add community resources](/contributing/content-resources/)
25-
_– Add a helpful article or resource to a relevant page_
26-
- [Add a product](/contributing/adding-products/)
27-
_– Add a dapp or wallet to a relevant page_
28-
- [Add developer tools](/contributing/adding-developer-tools/)
29-
_– Add a developer tool to a relevant page_
30-
- [Add an exchange](/contributing/adding-exchanges/)
31-
_– Add an exchange to our [exchange finder](/get-eth/#country-picker)_
32-
- [Improve our research](https://www.notion.so/efdn/Ethereum-org-User-Persona-Memo-b44dc1e89152457a87ba872b0dfa366c)
33-
_– Let us know your feedback on our research or contribute your own_
34-
- [Request a feature](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=)
35-
_– Let us know about any ideas you have for a new feature or design_
36-
- [Add a glossary term](/contributing/adding-glossary-terms)
37-
_– Help us continue to expand the Ethereum [glossary](/glossary/)_
38-
- [Create/edit content](/contributing/#how-to-update-content)
39-
_– Suggest new pages or make tweaks to what's here already_
40-
- [Add a layer 2](/contributing/adding-layer-2s/)
41-
_– Add a layer 2 to a relevant page_
42-
- [Add a staking product or service](/contributing/adding-staking-products/)
43-
_– Add a project that helps facilitate solo staking, pooled staking, or staking as a service_
44-
- [Add a wallet](/contributing/adding-wallets/)
45-
_– Add a wallet for the [find wallets page](/wallets/find-wallet/)_
46-
- [Suggest a project for our DeSci page](/contributing/adding-desci-projects/)
47-
_- Add a project built on Ethereum that contributes to decentralized science_
48-
- [Quizzes](/contributing/quizzes/) _- Add, update, and delete quiz question banks for a relevant page_
49-
- [Suggest a design resource](/contributing/design/adding-design-resources/) _- Add, update, and delete helpful design resources_
50-
51-
_Any questions?_ 🤔 Reach out on our [Discord server](https://discord.gg/ethereum-org)
15+
**Translations**
16+
- [Join the translation program](/contributing/translation-program/) – Help us bring ethereum.org to new languages
17+
18+
**Development**
19+
- [Work on an open issue](https://github.com/ethereum/ethereum-org-website/issues) – Work we've identified that needs doing
20+
21+
**Design**
22+
- [Help design the website](/contributing/design/) Designers of all levels can contribute to improve the website
23+
24+
**Content**
25+
- [Create/edit content](/contributing/#how-to-update-content) – Suggest new pages or make tweaks to what's here already
26+
- [Add community resources](/contributing/content-resources/) – Add a helpful article or resource to a relevant page
27+
- [Suggest a design resource](/contributing/design/adding-design-resources/) – Add, update, and delete helpful design resources
28+
- [Add a glossary term](/contributing/adding-glossary-terms/) – Help us continue to expand the Ethereum [glossary](/glossary/)
29+
- [Quizzes](/contributing/quizzes/) – Add, update, and delete quiz question banks for a relevant page
30+
31+
**Feature ideas**
32+
- [Request a feature](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) – Let us know about any ideas you have for a new feature or design
33+
34+
**Product listings**
35+
- [Add an exchange](/contributing/adding-exchanges/) – Add an exchange to our [exchange finder](/get-eth/#country-picker)
36+
- [Add a product](/contributing/adding-products/) – Add a dapp or wallet to a relevant page
37+
- [Add developer tools](/contributing/adding-developer-tools/) – Add a developer tool to a relevant page
38+
- [Add a layer 2](/contributing/adding-layer-2s/) – Add a layer 2 to a relevant page
39+
- [Add a staking product or service](/contributing/adding-staking-products/) – Add a project that helps facilitate solo staking, pooled staking, or staking as a service
40+
- [Add a wallet](/contributing/adding-wallets/) – Add a wallet for the [find wallets page](/wallets/find-wallet/)
41+
- [Suggest a project for our DeSci page](/contributing/adding-desci-projects/) – Add a project built on Ethereum that contributes to decentralized science
42+
43+
Any questions? 🤔 Join our [Discord server](https://discord.gg/ethereum-org)
44+
45+
## Good first tasks to start contributing
46+
47+
These are few current tasks that you could help us solve and take responsibility for. For most you will need GitHub account as most changes to the website are made through GitHub.
48+
49+
<IssuesList issues={gfissues} my={8} />
50+
51+
<ButtonLink href="https://github.com/ethereum/ethereum-org-website/issues">See all tasks</ButtonLink>
5252

5353
## How to work on ethereum.org {#how-to-update-content}
5454

55-
Whether you're adding to the site, creating content or working on open issues, you'll need a [GitHub](https://github.com) account.
55+
If you wish to contribute in the [Translation Program](/contributing/translation-program/), we ask you to create an account on [Crowdin](https://crowdin.com/project/ethereum-org). For everything else – adding or editing content or visuals to the website, fixing bugs, working on open tasks – you will need a [GitHub](https://github.com/) account.
5656

5757
All updates are made via the GitHub PR process. This means you create a local copy of the website, make your changes and request to merge your changes. If you've never done this before, follow the instructions at the bottom of our [GitHub repository](https://github.com/ethereum/ethereum-org-website).
5858

@@ -84,25 +84,25 @@ Only use your original work or content that you have permission to use when cont
8484

8585
We have low barrier to entry issues on our GitHub repository specifically designed for developers who are new to open-source labelled [good first issue](https://github.com/ethereum/ethereum-org-website/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
8686

87-
## Claim your contributor POAP {#poap}
87+
## Claim your Onchain Achievement Token (OAT) {#oat}
8888

89-
If your contribution gets merged into ethereum.org, we'll mint you a unique contributors POAP. A Proof of Attendance Protocol (POAP) token is on-chain proof that you helped make the ecosystem a little more awesome.
89+
If your contribution gets merged into ethereum.org, you will have a change to claim a special badge on [Galxe](https://galxe.com/ethereumorg/). An Onchain Achievement Token (OAT) is a proof that you helped make the ecosystem a little more awesome.
9090

91-
[More on POAPs](https://www.poap.xyz/)
92-
93-
### How to claim {#how-to-claim}
91+
[More on OATs](https://help.galxe.com/en/articles/7067290-galxe-oats-reward-and-celebrate-achievements)
9492

93+
### How to claim
9594
1. Join our [Discord server](https://discord.gg/ethereum-org).
9695
2. Paste a link to your contribution in the `#🥇 | proof-of-contribution` channel
97-
3. Wait for a member of our team to send you a link to your POAP.
98-
4. Claim your POAP!
96+
3. Wait for a member of our team to send you a link to your OAT.
97+
4. Claim your OAT!
9998

100-
You should only use self-custody wallets to claim POAPs. Do not use exchange accounts or other accounts you do not hold the private keys to, as these will not allow you to access and manage your POAPs.
99+
You should only use self-custody wallets to claim OATs. Do not use exchange accounts or other accounts you do not hold the private keys to, as these will not allow you to access and manage your OATs.
101100

102101
## Claim your GitPOAP {#claim-gitpoap}
103102

104103
GitPOAP will also automatically recognize your merged contribution and let you mint a separate unique contributors POAP on their platform itself!
105104

105+
106106
### How to claim {#how-to-claim}
107107

108108
1. Visit [GitPOAP](https://www.gitpoap.io).

src/components/Contributors.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect, useState } from "react"
12
import shuffle from "lodash/shuffle"
23
import { Box, Flex, Image, LinkBox, LinkOverlay } from "@chakra-ui/react"
34

@@ -14,8 +15,14 @@ export interface Contributor {
1415
contributions: Array<string>
1516
}
1617

18+
const allContributors = JSON.parse(data)
19+
1720
const Contributors = () => {
18-
const contributorsList = shuffle(JSON.parse(data).contributors)
21+
const [contributorsList, setContributorsList] = useState<Contributor[]>([])
22+
23+
useEffect(() => {
24+
setContributorsList(shuffle(allContributors.contributors))
25+
}, [])
1926

2027
return (
2128
<>

src/components/IssuesList/index.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import Emoji from "react-emoji-render"
2+
import {
3+
Avatar,
4+
Flex,
5+
HStack,
6+
SimpleGrid,
7+
SimpleGridProps,
8+
Stack,
9+
Text,
10+
} from "@chakra-ui/react"
11+
12+
import type { GHIssue } from "@/lib/types"
13+
14+
import InlineLink from "../Link"
15+
import Tag from "../Tag"
16+
17+
type IssuesListProps = SimpleGridProps & {
18+
issues: GHIssue[]
19+
}
20+
21+
const IssuesList = ({ issues, ...props }: IssuesListProps) => {
22+
return (
23+
<SimpleGrid columns={[1, null, 2]} spacing={4} {...props}>
24+
{issues.map((issue) => (
25+
<Stack
26+
key={issue.title}
27+
p={4}
28+
spacing={4}
29+
border="1px solid"
30+
borderColor="body.light"
31+
borderRadius="md"
32+
>
33+
<Stack spacing={2}>
34+
<HStack spacing={2}>
35+
<Avatar
36+
name={issue.user.login}
37+
src={issue.user.avatar_url}
38+
w="32px"
39+
h="32px"
40+
/>
41+
<Text size="sm">by {issue.user.login}</Text>
42+
</HStack>
43+
44+
<InlineLink href={issue.html_url} textDecor="none">
45+
{issue.title}
46+
</InlineLink>
47+
</Stack>
48+
<Flex flexWrap="wrap" gap="1">
49+
{issue.labels.map((label) => {
50+
return (
51+
<Tag
52+
key={label.id}
53+
label={<Emoji text={label.name} />}
54+
variant="outline"
55+
/>
56+
)
57+
})}
58+
</Flex>
59+
</Stack>
60+
))}
61+
</SimpleGrid>
62+
)
63+
}
64+
65+
export default IssuesList

src/components/MdComponents.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import Emoji from "./Emoji"
4040
import ExpandableCard from "./ExpandableCard"
4141
import FeaturedText from "./FeaturedText"
4242
import InfoBanner from "./InfoBanner"
43+
import IssuesList from "./IssuesList"
4344
import LocaleDateTime from "./LocaleDateTime"
4445
import MainArticle from "./MainArticle"
4546
import VideoIframe from "./VideoIframe"
@@ -282,6 +283,7 @@ export const reactComponents = {
282283
Page,
283284
QuizWidget: StandaloneQuizWidget,
284285
StyledButtonDropdown,
286+
IssuesList,
285287
Title,
286288
YouTube,
287289
}

src/components/Tag/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from "@chakra-ui/react"
1111

1212
export interface EthTagProps extends TagProps {
13-
label: string
13+
label: React.ReactNode
1414
isCloseable?: boolean
1515
leftIcon?: any
1616
rightIcon?: any

src/lib/api/fetchGFIs.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { GHIssue } from "../types"
2+
3+
const owner = "ethereum"
4+
const repo = "ethereum-org-website"
5+
const label = "good first issue"
6+
7+
export const fetchGFIs = async () => {
8+
const url = new URL(`https://api.github.com/repos/${owner}/${repo}/issues`)
9+
url.searchParams.append("labels", label)
10+
url.searchParams.append("state", "open")
11+
url.searchParams.append("sort", "created")
12+
url.searchParams.append("direction", "desc")
13+
url.searchParams.append("assignee", "none")
14+
url.searchParams.append("per_page", "10")
15+
16+
try {
17+
const response = await fetch(url, {
18+
headers: {
19+
Authorization: `token ${process.env.NEXT_PUBLIC_GITHUB_TOKEN_READ_ONLY}`,
20+
Accept: "application/vnd.github.v3+json",
21+
},
22+
})
23+
24+
if (!response.ok) {
25+
throw new Error(
26+
`GitHub API responded with ${response.status}: ${response.statusText}`
27+
)
28+
}
29+
30+
return (await response.json()) as GHIssue[]
31+
} catch (error) {
32+
console.error(error)
33+
return []
34+
}
35+
}

src/lib/types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,22 @@ export type FooterLinkSection = {
647647
title: TranslationKey
648648
links: FooterLink[]
649649
}
650+
651+
// GitHub API
652+
export type GHIssue = {
653+
title: string
654+
html_url: string
655+
created_at: string
656+
user: {
657+
login: string
658+
html_url: string
659+
avatar_url: string
660+
}
661+
labels: GHLabel[]
662+
}
663+
664+
export type GHLabel = {
665+
id: number
666+
name: string
667+
color: string
668+
}

src/pages/[...slug].tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { dateToString } from "@/lib/utils/date"
3131
import { getLastDeployDate } from "@/lib/utils/getLastDeployDate"
3232
import { getLastModifiedDate } from "@/lib/utils/gh"
3333
import { getContent, getContentBySlug } from "@/lib/utils/md"
34+
import { runOnlyOnce } from "@/lib/utils/runOnlyOnce"
3435
import { remapTableOfContents } from "@/lib/utils/toc"
3536
import {
3637
filterRealLocales,
@@ -53,6 +54,7 @@ import {
5354
useCasesComponents,
5455
UseCasesLayout,
5556
} from "@/layouts"
57+
import { fetchGFIs } from "@/lib/api/fetchGFIs"
5658
import rehypeHeadingIds from "@/lib/rehype/rehypeHeadingIds"
5759
import rehypeImg from "@/lib/rehype/rehypeImg"
5860
import remarkInferToc from "@/lib/rehype/remarkInferToc"
@@ -104,8 +106,14 @@ export const getStaticPaths = (({ locales }) => {
104106
type Props = Omit<Parameters<LayoutMappingType[Layout]>[0], "children"> &
105107
SSRConfig & {
106108
mdxSource: MDXRemoteSerializeResult
109+
gfissues: Awaited<ReturnType<typeof fetchGFIs>>
107110
}
108111

112+
// Fetch external API data once to avoid hitting rate limit
113+
const gfIssuesDataFetch = runOnlyOnce(async () => {
114+
return await fetchGFIs()
115+
})
116+
109117
export const getStaticProps = (async (context) => {
110118
const params = context.params!
111119
const { locale } = context
@@ -170,6 +178,8 @@ export const getStaticProps = (async (context) => {
170178

171179
const requiredNamespaces = getRequiredNamespacesForPage(slug, layout)
172180

181+
const gfissues = await gfIssuesDataFetch()
182+
173183
return {
174184
props: {
175185
...(await serverSideTranslations(locale!, requiredNamespaces)),
@@ -183,22 +193,26 @@ export const getStaticProps = (async (context) => {
183193
timeToRead: Math.round(timeToRead.minutes),
184194
tocItems,
185195
crowdinContributors,
196+
gfissues,
186197
},
187198
}
188199
}) satisfies GetStaticProps<Props, Params>
189200

190201
const ContentPage: NextPageWithLayout<
191202
InferGetStaticPropsType<typeof getStaticProps>
192-
> = ({ mdxSource, layout }) => {
203+
> = ({ mdxSource, layout, gfissues }) => {
193204
// TODO: Address component typing error here (flip `FC` types to prop object types)
194205
// @ts-expect-error
195206
const components: Record<string, React.ReactNode> = {
196207
...mdComponents,
197208
...componentsMapping[layout],
198209
}
210+
211+
// Global scope for MDX components
212+
const scope = { gfissues }
199213
return (
200214
<>
201-
<MDXRemote {...mdxSource} components={components} />
215+
<MDXRemote {...mdxSource} components={components} scope={scope} />
202216
</>
203217
)
204218
}

0 commit comments

Comments
 (0)