Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion common/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ export const Y2024 = makePath('/2024')

export const NEWS = makePath("/news")

export const PARTNER_PACK = makePath('/partner-pack')
export const PARTNER_PACK = makePath('/partner-pack')

export const SECURITY_CHALLENGE = makePath('/security-challenge')
16 changes: 15 additions & 1 deletion components/header/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import GitHubLogo from '../../public/icons/github-logo'
import IconCalendar from '../../public/icons/calendar'
import IconBooks from '../../public/icons/books'
import BoxGift from '../../public/icons/box-gift'
import IconShield from '../../public/icons/shield'
import { BREAKPOINTS } from '../../common/constants'

const Header = () => {
Expand Down Expand Up @@ -81,7 +82,20 @@ const Header = () => {
</li>
<li>
<Link

href={ROUTES.SECURITY_CHALLENGE.getPath(year)}
aria-label={getLiteral('navigation:security-challenge')}
className={clsx('header__link', {
['is-active']: pathname === ROUTES.SECURITY_CHALLENGE.getPath(year),
})}
>
<IconShield />
<span className="header__link-text">
{getLiteral('navigation:security-challenge')}
</span>
</Link>
</li>
<li>
<Link
href={ROUTES.SCHEDULE.getPath(year)}
aria-label={getLiteral('navigation:schedule')}
className={clsx('header__link', {
Expand Down
1 change: 1 addition & 0 deletions content/commons.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"navigation:schedule": "Schedule",
"navigation:library": "Library",
"navigation:partner-pack": "Partner Pack",
"navigation:security-challenge": "Challenge",

"page:title": "Maintainer Month",
"page:title-mobile": "MM",
Expand Down
131 changes: 131 additions & 0 deletions pages/security-challenge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import Head from 'next/head'
import { useEffect } from 'react'
import { useBackground } from '../contexts/BackgroundContext'
import { marked } from 'marked'

export default function SecurityChallenge() {
const { setAnimationStep } = useBackground()

useEffect(() => {
// Use a distinctive animation step for Security Challenge
setAnimationStep(3)
}, [setAnimationStep])

// Skills course data
const skillsCourses = [
{
title: "Secure Your Repository's Supply Chain",
description: "Learn how to secure your repository's supply chain with proper dependency management",
link: "https://github.com/skills/secure-repository-supply-chain",
icon: "🔒"
},
{
title: "Introduction to Secret Scanning",
description: "Learn how to prevent accidental secret leaks and secure your repositories",
link: "https://github.com/skills/introduction-to-secret-scanning",
icon: "🔍"
},
{
title: "Introduction to Repository Management",
description: "Learn best practices for effective repository management and security",
link: "https://github.com/skills/introduction-to-repository-management",
icon: "📚"
}
]

// Convert markdown content to HTML
const content = marked(`
This Maintainer Month, we’re inviting open source maintainers to build their security skills through a hands-on challenge. Complete **three free GitHub Skills courses** and get a free voucher to earn your [GitHub Advanced Security certification](https://examregistration.github.com/certification/GHAS).

## How it Works

### Step 1: Complete these 3 GitHub Skills
Each one takes about 1 hour
`)


// Convert markdown content to HTML
const content_end = marked(`
### Step 2: Submit the Completion Form
Once you’ve finished all three, [fill out this form](https://forms.gle/HhPm3VofYDCiXeBB9) to share your progress and **claim your free certification voucher**.

🗓️ Deadline: Submit your form by May 31, 2025 to be eligible for the voucher.

### Step 3. Get Certified!
We’ll email you a voucher to register for the GitHub Advanced Security certification (valued at $99 USD) and showcase your expertise - for free!

## Why This Matters
Maintainers often carry the responsibility of software security—but don’t always have access to the right training or recognition. This challenge helps you build real-world skills and earn a GitHub-backed credential that showcases your expertise.

## FAQ
#### Who can participate?
Anyone! While we’re celebrating open source maintainers, this challenge is open to all contributors who want to grow their security skills.

#### How long does it take?
Each GitHub Skill takes about 1 hour, so expect to spend around 3 hours total.

#### How many vouchers are available?
Vouchers are limited and offered on a first-come, first-served basis. [Submit your form](https://forms.gle/HhPm3VofYDCiXeBB9) by May 31 to qualify!

#### I have more questions!
If you have any questions about the challenge, please reach out to us at [maintainermonth@github.com](mailto:maintainermonth@github.com).
`)
return (
<div>
<Head>
<title>Security Challenge - Maintainer Month 2025</title>
<meta name="description" content="Complete security courses and earn a free GitHub Advanced Security certification during Maintainer Month 2025!" />

{/* <!-- Facebook Meta Tags --> */}
<meta property="og:title" content="Security Challenge - Maintainer Month 2025" />
<meta property="og:description" content="Complete security courses and earn a free GitHub Advanced Security certification during Maintainer Month 2025!" />
<meta
property="og:image"
content="https://maintainermonth.github.com/images/og/generic.png"
/>

{/* <!-- Twitter Meta Tags --> */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Security Challenge - Maintainer Month 2025" />
<meta name="twitter:description" content="Complete security courses and earn a free GitHub Advanced Security certification during Maintainer Month 2025!" />
<meta
name="twitter:image"
content="https://maintainermonth.github.com/images/og/generic.png"
/>
</Head>

<div className="container page-content partner-pack">
<div className="partner-pack__hero">
<h1 className="partner-pack__title">Security Challenge</h1>
<p className="partner-pack__subtitle">Secure Your Open Source Projects & Earn a Free Certification!</p>
</div>
<div className="partner-pack__content">
<div dangerouslySetInnerHTML={{ __html: content }}></div>
<div className="offers-grid-container">
<div className="offers-grid">
{skillsCourses.map((course, index) => (
<div key={index} className="offer-card">
<div className="offer-card__logo">
<span style={{ fontSize: '3rem' }}>{course.icon}</span>
</div>
<div className="offer-card__description">
<h3>{course.title}</h3>
<p>{course.description}</p>
</div>
<div className="offer-card__cta-container">
<a href={course.link} className="offer-card__cta" target="_blank" rel="noopener noreferrer">
Start this course
</a>
</div>
</div>
))}
</div>
</div>

<div dangerouslySetInnerHTML={{ __html: content_end }}></div>

</div>
</div>
</div>
)
}
32 changes: 32 additions & 0 deletions public/icons/shield.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const IconShield = () => {
return (
<svg
className="icon-shield"
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M11.9999 2.5C11.9999 2.5 5.25 5.25 2.50002 5.25C2.5 5.25 2 12.5 2.5 15C3 17.5 4.99997 19 6.99997 20.5C8.99997 22 11.9999 23 11.9999 23C11.9999 23 15 22 17 20.5C19 19 21 17.5 21.5 15C22 12.5 21.5 5.25 21.5 5.25C18.75 5.25 11.9999 2.5 11.9999 2.5Z"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
<path
d="M9 12L11 14L16 9"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}

export default IconShield