Skip to content

Commit 0492e88

Browse files
committed
feat: add Opportunity Open Source page and update sitemap and site config
1 parent 83917a0 commit 0492e88

4 files changed

Lines changed: 280 additions & 0 deletions

File tree

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import type { Metadata } from "next"
2+
import Link from "next/link"
3+
import { ArrowRight, CalendarDays, ExternalLink, MapPin } from "lucide-react"
4+
5+
import { PageHero } from "@/components/page-hero"
6+
import { Linkedin } from "lucide-react"
7+
import { getSiteUrl } from "@/lib/site"
8+
import {
9+
editions,
10+
opportunityOpenSource as oos,
11+
type ConferenceEdition,
12+
} from "@/data/opportunity-open-source"
13+
14+
export const metadata: Metadata = {
15+
title: "Opportunity Open Source | OpenPrinting",
16+
description:
17+
"Opportunity Open Source is OpenPrinting's annual FOSS conference in India — talks, workshops and hackathons that bring students into open source. See past editions and the next one.",
18+
alternates: { canonical: getSiteUrl("/opportunity-open-source/") },
19+
openGraph: {
20+
title: "Opportunity Open Source | OpenPrinting",
21+
description:
22+
"OpenPrinting's annual free and open source software conference in India. Past editions and the upcoming one.",
23+
url: getSiteUrl("/opportunity-open-source/"),
24+
type: "website",
25+
},
26+
}
27+
28+
function EditionCard({ edition }: { edition: ConferenceEdition }) {
29+
return (
30+
<div className="flex h-full flex-col rounded-xl border border-border bg-card p-6 shadow-sm">
31+
<div className="flex items-center justify-between">
32+
<span className="text-2xl font-bold tracking-tight text-foreground">
33+
{oos.shortName} {edition.edition}
34+
</span>
35+
{edition.upcoming ? (
36+
<span className="inline-flex items-center rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2.5 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-300">
37+
Upcoming
38+
</span>
39+
) : (
40+
<span className="text-sm text-muted-foreground">{edition.year}</span>
41+
)}
42+
</div>
43+
44+
<dl className="mt-4 space-y-2 text-sm">
45+
<div className="flex items-center gap-2 text-foreground">
46+
<MapPin className="h-4 w-4 shrink-0 text-muted-foreground" />
47+
<span>
48+
{edition.venue} <span className="text-muted-foreground">· {edition.location}</span>
49+
</span>
50+
</div>
51+
<div className="flex items-center gap-2 text-foreground">
52+
<CalendarDays className="h-4 w-4 shrink-0 text-muted-foreground" />
53+
<span>{edition.dates}</span>
54+
</div>
55+
</dl>
56+
57+
{edition.summary ? (
58+
<p className="mt-4 text-sm leading-6 text-muted-foreground">{edition.summary}</p>
59+
) : null}
60+
61+
<div className="mt-auto flex flex-wrap gap-x-5 gap-y-2 pt-5 text-sm">
62+
{edition.recapUrl ? (
63+
<Link
64+
href={edition.recapUrl}
65+
className="inline-flex items-center gap-1 font-medium text-primary hover:underline"
66+
>
67+
{edition.upcoming ? "Announcement" : "Read the recap"}
68+
<ArrowRight className="h-4 w-4" />
69+
</Link>
70+
) : null}
71+
{edition.scheduleUrl ? (
72+
<a
73+
href={edition.scheduleUrl}
74+
target="_blank"
75+
rel="noopener noreferrer"
76+
className="inline-flex items-center gap-1 text-muted-foreground hover:text-foreground hover:underline"
77+
>
78+
Schedule
79+
<ExternalLink className="h-3.5 w-3.5" />
80+
</a>
81+
) : null}
82+
</div>
83+
</div>
84+
)
85+
}
86+
87+
export default function OpportunityOpenSourcePage() {
88+
const next = editions.find((e) => e.upcoming)
89+
const past = editions.filter((e) => !e.upcoming)
90+
91+
return (
92+
<>
93+
<PageHero
94+
title="Opportunity Open Source"
95+
description="OpenPrinting's annual free and open source software conference in India."
96+
/>
97+
98+
<main className="min-h-screen bg-background text-foreground pt-16 pb-20">
99+
<div className="mx-auto max-w-5xl px-4 sm:px-6 lg:px-8 space-y-16">
100+
<section className="space-y-4">
101+
<p className="text-base leading-relaxed text-foreground sm:text-lg">{oos.mission}</p>
102+
<p className="text-sm leading-relaxed text-muted-foreground">{oos.origin}</p>
103+
<a
104+
href={oos.linkedin}
105+
target="_blank"
106+
rel="noopener noreferrer"
107+
className="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline"
108+
>
109+
<Linkedin className="h-4 w-4" />
110+
Follow Opportunity Open Source on LinkedIn
111+
<ExternalLink className="h-3.5 w-3.5" />
112+
</a>
113+
</section>
114+
115+
{next ? (
116+
<section>
117+
<h2 className="mb-4 text-sm font-semibold uppercase tracking-[0.18em] text-muted-foreground">
118+
Next edition
119+
</h2>
120+
<div className="relative overflow-hidden rounded-2xl border border-border bg-card p-8 shadow-sm">
121+
<div className="absolute inset-0 grid-pattern opacity-40" aria-hidden />
122+
<div className="relative">
123+
<div className="flex flex-wrap items-center gap-3">
124+
<h3 className="text-3xl font-bold tracking-tight">
125+
{oos.shortName} {next.edition}
126+
</h3>
127+
<span className="inline-flex items-center rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2.5 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-300">
128+
Upcoming
129+
</span>
130+
</div>
131+
<div className="mt-4 flex flex-col gap-2 text-sm sm:flex-row sm:gap-8">
132+
<span className="inline-flex items-center gap-2">
133+
<MapPin className="h-4 w-4 text-muted-foreground" />
134+
{next.venue} · {next.location}
135+
</span>
136+
<span className="inline-flex items-center gap-2">
137+
<CalendarDays className="h-4 w-4 text-muted-foreground" />
138+
{next.dates}
139+
</span>
140+
</div>
141+
{next.summary ? (
142+
<p className="mt-4 max-w-2xl text-sm leading-6 text-muted-foreground">
143+
{next.summary}
144+
</p>
145+
) : null}
146+
{next.recapUrl ? (
147+
<Link
148+
href={next.recapUrl}
149+
className="mt-6 inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline"
150+
>
151+
Read the announcement
152+
<ArrowRight className="h-4 w-4" />
153+
</Link>
154+
) : null}
155+
</div>
156+
</div>
157+
</section>
158+
) : null}
159+
160+
<section>
161+
<h2 className="mb-6 text-2xl font-bold tracking-tight">Past editions</h2>
162+
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
163+
{past.map((edition) => (
164+
<EditionCard key={edition.edition} edition={edition} />
165+
))}
166+
</div>
167+
</section>
168+
169+
<section className="rounded-2xl border border-border bg-muted/30 p-8">
170+
<h2 className="text-2xl font-bold tracking-tight">Get involved</h2>
171+
<p className="mt-3 max-w-2xl text-sm leading-6 text-muted-foreground">
172+
Want to speak, host a future edition, sponsor the conference, or just attend? Follow the
173+
conference on LinkedIn for announcements and calls for proposals, or get in touch with the
174+
OpenPrinting team.
175+
</p>
176+
<div className="mt-6 flex flex-wrap gap-3 text-sm">
177+
<a
178+
href={oos.linkedin}
179+
target="_blank"
180+
rel="noopener noreferrer"
181+
className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-foreground hover:bg-accent"
182+
>
183+
<Linkedin className="h-4 w-4" />
184+
LinkedIn
185+
</a>
186+
<Link
187+
href="/contact"
188+
className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-foreground hover:bg-accent"
189+
>
190+
Contact us
191+
</Link>
192+
<Link
193+
href="/gsoc"
194+
className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-foreground hover:bg-accent"
195+
>
196+
Google Summer of Code
197+
</Link>
198+
<Link
199+
href="/sponsors"
200+
className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-foreground hover:bg-accent"
201+
>
202+
Sponsors &amp; donations
203+
</Link>
204+
</div>
205+
</section>
206+
</div>
207+
</main>
208+
</>
209+
)
210+
}

app/sitemap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const STATIC_ROUTES = [
3737
"/contact/",
3838
"/donations/",
3939
"/sponsors/",
40+
"/opportunity-open-source/",
4041
"/contribute/",
4142
"/contribute-website/",
4243
"/codeofconduct/",

config/site.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export const siteConfig: SiteConfig = {
143143
{ name: "Google Season of Docs", href: "/gsod" },
144144
{ name: "Contribute", href: "/contribute" },
145145
{ name: "Sponsors", href: "/sponsors" },
146+
{ name: "Opportunity Open Source", href: "/opportunity-open-source" },
146147
],
147148
},
148149
{

data/opportunity-open-source.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
export interface ConferenceEdition {
2+
edition: string;
3+
year: number;
4+
venue: string;
5+
location: string;
6+
dates: string;
7+
upcoming?: boolean;
8+
scheduleUrl?: string;
9+
recapUrl?: string;
10+
summary?: string;
11+
}
12+
13+
export const opportunityOpenSource = {
14+
name: "Opportunity Open Source",
15+
shortName: "OOSC",
16+
linkedin: "https://www.linkedin.com/company/opportunityopensource/",
17+
mission:
18+
"Opportunity Open Source is a conference held every year at a university or institute in India to showcase free and open source software (FOSS) and to motivate students, professors, and researchers to take part in its development — by contributing code, design, documentation, and more. Each edition features talks and hands-on workshops across a wide range of FOSS topics, and often a hackathon. To give people all over India the chance to take part, every edition is held at a different location.",
19+
origin:
20+
"It grew out of the wish of OpenPrinting's Till Kamppeter and Aveek Basu to meet their Google Summer of Code contributors in person and to motivate more people to join the free and open source software community. The conferences have since become a major source of new OpenPrinting and GSoC contributors.",
21+
} as const;
22+
23+
export const editions: ConferenceEdition[] = [
24+
{
25+
edition: "4.0",
26+
year: 2026,
27+
venue: "IIIT Allahabad",
28+
location: "Prayagraj, Uttar Pradesh, India",
29+
dates: "August 28–30, 2026",
30+
upcoming: true,
31+
recapUrl: "/OpenPrinting-News-Opportunity-Open-Source-4.0/",
32+
summary:
33+
"The fourth edition, hosted together with the Google Developer Group (GDG) at IIIT Allahabad.",
34+
},
35+
{
36+
edition: "3.0",
37+
year: 2025,
38+
venue: "IIT Kanpur",
39+
location: "Kanpur, India",
40+
dates: "September 5–7, 2025",
41+
scheduleUrl: "https://events.canonical.com/event/134/timetable/",
42+
recapUrl: "/OpenPrinting-News-Opportunity-Open-Source-3.0-in-the-IIT-Kanpur,-India/",
43+
summary:
44+
"A return to Kanpur with a wide range of sessions on FOSS, OpenPrinting, AI/ML and more, plus a hackathon day.",
45+
},
46+
{
47+
edition: "2.0",
48+
year: 2024,
49+
venue: "IIT Kanpur",
50+
location: "Kanpur, India",
51+
dates: "August 24–26, 2024",
52+
scheduleUrl: "https://events.canonical.com/event/89/",
53+
recapUrl: "/OpenPrinting-News-August-2024/#opportunity-open-source-in-iit-kanpur",
54+
summary:
55+
"The second edition, with around 50 sessions and a 12-hour hackathon on the final day.",
56+
},
57+
{
58+
edition: "1.0",
59+
year: 2023,
60+
venue: "IIT Mandi",
61+
location: "Mandi, India",
62+
dates: "September 2023",
63+
scheduleUrl: "https://events.canonical.com/event/35/",
64+
recapUrl: "/OpenPrinting-News-September-2023/#opportunitiy-open-source-in-the-iit-mandi-india",
65+
summary:
66+
"The first edition, where about a hundred students of IIT Mandi joined the talks and workshops.",
67+
},
68+
];

0 commit comments

Comments
 (0)