From 14e9332686694fadcbfb7d191526c5f59a7fff89 Mon Sep 17 00:00:00 2001 From: Aman Raj <113578582+huamanraj@users.noreply.github.com> Date: Tue, 25 Nov 2025 23:25:07 +0530 Subject: [PATCH 1/4] feat: OSS programs added with data --- apps/web/package.json | 3 +- .../dashboard/oss-programs/ProgramsList.tsx | 68 +++ .../dashboard/oss-programs/[slug]/page.tsx | 61 +++ .../oss-programs/[slug]/program-styles.css | 103 +++++ .../(main)/dashboard/oss-programs/page.tsx | 11 + apps/web/src/components/dashboard/Sidebar.tsx | 6 + .../components/oss-programs/ProgramCard.tsx | 38 ++ .../components/oss-programs/ProgramHeader.tsx | 44 ++ .../oss-programs/ProgramMetadata.tsx | 42 ++ .../oss-programs/ProgramSection.tsx | 50 +++ .../components/oss-programs/SearchInput.tsx | 24 ++ .../src/components/oss-programs/TagFilter.tsx | 124 ++++++ apps/web/src/components/oss-programs/index.ts | 6 + apps/web/src/data/oss-programs/index.ts | 79 ++++ .../oss-programs/programs/24-pull-requests.ts | 85 ++++ .../oss-programs/programs/advent-of-code.ts | 86 ++++ .../src/data/oss-programs/programs/apertre.ts | 85 ++++ .../programs/build-for-bharat-fellowship.ts | 85 ++++ .../oss-programs/programs/cncf-mentorship.ts | 85 ++++ .../oss-programs/programs/code-for-govtech.ts | 85 ++++ .../programs/european-summer-of-code.ts | 91 ++++ .../programs/fossasia-codeheat.ts | 85 ++++ .../programs/fossee-summer-fellowship.ts | 94 +++++ .../programs/girlscript-summer-of-code.ts | 91 ++++ .../programs/girlscript-winter-of-code.ts | 90 ++++ .../programs/github-campus-experts.ts | 86 ++++ .../programs/google-summer-of-code.ts | 106 +++++ .../programs/google-summer-of-earth-engine.ts | 88 ++++ .../oss-programs/programs/hacktoberfest.ts | 85 ++++ .../igalia-coding-experience-program.ts | 91 ++++ .../programs/iiit-kalyani-winter-of-code.ts | 84 ++++ .../programs/jgec-winter-of-code.ts | 91 ++++ .../programs/linux-foundation-mentorship.ts | 97 +++++ .../programs/linux-kernel-mentorship.ts | 87 ++++ .../oss-programs/programs/mlh-fellowship.ts | 98 +++++ .../open-mainframe-project-mentorship.ts | 88 ++++ .../programs/open-source-promotion-plan.ts | 90 ++++ .../data/oss-programs/programs/outreachy.ts | 97 +++++ .../processing-foundation-fellowship.ts | 89 ++++ .../programs/redox-summer-of-code.ts | 91 ++++ .../oss-programs/programs/season-of-kde.ts | 90 ++++ .../programs/summer-of-bitcoin.ts | 94 +++++ .../oss-programs/programs/summer-of-nix.ts | 96 +++++ apps/web/src/data/oss-programs/types.ts | 76 ++++ pnpm-lock.yaml | 390 +++++++++++++++++- 45 files changed, 3713 insertions(+), 22 deletions(-) create mode 100644 apps/web/src/app/(main)/dashboard/oss-programs/ProgramsList.tsx create mode 100644 apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx create mode 100644 apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css create mode 100644 apps/web/src/app/(main)/dashboard/oss-programs/page.tsx create mode 100644 apps/web/src/components/oss-programs/ProgramCard.tsx create mode 100644 apps/web/src/components/oss-programs/ProgramHeader.tsx create mode 100644 apps/web/src/components/oss-programs/ProgramMetadata.tsx create mode 100644 apps/web/src/components/oss-programs/ProgramSection.tsx create mode 100644 apps/web/src/components/oss-programs/SearchInput.tsx create mode 100644 apps/web/src/components/oss-programs/TagFilter.tsx create mode 100644 apps/web/src/components/oss-programs/index.ts create mode 100644 apps/web/src/data/oss-programs/index.ts create mode 100644 apps/web/src/data/oss-programs/programs/24-pull-requests.ts create mode 100644 apps/web/src/data/oss-programs/programs/advent-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/apertre.ts create mode 100644 apps/web/src/data/oss-programs/programs/build-for-bharat-fellowship.ts create mode 100644 apps/web/src/data/oss-programs/programs/cncf-mentorship.ts create mode 100644 apps/web/src/data/oss-programs/programs/code-for-govtech.ts create mode 100644 apps/web/src/data/oss-programs/programs/european-summer-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/fossasia-codeheat.ts create mode 100644 apps/web/src/data/oss-programs/programs/fossee-summer-fellowship.ts create mode 100644 apps/web/src/data/oss-programs/programs/girlscript-summer-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/girlscript-winter-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/github-campus-experts.ts create mode 100644 apps/web/src/data/oss-programs/programs/google-summer-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/google-summer-of-earth-engine.ts create mode 100644 apps/web/src/data/oss-programs/programs/hacktoberfest.ts create mode 100644 apps/web/src/data/oss-programs/programs/igalia-coding-experience-program.ts create mode 100644 apps/web/src/data/oss-programs/programs/iiit-kalyani-winter-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/jgec-winter-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/linux-foundation-mentorship.ts create mode 100644 apps/web/src/data/oss-programs/programs/linux-kernel-mentorship.ts create mode 100644 apps/web/src/data/oss-programs/programs/mlh-fellowship.ts create mode 100644 apps/web/src/data/oss-programs/programs/open-mainframe-project-mentorship.ts create mode 100644 apps/web/src/data/oss-programs/programs/open-source-promotion-plan.ts create mode 100644 apps/web/src/data/oss-programs/programs/outreachy.ts create mode 100644 apps/web/src/data/oss-programs/programs/processing-foundation-fellowship.ts create mode 100644 apps/web/src/data/oss-programs/programs/redox-summer-of-code.ts create mode 100644 apps/web/src/data/oss-programs/programs/season-of-kde.ts create mode 100644 apps/web/src/data/oss-programs/programs/summer-of-bitcoin.ts create mode 100644 apps/web/src/data/oss-programs/programs/summer-of-nix.ts create mode 100644 apps/web/src/data/oss-programs/types.ts diff --git a/apps/web/package.json b/apps/web/package.json index 06ca9e96..08c06269 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -28,6 +28,7 @@ "framer-motion": "^11.15.0", "geist": "^1.5.1", "gray-matter": "^4.0.3", + "jsdom": "^27.2.0", "lucide-react": "^0.456.0", "marked": "^17.0.0", "next": "15.5.3", @@ -44,8 +45,8 @@ "zustand": "^5.0.1" }, "devDependencies": { - "@types/dompurify": "^3.2.0", "@tailwindcss/line-clamp": "^0.4.4", + "@types/jsdom": "^27.0.0", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/ProgramsList.tsx b/apps/web/src/app/(main)/dashboard/oss-programs/ProgramsList.tsx new file mode 100644 index 00000000..ac73be27 --- /dev/null +++ b/apps/web/src/app/(main)/dashboard/oss-programs/ProgramsList.tsx @@ -0,0 +1,68 @@ +"use client"; + +import { useState, useMemo } from "react"; +import { Program } from "@/data/oss-programs/types"; +import { SearchInput, TagFilter, ProgramCard } from "@/components/oss-programs"; + +interface ProgramsListProps { + programs: Program[]; + tags: string[]; +} + +export default function ProgramsList({ programs, tags }: ProgramsListProps) { + const [searchQuery, setSearchQuery] = useState(""); + const [selectedTags, setSelectedTags] = useState([]); + + const filteredPrograms = useMemo(() => { + return programs.filter((program) => { + const matchesSearch = + program.name.toLowerCase().includes(searchQuery.toLowerCase()) || + program.tags.some((tag) => + tag.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + const matchesTags = + selectedTags.length === 0 || + selectedTags.every((tag) => program.tags.includes(tag)); + + return matchesSearch && matchesTags; + }); + }, [programs, searchQuery, selectedTags]); + + return ( +
+
+ {/* Header Section */} +
+

OSS Programs

+ +
+ + +
+
+ + {/* List Section */} +
+ {filteredPrograms.length === 0 ? ( +
+ No programs found matching your criteria. +
+ ) : ( + filteredPrograms.map((program) => ( + + )) + )} +
+
+
+ ); +} diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx new file mode 100644 index 00000000..ef4cfaea --- /dev/null +++ b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx @@ -0,0 +1,61 @@ +import { getProgramBySlug, getAllPrograms } from "@/data/oss-programs"; +import { notFound } from "next/navigation"; +import { marked } from "marked"; +import DOMPurify from "dompurify"; +import { JSDOM } from "jsdom"; +import { ProgramHeader, ProgramMetadata, ProgramSection } from "@/components/oss-programs"; +import "./program-styles.css"; + +export const revalidate = 3600; + +export async function generateStaticParams() { + const programs = getAllPrograms(); + return programs.map((program) => ({ + slug: program.slug, + })); +} + +export default async function ProgramPage({ + params, +}: { + params: Promise<{ slug: string }>; +}) { + const { slug } = await params; + const program = getProgramBySlug(slug); + + if (!program) { + notFound(); + } + + marked.setOptions({ + gfm: true, + breaks: true, + }); + + const renderMarkdown = (markdown: string) => { + const html = marked.parse(markdown) as string; + const window = new JSDOM("").window; + const purify = DOMPurify(window); + return purify.sanitize(html); + }; + + return ( +
+
+ + + +
+ {program.sections.map((section) => ( + + ))} +
+
+
+ ); +} diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css new file mode 100644 index 00000000..bde626b6 --- /dev/null +++ b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css @@ -0,0 +1,103 @@ +/* Base list styling */ +.program-content li { + position: relative; + padding-left: 1.5rem; + margin: 0.5rem 0; +} + +.program-content ul li::before { + content: "•"; + position: absolute; + left: 0; + color: #9455f4; + font-weight: bold; +} + +.program-content ol { + counter-reset: item; +} + +.program-content ol li { + counter-increment: item; +} + +.program-content ol li::before { + content: counter(item) "."; + position: absolute; + left: 0; + color: #9455f4; + font-weight: 600; + font-size: 0.875rem; +} + +.program-content ul li::marker, +.program-content ol li::marker { + content: ""; +} + +/* Eligibility section - checkmarks for "good match" list */ +.eligibility-section ul:first-of-type li::before { + content: "✓"; + color: #22c55e; +} + +/* Keep in mind - simple muted styling */ +.eligibility-section p:last-of-type { + color: #9ca3af; + font-style: italic; + padding-left: 1rem; + border-left: 2px solid #444; + margin-top: 1rem; +} + +/* Preparation checklist - numbered steps with subtle background */ +.preparation-checklist ol li { + background: #252525; + padding: 0.75rem 1rem 0.75rem 2.25rem; + margin: 0.5rem 0; + border-radius: 0.375rem; + border: 1px solid transparent; + transition: border-color 0.2s; +} + +.preparation-checklist ol li:hover { + border-color: #333; +} + +.preparation-checklist ol li::before { + left: 0.75rem; + top: 0.75rem; + color: #9455f4; + font-weight: 700; +} + +/* Application process - step indicators */ +.application-timeline ul { + padding-left: 0.5rem; + border-left: 2px solid #333; + margin-left: 0.5rem; +} + +.application-timeline ul li { + padding: 0.5rem 0 0.5rem 1.25rem; + margin: 0; +} + +.application-timeline ul li::before { + content: ""; + position: absolute; + left: -0.85rem; + top: 0.85rem; + width: 8px; + height: 8px; + background: #9455f4; + border-radius: 50%; +} + +.application-timeline ul li:first-child::before { + background: #22c55e; +} + +.application-timeline ul li:last-child::before { + background: #f59e0b; +} diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/page.tsx b/apps/web/src/app/(main)/dashboard/oss-programs/page.tsx new file mode 100644 index 00000000..8ebb079e --- /dev/null +++ b/apps/web/src/app/(main)/dashboard/oss-programs/page.tsx @@ -0,0 +1,11 @@ +import { getAllPrograms, getAllTags } from "@/data/oss-programs"; +import ProgramsList from "./ProgramsList"; + +export const revalidate = 3600; + +export default function Page() { + const programs = getAllPrograms(); + const tags = getAllTags(); + + return ; +} diff --git a/apps/web/src/components/dashboard/Sidebar.tsx b/apps/web/src/components/dashboard/Sidebar.tsx index 4257a398..d27c636e 100644 --- a/apps/web/src/components/dashboard/Sidebar.tsx +++ b/apps/web/src/components/dashboard/Sidebar.tsx @@ -19,6 +19,7 @@ import { Squares2X2Icon, ChevronDownIcon, LockClosedIcon, + AcademicCapIcon } from "@heroicons/react/24/outline"; import { useShowSidebar } from "@/store/useShowSidebar"; import { signOut, useSession } from "next-auth/react"; @@ -51,6 +52,11 @@ const FREE_ROUTES: RouteConfig[] = [ label: "OSS Sheet", icon: , }, + { + path: "/dashboard/oss-programs", + label: "OSS Programs", + icon: , + }, ]; // premium features under Opensox Pro diff --git a/apps/web/src/components/oss-programs/ProgramCard.tsx b/apps/web/src/components/oss-programs/ProgramCard.tsx new file mode 100644 index 00000000..fc075bed --- /dev/null +++ b/apps/web/src/components/oss-programs/ProgramCard.tsx @@ -0,0 +1,38 @@ +import Link from "next/link"; +import { ChevronRight } from "lucide-react"; +import { Program } from "@/data/oss-programs/types"; + +interface ProgramCardProps { + program: Program; +} + +export default function ProgramCard({ program }: ProgramCardProps) { + return ( + +
+
+

+ {program.name} +

+

+ {program.shortDescription} +

+
+ +
+
+

Region

+

{program.region}

+
+
+ +
+ +
+
+ + ); +} diff --git a/apps/web/src/components/oss-programs/ProgramHeader.tsx b/apps/web/src/components/oss-programs/ProgramHeader.tsx new file mode 100644 index 00000000..922cd9ca --- /dev/null +++ b/apps/web/src/components/oss-programs/ProgramHeader.tsx @@ -0,0 +1,44 @@ +import Link from "next/link"; +import { ChevronLeft, Globe } from "lucide-react"; +import { Program } from "@/data/oss-programs/types"; + +interface ProgramHeaderProps { + program: Program; +} + +export default function ProgramHeader({ program }: ProgramHeaderProps) { + return ( + <> + + + Back to Programs + + +
+

+ {program.name} +

+

+ {program.tagline} +

+ + {program.websiteUrl && ( + + + + Visit Website + + + )} +
+ + ); +} diff --git a/apps/web/src/components/oss-programs/ProgramMetadata.tsx b/apps/web/src/components/oss-programs/ProgramMetadata.tsx new file mode 100644 index 00000000..f86fa4a4 --- /dev/null +++ b/apps/web/src/components/oss-programs/ProgramMetadata.tsx @@ -0,0 +1,42 @@ +import { Clock, MapPin, DollarSign } from "lucide-react"; +import { Program } from "@/data/oss-programs/types"; + +interface ProgramMetadataProps { + program: Program; +} + +export default function ProgramMetadata({ program }: ProgramMetadataProps) { + return ( +
+
+
+ + Region +
+

+ {program.region} +

+
+ +
+
+ + Duration +
+

+ {program.duration || "Flexible"} +

+
+ +
+
+ + Stipend +
+

+ {program.isPaid ? "Paid" : "Unpaid"} +

+
+
+ ); +} diff --git a/apps/web/src/components/oss-programs/ProgramSection.tsx b/apps/web/src/components/oss-programs/ProgramSection.tsx new file mode 100644 index 00000000..0f8c94b8 --- /dev/null +++ b/apps/web/src/components/oss-programs/ProgramSection.tsx @@ -0,0 +1,50 @@ +import { Info, User, Calendar, Rocket, FileText } from "lucide-react"; + +interface ProgramSectionProps { + id: string; + title: string; + contentHtml: string; +} + +const getSectionIcon = (sectionId: string) => { + const icons: Record = { + 'what': , + 'is-it-for-you': , + 'when': , + 'how-to-prepare': , + 'application-process': , + }; + return icons[sectionId] || ; +}; + +export default function ProgramSection({ id, title, contentHtml }: ProgramSectionProps) { + return ( +
+

+ + {getSectionIcon(id)} + + {title} +

+
+
+ ); +} diff --git a/apps/web/src/components/oss-programs/SearchInput.tsx b/apps/web/src/components/oss-programs/SearchInput.tsx new file mode 100644 index 00000000..1098d1c8 --- /dev/null +++ b/apps/web/src/components/oss-programs/SearchInput.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { Search } from "lucide-react"; + +interface SearchInputProps { + value: string; + onChange: (value: string) => void; + placeholder?: string; +} + +export default function SearchInput({ value, onChange, placeholder = "Search programs..." }: SearchInputProps) { + return ( +
+ + onChange(e.target.value)} + className="w-full bg-[#252525] border border-[#333] rounded-xl py-3 pl-12 pr-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#9455f4] transition-colors truncate" + /> +
+ ); +} diff --git a/apps/web/src/components/oss-programs/TagFilter.tsx b/apps/web/src/components/oss-programs/TagFilter.tsx new file mode 100644 index 00000000..a9c15dbc --- /dev/null +++ b/apps/web/src/components/oss-programs/TagFilter.tsx @@ -0,0 +1,124 @@ +"use client"; + +import { useState, useRef, useEffect, useMemo } from "react"; +import { X, ChevronDown } from "lucide-react"; +import { motion, AnimatePresence } from "framer-motion"; + +interface TagFilterProps { + tags: string[]; + selectedTags: string[]; + onTagsChange: (tags: string[]) => void; +} + +export default function TagFilter({ tags, selectedTags, onTagsChange }: TagFilterProps) { + const [filterInput, setFilterInput] = useState(""); + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const dropdownRef = useRef(null); + const inputRef = useRef(null); + + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { + setIsDropdownOpen(false); + } + } + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + const availableTags = useMemo(() => { + return tags.filter( + (tag) => + !selectedTags.includes(tag) && + tag.toLowerCase().includes(filterInput.toLowerCase()) + ); + }, [tags, selectedTags, filterInput]); + + const addTag = (tag: string) => { + onTagsChange([...selectedTags, tag]); + setFilterInput(""); + setIsDropdownOpen(true); + inputRef.current?.focus(); + }; + + const removeTag = (tagToRemove: string) => { + onTagsChange(selectedTags.filter((tag) => tag !== tagToRemove)); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Backspace" && filterInput === "" && selectedTags.length > 0) { + removeTag(selectedTags[selectedTags.length - 1]); + } + }; + + return ( +
+
{ + inputRef.current?.focus(); + setIsDropdownOpen(true); + }} + > +
+ {selectedTags.map((tag) => ( + + {tag} + + + ))} + { + setFilterInput(e.target.value); + setIsDropdownOpen(true); + }} + onKeyDown={handleKeyDown} + onFocus={() => setIsDropdownOpen(true)} + className="bg-transparent text-white placeholder-gray-500 focus:outline-none flex-1 min-w-[120px]" + /> +
+ +
+ + + {isDropdownOpen && ( + + {availableTags.length === 0 ? ( +
No matching tags found
+ ) : ( + availableTags.map((tag) => ( + + )) + )} +
+ )} +
+
+ ); +} diff --git a/apps/web/src/components/oss-programs/index.ts b/apps/web/src/components/oss-programs/index.ts new file mode 100644 index 00000000..d53e19dd --- /dev/null +++ b/apps/web/src/components/oss-programs/index.ts @@ -0,0 +1,6 @@ +export { default as SearchInput } from './SearchInput'; +export { default as TagFilter } from './TagFilter'; +export { default as ProgramCard } from './ProgramCard'; +export { default as ProgramHeader } from './ProgramHeader'; +export { default as ProgramMetadata } from './ProgramMetadata'; +export { default as ProgramSection } from './ProgramSection'; diff --git a/apps/web/src/data/oss-programs/index.ts b/apps/web/src/data/oss-programs/index.ts new file mode 100644 index 00000000..0cfe2051 --- /dev/null +++ b/apps/web/src/data/oss-programs/index.ts @@ -0,0 +1,79 @@ +// src/data/oss-programs/index.ts +import type { Program } from "./types"; +import { googleSummerOfCode } from "./programs/google-summer-of-code"; +import { outreachy } from "./programs/outreachy"; +import { mlhFellowship } from "./programs/mlh-fellowship"; +import { linuxFoundationMentorship } from "./programs/linux-foundation-mentorship"; +import { summerOfBitcoin } from "./programs/summer-of-bitcoin"; +import { europeanSummerOfCode } from "./programs/european-summer-of-code"; +import { girlscriptSummerOfCode } from "./programs/girlscript-summer-of-code"; +import { girlscriptWinterOfCode } from "./programs/girlscript-winter-of-code"; +import { seasonOfKde } from "./programs/season-of-kde"; +import { processingFoundationFellowship } from "./programs/processing-foundation-fellowship"; +import { igaliaCodingExperienceProgram } from "./programs/igalia-coding-experience-program"; +import { fosseeSummerFellowship } from "./programs/fossee-summer-fellowship"; +import { googleSummerOfEarthEngine } from "./programs/google-summer-of-earth-engine"; +import { summerOfNix } from "./programs/summer-of-nix"; +import { redoxSummerOfCode } from "./programs/redox-summer-of-code"; +import { adventOfCode } from "./programs/advent-of-code"; +import { openSourcePromotionPlan } from "./programs/open-source-promotion-plan"; +import { jgecWinterOfCode } from "./programs/jgec-winter-of-code"; +import { openMainframeProjectMentorship } from "./programs/open-mainframe-project-mentorship"; +import { linuxKernelMentorship } from "./programs/linux-kernel-mentorship"; +import { apertre } from "./programs/apertre"; +import { codeForGovtech } from "./programs/code-for-govtech"; +import { hacktoberfest } from "./programs/hacktoberfest"; +import { cncfMentorship } from "./programs/cncf-mentorship"; +import { iiitKalyaniWinterOfCode } from "./programs/iiit-kalyani-winter-of-code"; +import { buildForBharatFellowship } from "./programs/build-for-bharat-fellowship"; +import { githubCampusExperts } from "./programs/github-campus-experts"; +import { twentyFourPullRequests } from "./programs/24-pull-requests"; +import { fossasiaCodeheat } from "./programs/fossasia-codeheat"; + +export const programs: Program[] = [ + googleSummerOfCode, + outreachy, + mlhFellowship, + linuxFoundationMentorship, + summerOfBitcoin, + europeanSummerOfCode, + girlscriptSummerOfCode, + girlscriptWinterOfCode, + seasonOfKde, + processingFoundationFellowship, + igaliaCodingExperienceProgram, + fosseeSummerFellowship, + googleSummerOfEarthEngine, + summerOfNix, + redoxSummerOfCode, + adventOfCode, + openSourcePromotionPlan, + jgecWinterOfCode, + openMainframeProjectMentorship, + linuxKernelMentorship, + apertre, + codeForGovtech, + hacktoberfest, + cncfMentorship, + iiitKalyaniWinterOfCode, + buildForBharatFellowship, + githubCampusExperts, + twentyFourPullRequests, + fossasiaCodeheat, +]; + +export function getAllPrograms(): Program[] { + return programs; +} + +export function getProgramBySlug(slug: string): Program | undefined { + return programs.find((p) => p.slug === slug); +} + +export function getAllTags(): string[] { + const set = new Set(); + for (const p of programs) { + for (const tag of p.tags) set.add(tag); + } + return Array.from(set).sort(); +} diff --git a/apps/web/src/data/oss-programs/programs/24-pull-requests.ts b/apps/web/src/data/oss-programs/programs/24-pull-requests.ts new file mode 100644 index 00000000..0e354644 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/24-pull-requests.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const twentyFourPullRequests: Program = { + slug: "24-pull-requests", + name: "24 Pull Requests", + tagline: "December PR event.", + shortDescription: "December PR event.", + websiteUrl: "https://24pullrequests.com/", + tags: ["open source", "beginner", "holiday", "unpaid", "global"], + region: "global", + status: "active", + isPaid: false, + duration: "24 days", + stipendSummary: "Swag, recognition", + timelineSummary: "December 24 days", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +24 Pull Requests is a yearly initiative to encourage developers to give back to open source during the holiday season. The goal is to submit 24 pull requests between December 1st and December 24th. + +**Duration:** 24 days +**Stipend:** Swag, recognition +**Extra notes:** Holiday beginner friendly. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You want to contribute to open source during the holidays +- You are looking for a challenge similar to an advent calendar +- You are of any skill level + +Keep in mind: + +- Holiday beginner friendly. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The event runs from **December 1st to December 24th**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **24 Pull Requests**: + +1. Sign up on the website with your GitHub account. +2. Find projects that need help. +3. Plan to make one contribution each day. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Logging in with GitHub +- Submitting PRs to open source projects +- Tracking your progress on the site + +Check the official website to join. + `.trim(), + }, + ], + seo: { + title: "24 Pull Requests - Holiday Open Source Challenge", + description: + "24 Pull Requests encourages developers to give back to open source during December.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/advent-of-code.ts b/apps/web/src/data/oss-programs/programs/advent-of-code.ts new file mode 100644 index 00000000..72baf959 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/advent-of-code.ts @@ -0,0 +1,86 @@ +import type { Program } from "../types"; + +export const adventOfCode: Program = { + slug: "advent-of-code", + name: "Advent of Code", + tagline: "Annual December programming puzzle event.", + shortDescription: "Annual December programming puzzle event.", + websiteUrl: "https://adventofcode.com/", + tags: ["coding challenge", "puzzles", "learning", "unpaid", "global"], + region: "global", + status: "active", + isPaid: false, + duration: "25 days", + stipendSummary: "No prizes, learning-focused", + timelineSummary: "December 1-25, annual", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Advent of Code is an annual event where a new programming puzzle is released each day from December 1st to December 25th. It is designed for skill-building, practice, and fun. + +**Duration:** 25 days +**Stipend:** No prizes, learning-focused +**Extra notes:** Daily programming challenges, great for skill building and practice. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You enjoy solving algorithmic puzzles +- You want to improve your coding skills +- You are looking for a fun daily challenge + +Keep in mind: + +- Daily programming challenges, great for skill building and practice. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The event takes place annually from **December 1st to December 25th**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Advent of Code**: + +1. Brush up on algorithms and data structures. +2. Choose a programming language you want to practice (or learn a new one). +3. Sign up on the website before December 1st. +4. Join a leaderboard with friends or colleagues for extra motivation. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +There is no formal application process. Simply: + +- Go to the website +- Log in +- Solve the daily puzzles + +You can track your progress and compete on leaderboards. + `.trim(), + }, + ], + seo: { + title: "Advent of Code - Daily Programming Puzzles", + description: + "Advent of Code is an annual event with daily programming puzzles for skill building and fun.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/apertre.ts b/apps/web/src/data/oss-programs/programs/apertre.ts new file mode 100644 index 00000000..d226569f --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/apertre.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const apertre: Program = { + slug: "apertre", + name: "Apertre 2.0", + tagline: "30-day OSS event Resourcio Community.", + shortDescription: "30-day OSS event Resourcio Community.", + websiteUrl: "https://s2apertre.resourcio.in/", + tags: ["open source", "beginner", "india", "prizes", "environment"], + region: "india", + status: "active", + isPaid: false, + duration: "30 days", + stipendSummary: "20K INR prizes swags", + timelineSummary: "March 7-April 5 annual", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Apertre 2.0 is a 30-day open source event organized by the Resourcio Community. It encourages students and developers to contribute to open source projects. + +**Duration:** 30 days +**Stipend:** 20K INR prizes, swags +**Extra notes:** Beginner friendly; environmental focus (plant a tree for 5 PRs); Indian origin. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student or developer +- You want to start contributing to open source +- You are interested in winning prizes and swags + +Keep in mind: + +- Beginner friendly; environmental focus; Indian origin. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The event typically runs annually from **March 7 to April 5**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Apertre**: + +1. Join the Resourcio Community. +2. Learn basic Git and GitHub skills. +3. Look out for the registration announcement. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Registering for the event +- Submitting Pull Requests (PRs) +- Completing 5 PRs to plant a tree + +Check the official website for registration. + `.trim(), + }, + ], + seo: { + title: "Apertre 2.0 - Open Source Event", + description: + "Apertre 2.0 is a 30-day open source event with prizes and an environmental focus.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/build-for-bharat-fellowship.ts b/apps/web/src/data/oss-programs/programs/build-for-bharat-fellowship.ts new file mode 100644 index 00000000..b6a3a925 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/build-for-bharat-fellowship.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const buildForBharatFellowship: Program = { + slug: "build-for-bharat-fellowship", + name: "Build for Bharat Fellowship", + tagline: "Bharat Digital govt.", + shortDescription: "Bharat Digital govt.", + websiteUrl: "https://www.bharatdigital.io/fellowship", + tags: ["open source", "govtech", "india", "paid", "fellowship"], + region: "india", + status: "active", + isPaid: true, + duration: "6 months", + stipendSummary: "40K INR/month", + timelineSummary: "Jan-June 2026", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Build for Bharat Fellowship is a program focused on building digital public infrastructure for India. It involves design, data, and GIS projects. + +**Duration:** 6 months +**Stipend:** 40K INR/month +**Extra notes:** Govt high-impact. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a recent graduate (2024-2026 grads) +- You have skills in design, data, or GIS +- You want to work on government projects + +Keep in mind: + +- Govt high-impact. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The fellowship is scheduled for **January to June 2026**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Build for Bharat Fellowship**: + +1. Build a portfolio in design, data, or GIS. +2. Understand the digital public infrastructure landscape in India. +3. Apply when applications open. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Application +- Selection +- Fellowship work + +Check the official website for details. + `.trim(), + }, + ], + seo: { + title: "Build for Bharat Fellowship - GovTech India", + description: + "Build for Bharat Fellowship offers opportunities to work on high-impact government tech projects in India.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/cncf-mentorship.ts b/apps/web/src/data/oss-programs/programs/cncf-mentorship.ts new file mode 100644 index 00000000..1497fb65 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/cncf-mentorship.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const cncfMentorship: Program = { + slug: "cncf-mentorship", + name: "CNCF Mentorship", + tagline: "Cloud Native Foundation.", + shortDescription: "Cloud Native Foundation.", + websiteUrl: "https://github.com/cncf/mentoring", + tags: ["open source", "cloud native", "kubernetes", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "12-24 weeks", + stipendSummary: "3000-6600 USD", + timelineSummary: "Spring Summer Fall", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Cloud Native Computing Foundation (CNCF) Mentorship program offers structured mentorship for contributors to work on cloud-native projects like Kubernetes, Prometheus, and Envoy. + +**Duration:** 12-24 weeks +**Stipend:** 3000-6600 USD +**Extra notes:** Kubernetes, 100+ projects. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are 18 or older +- You have an interest in cloud-native technologies +- You want to work on high-impact infrastructure projects + +Keep in mind: + +- Kubernetes, 100+ projects. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program runs in **Spring, Summer, and Fall** terms, often aligned with the LFX Mentorship schedule. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **CNCF Mentorship**: + +1. Learn the basics of containers and Kubernetes. +2. Explore CNCF projects and find one that interests you. +3. Start contributing to the project before applying. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Applying via the LFX portal +- Selecting projects (Kubernetes, Prometheus, etc.) +- Working with mentors + +Check the official repository for details. + `.trim(), + }, + ], + seo: { + title: "CNCF Mentorship - Cloud Native Open Source", + description: + "CNCF Mentorship provides paid opportunities to work on cloud-native projects like Kubernetes.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/code-for-govtech.ts b/apps/web/src/data/oss-programs/programs/code-for-govtech.ts new file mode 100644 index 00000000..4cf62ffa --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/code-for-govtech.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const codeForGovtech: Program = { + slug: "code-for-govtech", + name: "DMP by C4GT Code for GovTech", + tagline: "India govt tech projects.", + shortDescription: "India govt tech projects.", + websiteUrl: "https://codeforgovtech.in/dedicated_mentoring_program/", + tags: ["open source", "govtech", "india", "paid", "student"], + region: "india", + status: "active", + isPaid: true, + duration: "2-3 months", + stipendSummary: "1,00,000 INR (~1200 USD)", + timelineSummary: "June-August", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Dedicated Mentoring Program (DMP) by Code for GovTech (C4GT) focuses on building open source digital public goods for government applications in India. + +**Duration:** 2-3 months +**Stipend:** 1,00,000 INR (~1200 USD) +**Extra notes:** Government digital services focus. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student (Indian preferred) +- You are interested in GovTech and digital public infrastructure +- You want to work on high-impact projects + +Keep in mind: + +- Government digital services focus. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically runs from **June to August**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **C4GT DMP**: + +1. Explore the C4GT community and projects. +2. Understand the basics of Digital Public Goods (DPGs). +3. Participate in community challenges if available. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Applying for the program +- Selection process +- Mentorship phase + +Check the official website for details. + `.trim(), + }, + ], + seo: { + title: "Code for GovTech DMP - GovTech Open Source", + description: + "Code for GovTech (C4GT) Dedicated Mentoring Program offers students the chance to work on Indian government tech projects.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/european-summer-of-code.ts b/apps/web/src/data/oss-programs/programs/european-summer-of-code.ts new file mode 100644 index 00000000..2f8b47a3 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/european-summer-of-code.ts @@ -0,0 +1,91 @@ +import type { Program } from "../types"; + +export const europeanSummerOfCode: Program = { + slug: "european-summer-of-code", + name: "European Summer of Code", + shortName: "ESoC", + tagline: + "Program that funds interns to work on applied AI and open source research projects with European hubs.", + shortDescription: + "Program that funds interns to work on applied AI and open source research projects with European hubs.", + websiteUrl: "https://www.esoc.dev/", + tags: ["open source", "ai", "research", "paid", "europe"], + region: "europe", + status: "active", + isPaid: true, + duration: "About 3 months per project", + stipendSummary: "Stipend provided by host organization; amount varies by project", + timelineSummary: + "Projects released in batches around Mar to Apr; each project then runs for roughly three months", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +European Summer of Code funds interns to work on applied AI and open source research projects. It focuses on connecting contributors with European organizations and research hubs. + +**Duration:** About 3 months per project +**Stipend:** Stipend provided by host organization; amount varies by project +**Extra notes:** Strong focus on applied AI and research outcomes. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are an early-career developer or student +- You are interested in AI and research +- You want to work with European organizations (though participation is often worldwide) + +Keep in mind: + +- Strong focus on applied AI and research outcomes. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +Projects are typically released in batches around **March to April**. Each project then runs for roughly **3 months**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **European Summer of Code**: + +1. Brush up on your AI and machine learning knowledge. +2. Review the list of participating organizations and their research areas. +3. Prepare a portfolio or resume highlighting relevant projects. +4. Be ready to discuss your technical skills and research interests. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Creating a profile +- Applying to specific projects +- Interviewing with host organizations +- Accepted interns working with a mentor on defined goals + +Check the official website for current project listings and deadlines. + `.trim(), + }, + ], + seo: { + title: "European Summer of Code - AI and Open Source Research", + description: + "European Summer of Code connects interns with European organizations for applied AI and open source research projects.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/fossasia-codeheat.ts b/apps/web/src/data/oss-programs/programs/fossasia-codeheat.ts new file mode 100644 index 00000000..f0ac8bab --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/fossasia-codeheat.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const fossasiaCodeheat: Program = { + slug: "fossasia-codeheat", + name: "FOSSASIA Codeheat", + tagline: "Continuous contest.", + shortDescription: "Continuous contest.", + websiteUrl: "https://codeheat.org/", + tags: ["open source", "contest", "fossasia", "prizes", "remote"], + region: "global", + status: "active", + isPaid: false, + duration: "Continuous", + stipendSummary: "Prizes periodic", + timelineSummary: "Year-round 2-month", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +FOSSASIA Codeheat is a coding contest for FOSSASIA projects. Contributors can win prizes and recognition by contributing code to FOSSASIA's open source software. + +**Duration:** Continuous / Periodic +**Stipend:** Prizes periodic +**Extra notes:** Contest, not internship. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are interested in FOSSASIA projects +- You like coding contests +- You want to earn recognition and prizes + +Keep in mind: + +- Contest, not internship. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The contest is often **continuous** or runs in **2-month** cycles year-round. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Codeheat**: + +1. Explore FOSSASIA repositories on GitHub. +2. Join the FOSSASIA community chat. +3. Start fixing bugs or implementing features. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Contributing code to FOSSASIA projects +- Submitting your contributions to the contest +- Evaluation by mentors + +Check the official website for current contest details. + `.trim(), + }, + ], + seo: { + title: "FOSSASIA Codeheat - Coding Contest", + description: + "FOSSASIA Codeheat is a coding contest where you can contribute to open source and win prizes.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/fossee-summer-fellowship.ts b/apps/web/src/data/oss-programs/programs/fossee-summer-fellowship.ts new file mode 100644 index 00000000..9355b6e8 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/fossee-summer-fellowship.ts @@ -0,0 +1,94 @@ +import type { Program } from "../types"; + +export const fosseeSummerFellowship: Program = { + slug: "fossee-summer-fellowship", + name: "FOSSEE Summer Fellowship", + tagline: + "Internship and fellowship program at IIT Bombay where students work on FOSSEE free software projects.", + shortDescription: + "Internship and fellowship program at IIT Bombay where students work on FOSSEE free software projects.", + websiteUrl: "https://fossee.in/fellowship/2025", + tags: ["open source", "fellowship", "india", "paid", "education"], + region: "india", + status: "active", + isPaid: true, + duration: "6 to 8 weeks", + stipendSummary: + "Honorarium paid on successful completion; amount depends on project and performance", + timelineSummary: + "Screening tasks announced around Jan; project work usually May to Jul", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The FOSSEE Summer Fellowship is conducted by IIT Bombay. It provides an opportunity for students to work on Free/Libre and Open Source Software (FOSS) projects used in engineering and science education. + +**Duration:** 6 to 8 weeks +**Stipend:** Honorarium paid on successful completion; amount depends on project and performance +**Extra notes:** Focuses on free software tools for engineering and science education. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student from an Indian institute (UG, PG, or PhD) +- You have good programming skills +- You are interested in contributing to educational software tools + +Keep in mind: + +- Focuses on free software tools for engineering and science education. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The schedule typically involves: + +- **Screening Tasks:** January to April +- **Fellowship:** May to July + +Typical duration is **6 to 8 weeks**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **FOSSEE Summer Fellowship**: + +1. Learn a programming language like Python, Scilab, or OpenFOAM depending on the project. +2. Complete the screening tasks diligently as they are the primary selection criteria. +3. Review the FOSSEE website for project details and tutorials. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Completing screening tasks for specific FOSSEE projects +- Selection based on performance in screening tasks +- Working at IIT Bombay or remotely on assigned tasks + +Check the official website for the release of screening tasks. + `.trim(), + }, + ], + seo: { + title: "FOSSEE Summer Fellowship - IIT Bombay Open Source", + description: + "FOSSEE Summer Fellowship offers students the chance to work on free software projects at IIT Bombay.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/girlscript-summer-of-code.ts b/apps/web/src/data/oss-programs/programs/girlscript-summer-of-code.ts new file mode 100644 index 00000000..de468092 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/girlscript-summer-of-code.ts @@ -0,0 +1,91 @@ +import type { Program } from "../types"; + +export const girlscriptSummerOfCode: Program = { + slug: "girlscript-summer-of-code", + name: "GirlScript Summer of Code", + shortName: "GSSoC", + tagline: + "Three month open source program by GirlScript Foundation for beginners to contribute to many projects.", + shortDescription: + "Three month open source program by GirlScript Foundation for beginners to contribute to many projects.", + websiteUrl: "https://gssoc.girlscript.tech/", + tags: ["open source", "beginner", "unpaid", "remote", "community"], + region: "global", + status: "active", + isPaid: false, + duration: "3 months", + stipendSummary: "Unpaid; goodies; certificates; and sometimes internship offers", + timelineSummary: "Typically Mar to May each year", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +GirlScript Summer of Code is a three-month open source program conducted by the GirlScript Foundation. It is designed to help beginners get started with open source development by contributing to various projects under the guidance of mentors. + +**Duration:** 3 months +**Stipend:** Unpaid; goodies; certificates; and sometimes internship offers +**Extra notes:** Community driven; very beginner friendly. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student or beginner +- You have no prior open source experience (it's very beginner friendly) +- You want to learn how to use Git and GitHub + +Keep in mind: + +- Community driven; very beginner friendly. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically runs from **March to May** each year. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **GirlScript Summer of Code**: + +1. Learn the basics of Git and GitHub. +2. Join the official communication channels (Discord/Telegram). +3. Look at the projects from previous years to get an idea of the tech stacks. +4. Be ready to claim issues and submit pull requests once the program starts. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Registering for the program +- Joining the communication channels +- Picking projects to contribute to +- Sending pull requests with mentor help +- Top contributors are recognized with prizes + +Check the official website for registration dates. + `.trim(), + }, + ], + seo: { + title: "GirlScript Summer of Code - Beginner Open Source Program", + description: + "GirlScript Summer of Code is a beginner-friendly open source program helping students contribute to real-world projects.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/girlscript-winter-of-code.ts b/apps/web/src/data/oss-programs/programs/girlscript-winter-of-code.ts new file mode 100644 index 00000000..07130cc1 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/girlscript-winter-of-code.ts @@ -0,0 +1,90 @@ +import type { Program } from "../types"; + +export const girlscriptWinterOfCode: Program = { + slug: "girlscript-winter-of-code", + name: "GirlScript Winter of Code", + tagline: + "Open source contribution program during winter focused on building educational content and code.", + shortDescription: + "Open source contribution program during winter focused on building educational content and code.", + websiteUrl: "https://gssoc.girlscript.tech/", + tags: ["open source", "beginner", "unpaid", "remote", "education"], + region: "global", + status: "active", + isPaid: false, + duration: "About 3 months", + stipendSummary: "Unpaid; certificates and goodies for active contributors", + timelineSummary: + "Usually around Sep to Nov or Dec to Feb; depends on edition", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +GirlScript Winter of Code is an open source contribution program that takes place during the winter. It emphasizes building educational content, tutorials, and documentation along with code contributions. + +**Duration:** About 3 months +**Stipend:** Unpaid; certificates and goodies for active contributors +**Extra notes:** Emphasis on tutorials, documentation, and learning content along with code. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a beginner or student +- You are interested in creating educational content or documentation +- You want to contribute to open source in a supportive environment + +Keep in mind: + +- Emphasis on tutorials, documentation, and learning content along with code. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The schedule varies by edition but usually runs around **September to November** or **December to February**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **GirlScript Winter of Code**: + +1. Familiarize yourself with technical writing and documentation standards. +2. Learn basic Git and GitHub workflows. +3. Identify domains or technologies you are interested in teaching or documenting. +4. Connect with mentors and the community. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Registering as a contributor +- Choosing domains or projects +- Completing tasks in repositories under mentor guidance +- Contributions are tracked and ranked + +Check the official website for specific dates and details. + `.trim(), + }, + ], + seo: { + title: "GirlScript Winter of Code - Open Source Education", + description: + "GirlScript Winter of Code focuses on creating educational content and code contributions in an open source environment.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/github-campus-experts.ts b/apps/web/src/data/oss-programs/programs/github-campus-experts.ts new file mode 100644 index 00000000..a7756702 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/github-campus-experts.ts @@ -0,0 +1,86 @@ +import type { Program } from "../types"; + +export const githubCampusExperts: Program = { + slug: "github-campus-experts", + name: "GitHub Campus Experts", + tagline: "Community leadership.", + shortDescription: "Community leadership.", + websiteUrl: + "https://docs.github.com/en/education/about-github-education/use-github-at-your-educational-institution/applying-to-be-a-github-campus-expert", + tags: ["community", "leadership", "student", "swag", "learning"], + region: "global", + status: "active", + isPaid: false, + duration: "Ongoing", + stipendSummary: "Swag, resources", + timelineSummary: "Year-round", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The GitHub Campus Experts program helps students learn the skills they need to build and grow technical communities on their campus. + +**Duration:** Ongoing +**Stipend:** Swag, resources +**Extra notes:** Leadership focus, not just coding. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a university student +- You want to build a tech community on campus +- You want to improve your public speaking and leadership skills + +Keep in mind: + +- Leadership focus, not just coding. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +Applications are open **year-round** (or periodically). + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **GitHub Campus Experts**: + +1. Be active in your campus tech community. +2. Understand the challenges your community faces. +3. Complete the training modules provided by GitHub. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Applying online +- Submitting a video explaining your community vision +- Completing training + +Check the official documentation for details. + `.trim(), + }, + ], + seo: { + title: "GitHub Campus Experts - Community Leadership", + description: + "GitHub Campus Experts program empowers students to build technical communities on their campuses.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/google-summer-of-code.ts b/apps/web/src/data/oss-programs/programs/google-summer-of-code.ts new file mode 100644 index 00000000..5d7ff73d --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/google-summer-of-code.ts @@ -0,0 +1,106 @@ +// src/data/oss-programs/google-summer-of-code.ts + +import type { Program } from "../types"; + +export const googleSummerOfCode: Program = { + slug: "google-summer-of-code", + name: "Google Summer of Code", + shortName: "GSoC", + tagline: + "International program where contributors 18 plus are paid by Google to work on open source projects over the summer.", + shortDescription: + "International program where contributors 18 plus are paid by Google to work on open source projects over the summer.", + websiteUrl: "https://summerofcode.withgoogle.com/", + tags: ["open source", "code program", "data or ai", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "10 to 22 weeks", + stipendSummary: + "Amount varies by country and project; typically 1500 to 6600 USD", + timelineSummary: + "Org list Jan to Feb; applications Mar to Apr; coding May to Aug", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Google Summer of Code is an international program where contributors who are 18 or older are paid by Google to work on open source projects over the summer. + +**Duration:** 10 to 22 weeks +**Stipend:** Amount varies by country and project; typically 1500 to 6600 USD +**Extra notes:** Remote only; open to students and non students. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are 18 plus +- You can participate worldwide +- You have basic programming skills +- You can work remotely during the program period + +Keep in mind: + +- Remote only; open to students and non students. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program usually follows this kind of schedule: + +- **Org list:** January to February +- **Applications:** March to April +- **Coding:** May to August + +Typical duration is **10 to 22 weeks**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Google Summer of Code**: + +1. Read the official website and any recent announcements carefully. +2. Check the eligibility and timeline so you know if you fit and when to apply. +3. Look at past projects and accepted proposals to understand what successful work looks like. +4. Make sure your GitHub profile and basic open source workflow are in decent shape. +5. Start early and talk with mentors in the org you are targeting. + +If you are new to open source, begin with small fixes or documentation improvements to understand the tools and review process. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process is usually: + +- Choose organization and project +- Talk with mentors +- Submit proposal +- Organizations review and select +- Coding under mentor guidance +- Final evaluation + +Always double check the official website because exact steps and dates can change each year. + `.trim(), + }, + ], + seo: { + title: "Google Summer of Code - Open source program guide", + description: + "Overview of Google Summer of Code: what it is about, who it is for, when it happens, how to prepare, and how to apply.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/google-summer-of-earth-engine.ts b/apps/web/src/data/oss-programs/programs/google-summer-of-earth-engine.ts new file mode 100644 index 00000000..34677f7c --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/google-summer-of-earth-engine.ts @@ -0,0 +1,88 @@ +import type { Program } from "../types"; + +export const googleSummerOfEarthEngine: Program = { + slug: "google-summer-of-earth-engine", + name: "Google Summer of Earth Engine", + tagline: + "Pilot program for Indian students to work on Earth Engine based environmental and geospatial projects.", + shortDescription: + "Pilot program for Indian students to work on Earth Engine based environmental and geospatial projects.", + websiteUrl: "https://sites.google.com/view/summerofearthengine/home", + tags: ["open source", "earth engine", "india", "paid", "research"], + region: "india", + status: "historical", + isPaid: true, + duration: "About 3 months", + stipendSummary: "Paid stipend plus certificate and swag", + timelineSummary: + "Held in 2019; applications early year; work roughly Jun to Aug", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Google Summer of Earth Engine was a pilot program that enabled Indian students to work on environmental and geospatial projects using Google Earth Engine. It connected students with research organizations. + +**Duration:** About 3 months +**Stipend:** Paid stipend plus certificate and swag +**Extra notes:** One time pilot; useful historical example of an open source related program. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program was a good match if: + +- You were a student or researcher in India +- You had a background in environmental science or GIS +- You were interested in using Earth Engine for research + +Keep in mind: + +- One time pilot; useful historical example of an open source related program. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program was held in **2019**, running from **June to August**. It is currently considered historical. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +Since this program is historical, you can prepare for similar opportunities by: + +1. Learning Google Earth Engine and geospatial analysis. +2. Exploring environmental data science projects. +3. Looking for other research-based internships. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involved: + +- Research organizations proposing projects +- Students applying to projects +- Selection and work with host organizations + +This program is not currently active. + `.trim(), + }, + ], + seo: { + title: "Google Summer of Earth Engine - Historical Program", + description: + "Information about the Google Summer of Earth Engine, a historical pilot program for geospatial projects in India.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/hacktoberfest.ts b/apps/web/src/data/oss-programs/programs/hacktoberfest.ts new file mode 100644 index 00000000..31e07f5e --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/hacktoberfest.ts @@ -0,0 +1,85 @@ +import type { Program } from "../types"; + +export const hacktoberfest: Program = { + slug: "hacktoberfest", + name: "Hacktoberfest", + tagline: "Digital Ocean October event.", + shortDescription: "Digital Ocean October event.", + websiteUrl: "https://hacktoberfest.com/", + tags: ["open source", "beginner", "swag", "remote", "global"], + region: "global", + status: "active", + isPaid: false, + duration: "1 month", + stipendSummary: "Badge, tree, swag", + timelineSummary: "October month", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Hacktoberfest is a month-long celebration of open source software run by DigitalOcean. It encourages people to contribute to open source projects during the month of October. + +**Duration:** 1 month +**Stipend:** Badge, tree, swag +**Extra notes:** Most popular beginner event. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a beginner or experienced developer +- You want to get involved in open source +- You enjoy collecting digital badges or swag (often a t-shirt or tree planted) + +Keep in mind: + +- Most popular beginner event. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The event takes place every year in **October**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Hacktoberfest**: + +1. Create a GitHub or GitLab account. +2. Look for repositories with the "hacktoberfest" topic. +3. Read the contribution guidelines of the projects you want to contribute to. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Registering on the Hacktoberfest website +- Submitting 4 or more valid Pull Requests (PRs) during October +- Waiting for validation + +Check the official website for registration. + `.trim(), + }, + ], + seo: { + title: "Hacktoberfest - October Open Source Event", + description: + "Hacktoberfest is a global open source event held in October, encouraging contributions to open source projects.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/igalia-coding-experience-program.ts b/apps/web/src/data/oss-programs/programs/igalia-coding-experience-program.ts new file mode 100644 index 00000000..15295bf5 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/igalia-coding-experience-program.ts @@ -0,0 +1,91 @@ +import type { Program } from "../types"; + +export const igaliaCodingExperienceProgram: Program = { + slug: "igalia-coding-experience-program", + name: "Igalia Coding Experience Program", + tagline: + "Summer program by Igalia giving newcomers experience working on open source browsers and graphics projects.", + shortDescription: + "Summer program by Igalia giving newcomers experience working on open source browsers and graphics projects.", + websiteUrl: "https://www.igalia.com/coding-experience/", + tags: ["open source", "browsers", "graphics", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "Around 12 weeks", + stipendSummary: + "Paid internship style grant; exact amount varies and is not always public", + timelineSummary: + "Usually runs during summer; applications some months before start", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Igalia Coding Experience Program is a summer program designed to give newcomers experience working on open source web engines, browsers, and graphics projects. Participants work with mentors on upstream projects like Chromium, WebKit, or Mesa. + +**Duration:** Around 12 weeks +**Stipend:** Paid internship style grant; exact amount varies and is not always public +**Extra notes:** Strong focus on upstream contributions to major open source projects. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student or early-career developer +- You have an interest in C++, web engines, or graphics +- You want to contribute to major browser engines or graphics drivers + +Keep in mind: + +- Strong focus on upstream contributions to major open source projects. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program usually runs during the **summer**. Applications typically open a few months before the start date. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **Igalia Coding Experience Program**: + +1. Strengthen your C++ skills. +2. Learn about browser architecture or graphics pipelines. +3. Explore the projects Igalia contributes to (Chromium, WebKit, Mesa). +4. Demonstrate your interest through small contributions or personal projects. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Igalia announcing available projects +- Candidates applying for specific projects +- Selection process involving interviews +- Selected participants joining remote teams to work with mentors + +Check the official website for announcements. + `.trim(), + }, + ], + seo: { + title: "Igalia Coding Experience Program - Browser & Graphics", + description: + "Join the Igalia Coding Experience Program to work on open source web engines and graphics projects.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/iiit-kalyani-winter-of-code.ts b/apps/web/src/data/oss-programs/programs/iiit-kalyani-winter-of-code.ts new file mode 100644 index 00000000..64ecd1e7 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/iiit-kalyani-winter-of-code.ts @@ -0,0 +1,84 @@ +import type { Program } from "../types"; + +export const iiitKalyaniWinterOfCode: Program = { + slug: "iiit-kalyani-winter-of-code", + name: "IIIT Kalyani Winter of Code", + tagline: "GDSC IIIT Kalyani.", + shortDescription: "GDSC IIIT Kalyani.", + websiteUrl: "https://winter-of-code.tech/", + tags: ["open source", "student", "beginner", "india", "certificates"], + region: "india", + status: "active", + isPaid: false, + duration: "1-2 months", + stipendSummary: "Certificates", + timelineSummary: "Dec-Jan", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +IIIT Kalyani Winter of Code is an open source initiative organized by GDSC IIIT Kalyani. It aims to help students get started with open source development. + +**Duration:** 1-2 months +**Stipend:** Certificates +**Extra notes:** GDSC West Bengal. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student +- You want to learn about open source +- You are looking for a winter project + +Keep in mind: + +- GDSC West Bengal. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically runs from **December to January**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **IIIT Kalyani Winter of Code**: + +1. Learn basic Git commands. +2. Join the community channels. +3. Look for projects to contribute to. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The process involves: + +- Registering +- Contributing via Pull Requests (PRs) + +Check the official website for details. + `.trim(), + }, + ], + seo: { + title: "IIIT Kalyani Winter of Code - Student Program", + description: + "IIIT Kalyani Winter of Code is a student-run open source program in India.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/jgec-winter-of-code.ts b/apps/web/src/data/oss-programs/programs/jgec-winter-of-code.ts new file mode 100644 index 00000000..2d426737 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/jgec-winter-of-code.ts @@ -0,0 +1,91 @@ +import type { Program } from "../types"; + +export const jgecWinterOfCode: Program = { + slug: "jgec-winter-of-code", + name: "JGEC Winter of Code", + shortName: "JWoC", + tagline: + "Winter open source program by Jalpaiguri Government Engineering College.", + shortDescription: + "Winter open source program by Jalpaiguri Government Engineering College.", + websiteUrl: "https://www.jwoc.in/", + tags: ["open source", "beginner", "unpaid", "student", "india"], + region: "india", + status: "active", + isPaid: false, + duration: "~1-2 months", + stipendSummary: "No stipend certificates provided", + timelineSummary: "December-January", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +JGEC Winter of Code (JWoC) is an open source program organized by Jalpaiguri Government Engineering College. It aims to introduce students to the world of open source development. + +**Duration:** ~1-2 months +**Stipend:** No stipend; certificates provided +**Extra notes:** College-level program from West Bengal, India; beginner-friendly; small scale. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student or beginner +- You want to get started with open source +- You are looking for a beginner-friendly environment + +Keep in mind: + +- College-level program from West Bengal, India; beginner-friendly; small scale. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically runs from **December to January**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **JWoC**: + +1. Learn the basics of Git and GitHub. +2. Join the program's Discord or communication channels. +3. Look for projects that match your skill level. +4. Be ready to ask questions and learn. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Registration +- Project browsing +- Making contributions +- Submitting Pull Requests (PRs) +- Certificates awarded upon completion + +Check the official website for registration details. + `.trim(), + }, + ], + seo: { + title: "JGEC Winter of Code - Student Open Source Program", + description: + "JGEC Winter of Code is a beginner-friendly open source program for students.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/linux-foundation-mentorship.ts b/apps/web/src/data/oss-programs/programs/linux-foundation-mentorship.ts new file mode 100644 index 00000000..6510dde2 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/linux-foundation-mentorship.ts @@ -0,0 +1,97 @@ +import type { Program } from "../types"; + +export const linuxFoundationMentorship: Program = { + slug: "linux-foundation-mentorship", + name: "Linux Foundation Mentorship Program", + shortName: "LFX Mentorship", + tagline: + "Mentorship program that matches contributors with maintainers on Linux Foundation projects.", + shortDescription: + "Mentorship program that matches contributors with maintainers on Linux Foundation projects.", + websiteUrl: "https://www.linuxfoundation.org/about/mentorship-programs/", + tags: ["open source", "mentorship", "linux", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "12 weeks", + stipendSummary: "Stipend tiers based on region; usually in the low thousands of USD", + timelineSummary: + "Several cohorts each year; typical terms are Mar to May; Jun to Aug; Sep to Nov", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Linux Foundation Mentorship Program connects aspiring contributors with experienced maintainers working on Linux Foundation projects. It covers a wide range of technologies including the Linux kernel, cloud-native applications, and networking. + +**Duration:** 12 weeks +**Stipend:** Stipend tiers based on region; usually in the low thousands of USD +**Extra notes:** Covers kernel, cloud native, networking, and many other LF projects. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student or early-career engineer +- You have an interest in specific Linux Foundation projects +- You want to learn from experienced open source maintainers + +Keep in mind: + +- Covers kernel, cloud native, networking, and many other LF projects. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +There are several cohorts each year. Typical terms are: + +- **March to May** +- **June to August** +- **September to November** + +Typical duration is **12 weeks**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **Linux Foundation Mentorship Program**: + +1. Create a profile on the LFX Mentorship platform. +2. Explore the projects that are participating in the upcoming cohort. +3. Familiarize yourself with the project's codebase and contribution guidelines. +4. Try to fix small bugs or improve documentation before applying. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Browsing projects on the LFX platform +- Submitting up to three applications +- Mentors reviewing applications and interviewing candidates +- Selected mentees working under a mentor with regular evaluations + +Check the LFX platform for the latest project listings and deadlines. + `.trim(), + }, + ], + seo: { + title: "Linux Foundation Mentorship - Open Source Mentoring", + description: + "Join the Linux Foundation Mentorship Program to work on major open source projects like Linux Kernel and Kubernetes with expert guidance.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/linux-kernel-mentorship.ts b/apps/web/src/data/oss-programs/programs/linux-kernel-mentorship.ts new file mode 100644 index 00000000..359b3128 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/linux-kernel-mentorship.ts @@ -0,0 +1,87 @@ +import type { Program } from "../types"; + +export const linuxKernelMentorship: Program = { + slug: "linux-kernel-mentorship", + name: "Linux Kernel Mentorship", + shortName: "LKMP", + tagline: "Linux kernel developer mentorship.", + shortDescription: "Linux kernel developer mentorship.", + websiteUrl: "https://wiki.linuxfoundation.org/lkmp", + tags: ["open source", "linux kernel", "c", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "12-24 weeks", + stipendSummary: "3000-6600 USD LFX", + timelineSummary: "Multiple terms LFX schedule", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Linux Kernel Mentorship Program (LKMP) offers a structured mentorship opportunity for developers to contribute to the Linux Kernel. It is designed to help aspiring kernel developers gain the skills and experience needed to become effective contributors. + +**Duration:** 12-24 weeks +**Stipend:** 3000-6600 USD (via LFX) +**Extra notes:** LFX; Strong C skills required; kernel focus. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You have a strong interest in kernel development +- You are proficient in C programming +- You want to contribute to the core of the Linux operating system + +Keep in mind: + +- LFX; Strong C skills required; kernel focus. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program follows the **LFX Mentorship schedule** with multiple terms (Spring, Summer, Fall). + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **Linux Kernel Mentorship**: + +1. Complete the Linux Kernel Mentorship courses if available. +2. Learn how to build and boot a custom kernel. +3. Familiarize yourself with the kernel coding style and submission process. +4. Fix small warnings or bugs in the kernel staging tree. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Completing prerequisite courses (often required) +- Applying via the LFX portal +- Working with developers on assigned tasks + +Check the official wiki and LFX portal for details. + `.trim(), + }, + ], + seo: { + title: "Linux Kernel Mentorship - Kernel Development", + description: + "Become a Linux Kernel contributor through the Linux Kernel Mentorship Program.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/mlh-fellowship.ts b/apps/web/src/data/oss-programs/programs/mlh-fellowship.ts new file mode 100644 index 00000000..7f0b8f81 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/mlh-fellowship.ts @@ -0,0 +1,98 @@ +import type { Program } from "../types"; + +export const mlhFellowship: Program = { + slug: "mlh-fellowship", + name: "MLH Fellowship", + tagline: + "Remote fellowship where students and early career developers work on real world open source or production code.", + shortDescription: + "Remote fellowship where students and early career developers work on real world open source or production code.", + websiteUrl: "https://fellowship.mlh.io/", + tags: ["open source", "fellowship", "paid", "remote", "learning"], + region: "global", + status: "active", + isPaid: true, + duration: "12 weeks", + stipendSummary: "Paid; up to about 5000 USD depending on location and track", + timelineSummary: + "Three batches each year; spring; summer; fall; applications usually 2 to 4 months before start", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The MLH Fellowship is a remote program where students and early-career developers collaborate on real-world open source projects or production code. Fellows work in small groups (pods) under the guidance of a mentor. + +**Duration:** 12 weeks +**Stipend:** Paid; up to about 5000 USD depending on location and track +**Extra notes:** Multiple tracks such as Open Source, Explorer, and Production Engineering. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a student or recent graduate +- You are fluent in English +- You have basic software development skills +- You want to gain practical experience in a team setting + +Keep in mind: + +- Multiple tracks such as Open Source, Explorer, Production Engineering. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +There are three batches each year: + +- **Spring** +- **Summer** +- **Fall** + +Applications usually open **2 to 4 months** before the start of each batch. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **MLH Fellowship**: + +1. Polish your resume and GitHub profile. +2. Practice coding problems and explaining your thought process. +3. Have a code sample ready that you can walk through during an interview. +4. Show enthusiasm for learning and collaborating with others. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process typically includes: + +- Online application form +- Coding tasks or technical interview +- Behavioral interview +- Acceptance and placement into a pod +- Regular mentor sessions and demos during the program + +Check the official website for specific track requirements and deadlines. + `.trim(), + }, + ], + seo: { + title: "MLH Fellowship - Remote Open Source Fellowship", + description: + "Discover the MLH Fellowship, a remote program for students and early career developers to work on real-world open source projects.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/open-mainframe-project-mentorship.ts b/apps/web/src/data/oss-programs/programs/open-mainframe-project-mentorship.ts new file mode 100644 index 00000000..2dcb68db --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/open-mainframe-project-mentorship.ts @@ -0,0 +1,88 @@ +import type { Program } from "../types"; + +export const openMainframeProjectMentorship: Program = { + slug: "open-mainframe-project-mentorship", + name: "Open Mainframe Project Mentorship", + tagline: + "Mentorship for mainframe and COBOL projects under Linux Foundation.", + shortDescription: + "Mentorship for mainframe and COBOL projects under Linux Foundation.", + websiteUrl: "https://openmainframeproject.org/projects/mentorship/", + tags: ["open source", "mainframe", "cobol", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "12-24 weeks", + stipendSummary: "3000-6600 USD via LFX location-based", + timelineSummary: "Part of LFX Mentorship schedule multiple batches", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Open Mainframe Project Mentorship program connects mentees with mentors to work on mainframe technologies, including COBOL, Zowe, and z/OS. It is part of the Linux Foundation Mentorship (LFX) platform. + +**Duration:** 12-24 weeks +**Stipend:** 3000-6600 USD via LFX; location-based +**Extra notes:** Great for learning mainframe tech, COBOL, z/OS, Zowe; in high demand. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are 18 or older +- You have an interest in mainframe technologies +- You want to learn skills that are in high demand in the enterprise world + +Keep in mind: + +- Great for learning mainframe tech, COBOL, z/OS, Zowe; in high demand. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program follows the **LFX Mentorship schedule** with multiple batches throughout the year (Spring, Summer, Fall). + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **Open Mainframe Project Mentorship**: + +1. Create an LFX profile. +2. Learn the basics of mainframe concepts (IBM Z, COBOL). +3. Explore the Open Mainframe Project landscape. +4. Look for introductory resources or courses provided by the foundation. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Applying via the LFX portal +- Project selection +- Working on mainframe/COBOL/Zowe projects + +Check the LFX Mentorship portal for open applications. + `.trim(), + }, + ], + seo: { + title: "Open Mainframe Project Mentorship - Mainframe & COBOL", + description: + "Learn mainframe technologies like COBOL and Zowe through the Open Mainframe Project Mentorship.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/open-source-promotion-plan.ts b/apps/web/src/data/oss-programs/programs/open-source-promotion-plan.ts new file mode 100644 index 00000000..a7e28c3e --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/open-source-promotion-plan.ts @@ -0,0 +1,90 @@ +import type { Program } from "../types"; + +export const openSourcePromotionPlan: Program = { + slug: "open-source-promotion-plan", + name: "Open Source Promotion Plan", + shortName: "OSPP", + tagline: "Program by Chinese Academy of Sciences for college students.", + shortDescription: + "Program by Chinese Academy of Sciences for college students.", + websiteUrl: "https://mentorship.kde.org/blog/2025-03-29-ospp/", + tags: ["open source", "china", "paid", "student", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "~3 months", + stipendSummary: "CNY 8000-12000 approx 1100-1700 USD varies by difficulty", + timelineSummary: "Summer June-September", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Open Source Promotion Plan (OSPP) is a program organized by the Chinese Academy of Sciences. It encourages college students to actively participate in the development and maintenance of open source software. + +**Duration:** ~3 months +**Stipend:** CNY 8000-12000 (approx 1100-1700 USD); varies by difficulty +**Extra notes:** Organized in China but open globally; many Chinese OSS projects. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are a college or university student (worldwide) +- You are interested in Chinese open source projects +- You want to gain experience in a structured mentorship program + +Keep in mind: + +- Organized in China but open globally; many Chinese OSS projects. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically runs during the **Summer (June-September)**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **OSPP**: + +1. Check the official portal for project listings. +2. Communicate with mentors to understand the requirements. +3. Prepare a project proposal. +4. Familiarize yourself with the specific technologies used in the projects. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Registering on the portal +- Browsing projects +- Contacting mentors +- Submitting a proposal +- Coding period upon selection + +Check the official website for the exact steps. + `.trim(), + }, + ], + seo: { + title: "Open Source Promotion Plan - Student Program", + description: + "Open Source Promotion Plan (OSPP) is a summer program for students to contribute to open source projects, organized by CAS.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/outreachy.ts b/apps/web/src/data/oss-programs/programs/outreachy.ts new file mode 100644 index 00000000..ac23b884 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/outreachy.ts @@ -0,0 +1,97 @@ +import type { Program } from "../types"; + +export const outreachy: Program = { + slug: "outreachy", + name: "Outreachy", + tagline: + "Diversity focused program offering paid remote internships in open source and open science.", + shortDescription: + "Diversity focused program offering paid remote internships in open source and open science.", + websiteUrl: "https://www.outreachy.org/", + tags: ["open source", "diversity", "paid", "remote", "internship"], + region: "global", + status: "active", + isPaid: true, + duration: "3 months", + stipendSummary: "7000 USD internship stipend plus travel support for some interns", + timelineSummary: "Two rounds each year; May to Aug and Dec to Mar", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Outreachy is a diversity-focused program that provides paid remote internships in open source and open science. The goal is to support people from groups underrepresented in the technology industry. + +**Duration:** 3 months +**Stipend:** 7000 USD internship stipend plus travel support for some interns +**Extra notes:** Strong focus on diversity and inclusion; remote only. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You identify with an underrepresented group in tech +- You are 18 or older +- You can commit full-time (40 hours per week) during the internship +- You are available worldwide + +Keep in mind: + +- Strong focus on diversity and inclusion; remote only. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program has two rounds each year: + +- **May to August** cohort +- **December to March** cohort + +Typical duration is **3 months**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Outreachy**: + +1. Check the eligibility criteria on the official website to ensure you qualify. +2. Watch for the initial application opening dates. +3. Once the contribution period starts, browse the available projects. +4. Communicate publicly with mentors and ask questions. +5. Start making small contributions (fixes, documentation) to demonstrate your skills and interest. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Initial eligibility check and application +- Browsing projects +- Making small contributions during the application period +- Submitting application essays +- Mentors reviewing and selecting interns + +Always check the official website for the most accurate dates and requirements. + `.trim(), + }, + ], + seo: { + title: "Outreachy - Diversity in Open Source Internships", + description: + "Learn about Outreachy, a paid remote internship program for underrepresented groups in open source and open science.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/processing-foundation-fellowship.ts b/apps/web/src/data/oss-programs/programs/processing-foundation-fellowship.ts new file mode 100644 index 00000000..8406c5b2 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/processing-foundation-fellowship.ts @@ -0,0 +1,89 @@ +import type { Program } from "../types"; + +export const processingFoundationFellowship: Program = { + slug: "processing-foundation-fellowship", + name: "Processing Foundation Fellowship", + tagline: + "Fellowships that support individuals or small teams building creative coding projects with Processing or p5.js.", + shortDescription: + "Fellowships that support individuals or small teams building creative coding projects with Processing or p5.js.", + websiteUrl: "https://processingfoundation.org/fellowships", + tags: ["open source", "art", "creative coding", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "4-5 months", + stipendSummary: "10,000 USD per fellowship", + timelineSummary: "Summer, June-October", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +The Processing Foundation Fellowship supports artists, designers, activists, educators, engineers, researchers, coders, and collectives who want to work on creative coding projects. The program focuses on Processing, p5.js, and related software. + +**Duration:** 4-5 months +**Stipend:** 10,000 USD per fellowship +**Extra notes:** Focus on art, education, and social justice in creative tech. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are an artist, educator, developer, or activist +- You are interested in creative coding +- You have a project proposal aligned with the foundation's themes + +Keep in mind: + +- Focus on art, education, and social justice in creative tech. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The fellowship typically runs during the **Summer (June-October)**. Calls for proposals usually happen early in the year. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for the **Processing Foundation Fellowship**: + +1. Develop a strong project proposal that aligns with the yearly themes. +2. Review past fellows' work to understand the scope and impact. +3. Clearly articulate how your project benefits the community. +4. Prepare a detailed timeline and budget if required. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Submitting a detailed fellowship application with a project proposal +- Foundation review and selection +- Fellows building their project and publishing outcomes +- Often running workshops or community events + +Check the official website for the specific themes and deadlines for the current year. + `.trim(), + }, + ], + seo: { + title: "Processing Foundation Fellowship - Creative Coding", + description: + "The Processing Foundation Fellowship supports creative coding projects involving art, code, and education.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/redox-summer-of-code.ts b/apps/web/src/data/oss-programs/programs/redox-summer-of-code.ts new file mode 100644 index 00000000..841bf914 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/redox-summer-of-code.ts @@ -0,0 +1,91 @@ +import type { Program } from "../types"; + +export const redoxSummerOfCode: Program = { + slug: "redox-summer-of-code", + name: "Redox Summer of Code", + shortName: "RSoC", + tagline: + "Redox OS program that uses project donations to fund students or contributors to work on Redox OS and ecosystem projects.", + shortDescription: + "Redox OS program that uses project donations to fund students or contributors to work on Redox OS and ecosystem projects.", + websiteUrl: "https://www.redox-os.org/rsoc-project-suggestions/", + tags: ["open source", "os dev", "rust", "paid", "remote"], + region: "global", + status: "active", + isPaid: true, + duration: "Varies by project; often similar to a summer term", + stipendSummary: "Amount varies; paid from donations and negotiated per project", + timelineSummary: + "Runs during northern hemisphere summer; exact dates and schedule agreed individually with mentors", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Redox Summer of Code is a program organized by the Redox OS project. It uses donations to fund contributors who want to work on Redox OS and its ecosystem. It offers more flexibility than traditional programs like GSoC. + +**Duration:** Varies by project; often similar to a summer term +**Stipend:** Amount varies; paid from donations and negotiated per project +**Extra notes:** Offers more flexibility than GSoC; schedule and payment are highly customizable. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You have shown interest and ability in Redox OS +- You are comfortable with Rust and systems programming +- You are self-motivated (as it's highly customizable) + +Keep in mind: + +- Offers more flexibility than GSoC; schedule and payment are highly customizable. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically runs during the **Northern Hemisphere summer**. However, exact dates and schedules are agreed upon individually with mentors. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Redox Summer of Code**: + +1. Learn Rust and operating system concepts. +2. Join the Redox OS chat and introduce yourself. +3. Start contributing to the project to demonstrate your skills. +4. Discuss project ideas with the maintainers. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Joining the Redox chat +- Contributing to the project +- Discussing a project idea and proposing a plan +- If selected, working on Redox OS under mentor guidance + +Check the official website for project suggestions. + `.trim(), + }, + ], + seo: { + title: "Redox Summer of Code - Rust OS Development", + description: + "Redox Summer of Code funds contributors to work on the Rust-based Redox Operating System.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/season-of-kde.ts b/apps/web/src/data/oss-programs/programs/season-of-kde.ts new file mode 100644 index 00000000..258a9108 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/season-of-kde.ts @@ -0,0 +1,90 @@ +import type { Program } from "../types"; + +export const seasonOfKde: Program = { + slug: "season-of-kde", + name: "Season of KDE", + shortName: "SoK", + tagline: + "Mentorship program by KDE community for code and non code projects similar in style to GSoC.", + shortDescription: + "Mentorship program by KDE community for code and non code projects similar in style to GSoC.", + websiteUrl: "https://mentorship.kde.org/sok/", + tags: ["open source", "kde", "mentorship", "unpaid", "remote"], + region: "global", + status: "active", + isPaid: false, + duration: "About 3 months", + stipendSummary: "Unpaid; certificates and KDE swag only", + timelineSummary: "Most editions run roughly Jan to Apr", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Season of KDE is a mentorship program offered by the KDE community. It is similar in style to Google Summer of Code but includes both code and non-code projects, such as design, documentation, websites, and translation. + +**Duration:** About 3 months +**Stipend:** Unpaid; certificates and KDE swag only +**Extra notes:** Allows work on design, documentation, websites, translation, and more. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are interested in the KDE ecosystem +- You are a student or non-student (everyone is welcome) +- You want to contribute to code or non-code areas like design or translation + +Keep in mind: + +- Allows work on design, documentation, websites, translation, and more. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +Most editions run roughly from **January to April**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Season of KDE**: + +1. Explore the KDE community and its projects. +2. Join the KDE mailing lists and chat channels. +3. Identify a project idea or pick one from the suggestions. +4. Find a mentor who is willing to guide you. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Proposing a project idea or picking one +- Getting a mentor to sign on +- Accepted mentees working with the mentor +- Receiving a certificate after successful completion + +Check the official website for the latest timeline. + `.trim(), + }, + ], + seo: { + title: "Season of KDE - KDE Mentorship Program", + description: + "Season of KDE offers mentorship for code and non-code contributions to the KDE community.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/summer-of-bitcoin.ts b/apps/web/src/data/oss-programs/programs/summer-of-bitcoin.ts new file mode 100644 index 00000000..d04c666f --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/summer-of-bitcoin.ts @@ -0,0 +1,94 @@ +import type { Program } from "../types"; + +export const summerOfBitcoin: Program = { + slug: "summer-of-bitcoin", + name: "Summer of Bitcoin", + tagline: + "Global online program that introduces university students to Bitcoin open source development and design.", + shortDescription: + "Global online program that introduces university students to Bitcoin open source development and design.", + websiteUrl: "https://www.summerofbitcoin.org/", + tags: ["open source", "bitcoin", "crypto", "paid", "remote", "student"], + region: "global", + status: "active", + isPaid: true, + duration: "12 weeks", + stipendSummary: "Stipend paid in bitcoin; roughly similar to GSoC levels", + timelineSummary: "Student applications around Jan to Feb; program runs May to Aug", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Summer of Bitcoin is a global online program focused on introducing university students to open source development and design within the Bitcoin ecosystem. + +**Duration:** 12 weeks +**Stipend:** Stipend paid in bitcoin; roughly similar to GSoC levels +**Extra notes:** Fully remote; focused strictly on Bitcoin and related open source projects. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are an undergraduate or similar level student +- You have an interest in Bitcoin technology +- You have good skills in C++, systems programming, or design + +Keep in mind: + +- Fully remote; focused strictly on Bitcoin and related open source projects. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically follows this schedule: + +- **Applications:** January to February +- **Program Run:** May to August + +Typical duration is **12 weeks**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Summer of Bitcoin**: + +1. Learn the basics of Bitcoin and how it works. +2. Study C++ or other relevant languages used in Bitcoin Core and related projects. +3. Look at previous projects to understand the scope. +4. Engage with the community and mentors early on. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Reviewing projects listed by mentors +- Submitting a proposal for a project +- Interviews with mentors +- Selected students working under mentors on Bitcoin projects + +Check the official website for the exact timeline and project list. + `.trim(), + }, + ], + seo: { + title: "Summer of Bitcoin - Bitcoin Open Source Development", + description: + "Summer of Bitcoin introduces university students to open source development and design in the Bitcoin ecosystem.", + }, +}; diff --git a/apps/web/src/data/oss-programs/programs/summer-of-nix.ts b/apps/web/src/data/oss-programs/programs/summer-of-nix.ts new file mode 100644 index 00000000..16d2b269 --- /dev/null +++ b/apps/web/src/data/oss-programs/programs/summer-of-nix.ts @@ -0,0 +1,96 @@ +import type { Program } from "../types"; + +export const summerOfNix: Program = { + slug: "summer-of-nix", + name: "Summer of Nix", + tagline: + "NixOS Foundation program where participants work in remote teams to improve Nix ecosystem and package free and open source software.", + shortDescription: + "NixOS Foundation program where participants work in remote teams to improve Nix ecosystem and package free and open source software.", + websiteUrl: "https://github.com/ngi-nix/summer-of-nix", + tags: ["open source", "nix", "paid", "remote", "devops"], + region: "global", + status: "active", + isPaid: true, + duration: "Around 13 weeks", + stipendSummary: + "Base stipend about 3000 EUR for EU residents; adjusted by purchasing power parity for other countries", + timelineSummary: + "Application period typically Apr to Jun; project work about Jul to Oct", + sections: [ + { + id: "what", + slug: "what-this-program-is-about", + title: "What this program is about", + bodyMarkdown: ` +Summer of Nix is a program organized by the NixOS Foundation. Participants work in remote teams to improve the Nix ecosystem, package free software, and contribute to the Next Generation Internet (NGI) initiative. + +**Duration:** Around 13 weeks +**Stipend:** Base stipend about 3000 EUR for EU residents; adjusted by purchasing power parity for other countries +**Extra notes:** Remote only; modeled after GSoC but independent; funded via NixOS Foundation and NLnet. + `.trim(), + }, + { + id: "is-it-for-you", + slug: "is-it-for-you", + title: "Is it for you", + bodyMarkdown: ` +This program is a good match if: + +- You are interested in Nix and FOSS +- You have some programming or DevOps experience +- You enjoy working in a team (mob programming style) + +Keep in mind: + +- Remote only; modeled after GSoC but independent. + `.trim(), + }, + { + id: "when", + slug: "when-it-happens", + title: "When it happens", + bodyMarkdown: ` +The program typically follows this schedule: + +- **Applications:** April to June +- **Project Work:** July to October + +Typical duration is **13 weeks**. + `.trim(), + }, + { + id: "how-to-prepare", + slug: "how-to-prepare", + title: "How to prepare", + bodyMarkdown: ` +To prepare for **Summer of Nix**: + +1. Learn the basics of Nix and NixOS. +2. Try packaging some software using Nix. +3. Join the Nix community channels. +4. Demonstrate your ability to work collaboratively. + `.trim(), + }, + { + id: "application-process", + slug: "application-process", + title: "Application process", + bodyMarkdown: ` +The application process involves: + +- Applying for the program +- Joining a remote team +- Working in mob programming style on assigned Nix projects +- Publishing blog posts and updates + +Check the official repository or website for the latest announcements. + `.trim(), + }, + ], + seo: { + title: "Summer of Nix - NixOS Foundation Program", + description: + "Summer of Nix is a remote program for improving the Nix ecosystem and packaging free software.", + }, +}; diff --git a/apps/web/src/data/oss-programs/types.ts b/apps/web/src/data/oss-programs/types.ts new file mode 100644 index 00000000..1f69a58b --- /dev/null +++ b/apps/web/src/data/oss-programs/types.ts @@ -0,0 +1,76 @@ +// src/data/programs/types.ts + +export type ProgramSlug = + | "google-summer-of-code" + | "outreachy" + | "mlh-fellowship" + | "linux-foundation-mentorship" + | "summer-of-bitcoin" + | "european-summer-of-code" + | "girlscript-summer-of-code" + | "girlscript-winter-of-code" + | "season-of-kde" + | "processing-foundation-fellowship" + | "igalia-coding-experience-program" + | "fossee-summer-fellowship" + | "google-summer-of-earth-engine" + | "summer-of-nix" + | "redox-summer-of-code" + | "advent-of-code" + | "open-source-promotion-plan" + | "jgec-winter-of-code" + | "open-mainframe-project-mentorship" + | "linux-kernel-mentorship" + | "apertre" + | "code-for-govtech" + | "hacktoberfest" + | "cncf-mentorship" + | "iiit-kalyani-winter-of-code" + | "build-for-bharat-fellowship" + | "github-campus-experts" + | "24-pull-requests" + | "fossasia-codeheat"; + +export type ProgramSectionId = + | "what" + | "is-it-for-you" + | "when" + | "how-to-prepare" + | "application-process"; + +export type ProgramStatus = "active" | "historical" | "unknown"; + +export interface ProgramSection { + id: ProgramSectionId; + slug: string; + title: string; + bodyMarkdown: string; +} + +export interface Program { + slug: ProgramSlug; + name: string; + shortName?: string; + logoUrl?: string; + + tagline: string; + shortDescription: string; + + websiteUrl: string; + + tags: string[]; + region: "global" | "india" | "europe" | "other"; + status: ProgramStatus; + isPaid: boolean; + + duration?: string; + stipendSummary?: string; + timelineSummary: string; + + sections: ProgramSection[]; + + seo: { + title: string; + description: string; + }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97d7f4b9..57389987 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,6 +184,9 @@ importers: gray-matter: specifier: ^4.0.3 version: 4.0.3 + jsdom: + specifier: ^27.2.0 + version: 27.2.0 lucide-react: specifier: ^0.456.0 version: 0.456.0(react@18.3.1) @@ -230,9 +233,9 @@ importers: '@tailwindcss/line-clamp': specifier: ^0.4.4 version: 0.4.4(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@20.19.0)(typescript@5.9.2))) - '@types/dompurify': - specifier: ^3.2.0 - version: 3.2.0 + '@types/jsdom': + specifier: ^27.0.0 + version: 27.0.0 '@types/node': specifier: ^20 version: 20.19.0 @@ -332,6 +335,9 @@ importers: packages: + '@acemir/cssom@0.9.24': + resolution: {integrity: sha512-5YjgMmAiT2rjJZU7XK1SNI7iqTy92DpaYVgG6x63FxkJ11UpYfLndHJATtinWJClAXiOlW9XWaUyAQf8pMrQPg==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -340,6 +346,15 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@asamuzakjp/css-color@4.1.0': + resolution: {integrity: sha512-9xiBAtLn4aNsa4mDnpovJvBn72tNEIACyvlqaNJ+ADemR+yeMJWnBudOi2qGDviJa7SwcDOU/TRh5dnET7qk0w==} + + '@asamuzakjp/dom-selector@6.7.4': + resolution: {integrity: sha512-buQDjkm+wDPXd6c13534URWZqbz0RP5PAhXZ+LIoa5LgwInT9HVJvGIJivg75vi8I13CxDGdTnz+aY5YUJlIAA==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -443,6 +458,38 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.17': + resolution: {integrity: sha512-LCC++2h8pLUSPY+EsZmrrJ1EOUu+5iClpEiDhhdw3zRJpPbABML/N5lmRuBHjxtKm9VnRcsUzioyD0sekFMF0A==} + engines: {node: '>=18'} + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} @@ -1299,10 +1346,6 @@ packages: '@types/cors@2.8.19': resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} - '@types/dompurify@3.2.0': - resolution: {integrity: sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==} - deprecated: This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed. - '@types/eslint@8.56.12': resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} @@ -1324,6 +1367,9 @@ packages: '@types/inquirer@6.5.0': resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} + '@types/jsdom@27.0.0': + resolution: {integrity: sha512-NZyFl/PViwKzdEkQg96gtnB8wm+1ljhdDay9ahn4hgb+SfVtPCbm3TlmDUFXTA+MGN3CijicnMhG18SI5H3rFw==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1386,6 +1432,9 @@ packages: '@types/tinycolor2@1.4.6': resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -1964,6 +2013,9 @@ packages: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -2192,11 +2244,19 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true + cssstyle@5.3.3: + resolution: {integrity: sha512-OytmFH+13/QXONJcC75QNdMtKpceNk3u8ThBjyyYjkEcy/ekBwR1mMAuNvi3gdBPW3N5TlCzQ0WZw8H0lN/bDw==} + engines: {node: '>=20'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -2207,6 +2267,10 @@ packages: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} + data-urls@6.0.0: + resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} + engines: {node: '>=20'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -2244,6 +2308,9 @@ packages: supports-color: optional: true + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -2380,6 +2447,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -2984,6 +3055,10 @@ packages: hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -3004,6 +3079,10 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3165,6 +3244,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -3265,6 +3347,15 @@ packages: jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + jsdom@27.2.0: + resolution: {integrity: sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -3397,6 +3488,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3428,6 +3523,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -3763,6 +3861,12 @@ packages: resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} engines: {node: '>=0.10.0'} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + parse5@8.0.0: + resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -4030,6 +4134,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + require-package-name@2.0.1: resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} @@ -4105,6 +4213,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -4381,6 +4493,9 @@ packages: peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.11.11: resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4424,6 +4539,13 @@ packages: title-case@2.1.1: resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} + tldts-core@7.0.19: + resolution: {integrity: sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==} + + tldts@7.0.19: + resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==} + hasBin: true + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -4436,9 +4558,17 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tough-cookie@6.0.0: + resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -4649,6 +4779,10 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -4658,6 +4792,22 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@8.0.0: + resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==} + engines: {node: '>=20'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -4708,6 +4858,25 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -4769,6 +4938,8 @@ packages: snapshots: + '@acemir/cssom@0.9.24': {} + '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': @@ -4776,6 +4947,24 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 + '@asamuzakjp/css-color@4.1.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 11.2.2 + + '@asamuzakjp/dom-selector@6.7.4': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.1.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.2 + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -4923,6 +5112,28 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.17': {} + + '@csstools/css-tokenizer@3.0.4': {} + '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 @@ -5652,10 +5863,6 @@ snapshots: dependencies: '@types/node': 20.19.0 - '@types/dompurify@3.2.0': - dependencies: - dompurify: 3.3.0 - '@types/eslint@8.56.12': dependencies: '@types/estree': 1.0.8 @@ -5689,6 +5896,12 @@ snapshots: '@types/through': 0.0.33 rxjs: 6.6.7 + '@types/jsdom@27.0.0': + dependencies: + '@types/node': 20.19.0 + '@types/tough-cookie': 4.0.5 + parse5: 7.3.0 + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -5750,6 +5963,8 @@ snapshots: '@types/tinycolor2@1.4.6': {} + '@types/tough-cookie@4.0.5': {} + '@types/trusted-types@2.0.7': optional: true @@ -6401,6 +6616,10 @@ snapshots: basic-ftp@5.0.5: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + binary-extensions@2.3.0: {} bl@4.1.0: @@ -6660,14 +6879,30 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + cssesc@3.0.0: {} + cssstyle@5.3.3: + dependencies: + '@asamuzakjp/css-color': 4.1.0 + '@csstools/css-syntax-patches-for-csstree': 1.0.17 + css-tree: 3.1.0 + csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} data-uri-to-buffer@6.0.2: {} + data-urls@6.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -6698,6 +6933,8 @@ snapshots: dependencies: ms: 2.1.3 + decimal.js@10.6.0: {} + deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -6838,6 +7075,8 @@ snapshots: entities@4.5.0: {} + entities@6.0.1: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -6995,7 +7234,7 @@ snapshots: eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1) @@ -7014,8 +7253,8 @@ snapshots: '@typescript-eslint/parser': 8.34.0(eslint@8.57.1)(typescript@5.9.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1) @@ -7048,6 +7287,21 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.1 + eslint: 8.57.1 + get-tsconfig: 4.10.1 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.14 + unrs-resolver: 1.9.0 + optionalDependencies: + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + transitivePeerDependencies: + - supports-color + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 @@ -7059,7 +7313,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.9.0 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -7074,7 +7328,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.9.0 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -7099,14 +7353,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.34.0(eslint@8.57.1)(typescript@5.9.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -7145,7 +7399,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7174,7 +7428,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7185,7 +7439,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -7793,6 +8047,10 @@ snapshots: hosted-git-info@2.8.9: {} + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -7821,6 +8079,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -7993,6 +8255,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -8090,6 +8354,33 @@ snapshots: jsbn@1.1.0: {} + jsdom@27.2.0: + dependencies: + '@acemir/cssom': 0.9.24 + '@asamuzakjp/dom-selector': 6.7.4 + cssstyle: 5.3.3 + data-urls: 6.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 8.0.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.18.3 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@0.5.0: {} jsesc@3.1.0: {} @@ -8215,6 +8506,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.2.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -8239,6 +8532,8 @@ snapshots: math-intrinsics@1.1.0: {} + mdn-data@2.12.2: {} + media-typer@0.3.0: {} merge-descriptors@1.0.3: {} @@ -8601,6 +8896,14 @@ snapshots: parse-passwd@1.0.0: {} + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + parse5@8.0.0: + dependencies: + entities: 6.0.1 + parseurl@1.3.3: {} pascal-case@2.0.1: @@ -8872,6 +9175,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + require-package-name@2.0.1: {} resolve-dir@1.0.1: @@ -8950,6 +9255,10 @@ snapshots: safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -9295,6 +9604,8 @@ snapshots: react: 18.3.1 use-sync-external-store: 1.5.0(react@18.3.1) + symbol-tree@3.2.4: {} + synckit@0.11.11: dependencies: '@pkgr/core': 0.2.9 @@ -9361,6 +9672,12 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 + tldts-core@7.0.19: {} + + tldts@7.0.19: + dependencies: + tldts-core: 7.0.19 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -9371,8 +9688,16 @@ snapshots: toidentifier@1.0.1: {} + tough-cookie@6.0.0: + dependencies: + tldts: 7.0.19 + tr46@0.0.3: {} + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + ts-api-utils@1.4.3(typescript@5.9.2): dependencies: typescript: 5.9.2 @@ -9591,6 +9916,10 @@ snapshots: vary@1.1.2: {} + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -9599,6 +9928,19 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@8.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@15.1.0: + dependencies: + tr46: 6.0.0 + webidl-conversions: 8.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -9677,6 +10019,12 @@ snapshots: wrappy@1.0.2: {} + ws@8.18.3: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + y18n@5.0.8: {} yallist@3.1.1: {} From 5292a9d4787d38fddb325dd409685b016111b74b Mon Sep 17 00:00:00 2001 From: Aman Raj <113578582+huamanraj@users.noreply.github.com> Date: Wed, 26 Nov 2025 00:05:05 +0530 Subject: [PATCH 2/4] feat: update styles and improve accessibility for OSS program components --- .../dashboard/oss-programs/[slug]/page.tsx | 2 +- .../oss-programs/[slug]/program-styles.css | 30 ++++++++++++------- .../components/oss-programs/SearchInput.tsx | 5 ++-- .../src/components/oss-programs/TagFilter.tsx | 10 ++++--- .../src/data/oss-programs/programs/apertre.ts | 2 +- .../programs/github-campus-experts.ts | 4 +-- .../oss-programs/programs/hacktoberfest.ts | 4 +-- apps/web/src/data/oss-programs/types.ts | 2 +- 8 files changed, 36 insertions(+), 23 deletions(-) diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx index ef4cfaea..a6a51736 100644 --- a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx +++ b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx @@ -2,7 +2,7 @@ import { getProgramBySlug, getAllPrograms } from "@/data/oss-programs"; import { notFound } from "next/navigation"; import { marked } from "marked"; import DOMPurify from "dompurify"; -import { JSDOM } from "jsdom"; +import { JSDOM } from "jsdom"; import { ProgramHeader, ProgramMetadata, ProgramSection } from "@/components/oss-programs"; import "./program-styles.css"; diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css index bde626b6..32630b1e 100644 --- a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css +++ b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/program-styles.css @@ -1,3 +1,13 @@ +:root { + --color-primary: #9455f4; + --color-success: #22c55e; + --color-warning: #f59e0b; + --color-text-primary: #333; + --color-text-secondary: #444; + --color-text-tertiary: #9ca3af; + --color-bg-secondary: #252525; +} + /* Base list styling */ .program-content li { position: relative; @@ -9,7 +19,7 @@ content: "•"; position: absolute; left: 0; - color: #9455f4; + color: var(--color-primary); font-weight: bold; } @@ -25,7 +35,7 @@ content: counter(item) "."; position: absolute; left: 0; - color: #9455f4; + color: var(--color-primary); font-weight: 600; font-size: 0.875rem; } @@ -38,21 +48,21 @@ /* Eligibility section - checkmarks for "good match" list */ .eligibility-section ul:first-of-type li::before { content: "✓"; - color: #22c55e; + color: var(--color-success); } /* Keep in mind - simple muted styling */ .eligibility-section p:last-of-type { - color: #9ca3af; + color: var(--color-text-tertiary); font-style: italic; padding-left: 1rem; - border-left: 2px solid #444; + border-left: 2px solid var(--color-text-secondary); margin-top: 1rem; } /* Preparation checklist - numbered steps with subtle background */ .preparation-checklist ol li { - background: #252525; + background: var(--color-bg-secondary); padding: 0.75rem 1rem 0.75rem 2.25rem; margin: 0.5rem 0; border-radius: 0.375rem; @@ -67,7 +77,7 @@ .preparation-checklist ol li::before { left: 0.75rem; top: 0.75rem; - color: #9455f4; + color: var(--color-primary); font-weight: 700; } @@ -90,14 +100,14 @@ top: 0.85rem; width: 8px; height: 8px; - background: #9455f4; + background: var(--color-primary); border-radius: 50%; } .application-timeline ul li:first-child::before { - background: #22c55e; + background: var(--color-success); } .application-timeline ul li:last-child::before { - background: #f59e0b; + background: var(--color-warning); } diff --git a/apps/web/src/components/oss-programs/SearchInput.tsx b/apps/web/src/components/oss-programs/SearchInput.tsx index 1098d1c8..93e02608 100644 --- a/apps/web/src/components/oss-programs/SearchInput.tsx +++ b/apps/web/src/components/oss-programs/SearchInput.tsx @@ -8,7 +8,7 @@ interface SearchInputProps { placeholder?: string; } -export default function SearchInput({ value, onChange, placeholder = "Search programs..." }: SearchInputProps) { +export default function SearchInput({ value, onChange, placeholder = "Search programs..." }: SearchInputProps): JSX.Element { return (
@@ -17,7 +17,8 @@ export default function SearchInput({ value, onChange, placeholder = "Search pro placeholder={placeholder} value={value} onChange={(e) => onChange(e.target.value)} - className="w-full bg-[#252525] border border-[#333] rounded-xl py-3 pl-12 pr-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#9455f4] transition-colors truncate" + className="w-full bg-dash-surface border border-dash-border rounded-xl py-3 pl-12 pr-4 text-text-primary placeholder-gray-500 focus:outline-none focus:border-brand-purple transition-colors truncate" + aria-label="Search programs" />
); diff --git a/apps/web/src/components/oss-programs/TagFilter.tsx b/apps/web/src/components/oss-programs/TagFilter.tsx index a9c15dbc..82926bb9 100644 --- a/apps/web/src/components/oss-programs/TagFilter.tsx +++ b/apps/web/src/components/oss-programs/TagFilter.tsx @@ -54,7 +54,7 @@ export default function TagFilter({ tags, selectedTags, onTagsChange }: TagFilte return (
{ inputRef.current?.focus(); setIsDropdownOpen(true); @@ -64,7 +64,7 @@ export default function TagFilter({ tags, selectedTags, onTagsChange }: TagFilte {selectedTags.map((tag) => ( {tag} diff --git a/apps/web/src/data/oss-programs/programs/apertre.ts b/apps/web/src/data/oss-programs/programs/apertre.ts index d226569f..60d992cb 100644 --- a/apps/web/src/data/oss-programs/programs/apertre.ts +++ b/apps/web/src/data/oss-programs/programs/apertre.ts @@ -3,7 +3,7 @@ import type { Program } from "../types"; export const apertre: Program = { slug: "apertre", name: "Apertre 2.0", - tagline: "30-day OSS event Resourcio Community.", + tagline: "30-day OSS event by Resourcio Community.", shortDescription: "30-day OSS event Resourcio Community.", websiteUrl: "https://s2apertre.resourcio.in/", tags: ["open source", "beginner", "india", "prizes", "environment"], diff --git a/apps/web/src/data/oss-programs/programs/github-campus-experts.ts b/apps/web/src/data/oss-programs/programs/github-campus-experts.ts index a7756702..5e586355 100644 --- a/apps/web/src/data/oss-programs/programs/github-campus-experts.ts +++ b/apps/web/src/data/oss-programs/programs/github-campus-experts.ts @@ -3,8 +3,8 @@ import type { Program } from "../types"; export const githubCampusExperts: Program = { slug: "github-campus-experts", name: "GitHub Campus Experts", - tagline: "Community leadership.", - shortDescription: "Community leadership.", + tagline: "Helps students build and grow technical communities on campus", + shortDescription: "A leadership program for university students who want to establish and expand tech communities on their campuses. Participants gain public speaking skills, leadership training, and access to GitHub resources while fostering innovation and collaboration among their peers.", websiteUrl: "https://docs.github.com/en/education/about-github-education/use-github-at-your-educational-institution/applying-to-be-a-github-campus-expert", tags: ["community", "leadership", "student", "swag", "learning"], diff --git a/apps/web/src/data/oss-programs/programs/hacktoberfest.ts b/apps/web/src/data/oss-programs/programs/hacktoberfest.ts index 31e07f5e..17a0579c 100644 --- a/apps/web/src/data/oss-programs/programs/hacktoberfest.ts +++ b/apps/web/src/data/oss-programs/programs/hacktoberfest.ts @@ -3,8 +3,8 @@ import type { Program } from "../types"; export const hacktoberfest: Program = { slug: "hacktoberfest", name: "Hacktoberfest", - tagline: "Digital Ocean October event.", - shortDescription: "Digital Ocean October event.", + tagline: "Month-long celebration of open source with contribution rewards", + shortDescription: "A global event run by DigitalOcean that encourages developers of all levels to contribute to open source projects during October. Participants earn digital badges, tree plantings, and swag by completing pull requests and making meaningful contributions to the community.", websiteUrl: "https://hacktoberfest.com/", tags: ["open source", "beginner", "swag", "remote", "global"], region: "global", diff --git a/apps/web/src/data/oss-programs/types.ts b/apps/web/src/data/oss-programs/types.ts index 1f69a58b..31220206 100644 --- a/apps/web/src/data/oss-programs/types.ts +++ b/apps/web/src/data/oss-programs/types.ts @@ -1,4 +1,4 @@ -// src/data/programs/types.ts +// apps/web/src/data/oss-programs/types.ts export type ProgramSlug = | "google-summer-of-code" From cf0e9ccf286a097c3e6d30a5768fcac4e8e113b7 Mon Sep 17 00:00:00 2001 From: apsinghdev Date: Sat, 29 Nov 2025 14:58:45 +0530 Subject: [PATCH 3/4] fix: fix jsdom esmodule requirement err --- apps/web/package.json | 2 +- .../dashboard/oss-programs/[slug]/page.tsx | 46 +- pnpm-lock.yaml | 406 ++++-------------- 3 files changed, 117 insertions(+), 337 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 08c06269..c0572117 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -28,7 +28,7 @@ "framer-motion": "^11.15.0", "geist": "^1.5.1", "gray-matter": "^4.0.3", - "jsdom": "^27.2.0", + "sanitize-html": "^2.11.0", "lucide-react": "^0.456.0", "marked": "^17.0.0", "next": "15.5.3", diff --git a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx index a6a51736..f9d07955 100644 --- a/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx +++ b/apps/web/src/app/(main)/dashboard/oss-programs/[slug]/page.tsx @@ -1,8 +1,7 @@ import { getProgramBySlug, getAllPrograms } from "@/data/oss-programs"; import { notFound } from "next/navigation"; import { marked } from "marked"; -import DOMPurify from "dompurify"; -import { JSDOM } from "jsdom"; +import sanitizeHtml from "sanitize-html"; import { ProgramHeader, ProgramMetadata, ProgramSection } from "@/components/oss-programs"; import "./program-styles.css"; @@ -34,9 +33,46 @@ export default async function ProgramPage({ const renderMarkdown = (markdown: string) => { const html = marked.parse(markdown) as string; - const window = new JSDOM("").window; - const purify = DOMPurify(window); - return purify.sanitize(html); + return sanitizeHtml(html, { + allowedTags: [ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "p", + "br", + "strong", + "em", + "u", + "s", + "code", + "pre", + "ul", + "ol", + "li", + "blockquote", + "a", + "img", + "table", + "thead", + "tbody", + "tr", + "th", + "td", + "hr", + "div", + "span", + ], + allowedAttributes: { + a: ["href", "title", "target", "rel"], + img: ["src", "alt", "title", "width", "height"], + code: ["class"], + pre: ["class"], + }, + allowedSchemes: ["http", "https", "mailto"], + }); }; return ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57389987..65a4f546 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,9 +184,6 @@ importers: gray-matter: specifier: ^4.0.3 version: 4.0.3 - jsdom: - specifier: ^27.2.0 - version: 27.2.0 lucide-react: specifier: ^0.456.0 version: 0.456.0(react@18.3.1) @@ -217,6 +214,9 @@ importers: react-tweet: specifier: ^3.2.1 version: 3.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + sanitize-html: + specifier: ^2.11.0 + version: 2.17.0 superjson: specifier: ^2.2.5 version: 2.2.5 @@ -335,9 +335,6 @@ importers: packages: - '@acemir/cssom@0.9.24': - resolution: {integrity: sha512-5YjgMmAiT2rjJZU7XK1SNI7iqTy92DpaYVgG6x63FxkJ11UpYfLndHJATtinWJClAXiOlW9XWaUyAQf8pMrQPg==} - '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -346,15 +343,6 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@asamuzakjp/css-color@4.1.0': - resolution: {integrity: sha512-9xiBAtLn4aNsa4mDnpovJvBn72tNEIACyvlqaNJ+ADemR+yeMJWnBudOi2qGDviJa7SwcDOU/TRh5dnET7qk0w==} - - '@asamuzakjp/dom-selector@6.7.4': - resolution: {integrity: sha512-buQDjkm+wDPXd6c13534URWZqbz0RP5PAhXZ+LIoa5LgwInT9HVJvGIJivg75vi8I13CxDGdTnz+aY5YUJlIAA==} - - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} - '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -458,38 +446,6 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@csstools/color-helpers@5.1.0': - resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} - engines: {node: '>=18'} - - '@csstools/css-calc@2.1.4': - resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-color-parser@3.1.0': - resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-parser-algorithms@3.0.5': - resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-syntax-patches-for-csstree@1.0.17': - resolution: {integrity: sha512-LCC++2h8pLUSPY+EsZmrrJ1EOUu+5iClpEiDhhdw3zRJpPbABML/N5lmRuBHjxtKm9VnRcsUzioyD0sekFMF0A==} - engines: {node: '>=18'} - - '@csstools/css-tokenizer@3.0.4': - resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} - engines: {node: '>=18'} - '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} @@ -2013,9 +1969,6 @@ packages: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} - bidi-js@1.0.3: - resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -2244,19 +2197,11 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - css-tree@3.1.0: - resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true - cssstyle@5.3.3: - resolution: {integrity: sha512-OytmFH+13/QXONJcC75QNdMtKpceNk3u8ThBjyyYjkEcy/ekBwR1mMAuNvi3gdBPW3N5TlCzQ0WZw8H0lN/bDw==} - engines: {node: '>=20'} - csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -2267,10 +2212,6 @@ packages: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} - data-urls@6.0.0: - resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} - engines: {node: '>=20'} - data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -2308,9 +2249,6 @@ packages: supports-color: optional: true - decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -2318,6 +2256,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -2399,9 +2341,22 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dompurify@3.3.0: resolution: {integrity: sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==} + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dot-case@2.1.1: resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} @@ -3055,9 +3010,8 @@ packages: hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - html-encoding-sniffer@4.0.0: - resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} - engines: {node: '>=18'} + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} @@ -3079,10 +3033,6 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3244,8 +3194,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} @@ -3347,15 +3298,6 @@ packages: jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - jsdom@27.2.0: - resolution: {integrity: sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -3488,10 +3430,6 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.2: - resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} - engines: {node: 20 || >=22} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3523,9 +3461,6 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - mdn-data@2.12.2: - resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} - media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -3861,12 +3796,12 @@ packages: resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} engines: {node: '>=0.10.0'} + parse-srcset@1.0.2: + resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} + parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - parse5@8.0.0: - resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} - parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -4134,10 +4069,6 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - require-package-name@2.0.1: resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} @@ -4213,9 +4144,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} + sanitize-html@2.17.0: + resolution: {integrity: sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==} scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -4493,9 +4423,6 @@ packages: peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - synckit@0.11.11: resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4539,13 +4466,6 @@ packages: title-case@2.1.1: resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} - tldts-core@7.0.19: - resolution: {integrity: sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==} - - tldts@7.0.19: - resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==} - hasBin: true - tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -4558,17 +4478,9 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - tough-cookie@6.0.0: - resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} - engines: {node: '>=16'} - tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@6.0.0: - resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} - engines: {node: '>=20'} - ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -4779,10 +4691,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} - wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -4792,22 +4700,6 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@8.0.0: - resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==} - engines: {node: '>=20'} - - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - - whatwg-url@15.1.0: - resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} - engines: {node: '>=20'} - whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -4858,25 +4750,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} - engines: {node: '>=18'} - - xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -4938,8 +4811,6 @@ packages: snapshots: - '@acemir/cssom@0.9.24': {} - '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': @@ -4947,24 +4818,6 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@asamuzakjp/css-color@4.1.0': - dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 11.2.2 - - '@asamuzakjp/dom-selector@6.7.4': - dependencies: - '@asamuzakjp/nwsapi': 2.3.9 - bidi-js: 1.0.3 - css-tree: 3.1.0 - is-potential-custom-element-name: 1.0.1 - lru-cache: 11.2.2 - - '@asamuzakjp/nwsapi@2.3.9': {} - '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -5112,28 +4965,6 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@csstools/color-helpers@5.1.0': {} - - '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/color-helpers': 5.1.0 - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-syntax-patches-for-csstree@1.0.17': {} - - '@csstools/css-tokenizer@3.0.4': {} - '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 @@ -6616,10 +6447,6 @@ snapshots: basic-ftp@5.0.5: {} - bidi-js@1.0.3: - dependencies: - require-from-string: 2.0.2 - binary-extensions@2.3.0: {} bl@4.1.0: @@ -6879,30 +6706,14 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-tree@3.1.0: - dependencies: - mdn-data: 2.12.2 - source-map-js: 1.2.1 - cssesc@3.0.0: {} - cssstyle@5.3.3: - dependencies: - '@asamuzakjp/css-color': 4.1.0 - '@csstools/css-syntax-patches-for-csstree': 1.0.17 - css-tree: 3.1.0 - csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} data-uri-to-buffer@6.0.2: {} - data-urls@6.0.0: - dependencies: - whatwg-mimetype: 4.0.0 - whatwg-url: 15.1.0 - data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -6933,12 +6744,12 @@ snapshots: dependencies: ms: 2.1.3 - decimal.js@10.6.0: {} - deep-extend@0.6.0: {} deep-is@0.1.4: {} + deepmerge@4.3.1: {} + defaults@1.0.4: dependencies: clone: 1.0.4 @@ -7037,10 +6848,28 @@ snapshots: dependencies: esutils: 2.0.3 + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + dompurify@3.3.0: optionalDependencies: '@types/trusted-types': 2.0.7 + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dot-case@2.1.1: dependencies: no-case: 2.3.2 @@ -7234,7 +7063,7 @@ snapshots: eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1) @@ -7253,8 +7082,8 @@ snapshots: '@typescript-eslint/parser': 8.34.0(eslint@8.57.1)(typescript@5.9.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1) @@ -7287,21 +7116,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.1 - eslint: 8.57.1 - get-tsconfig: 4.10.1 - is-bun-module: 2.0.0 - stable-hash: 0.0.5 - tinyglobby: 0.2.14 - unrs-resolver: 1.9.0 - optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) - transitivePeerDependencies: - - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 @@ -7313,7 +7127,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.9.0 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -7328,7 +7142,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.9.0 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -7353,14 +7167,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.34.0(eslint@8.57.1)(typescript@5.9.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -7399,7 +7213,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7428,7 +7242,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7439,7 +7253,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.34.0(eslint@8.57.1)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -8047,9 +7861,12 @@ snapshots: hosted-git-info@2.8.9: {} - html-encoding-sniffer@4.0.0: + htmlparser2@8.0.2: dependencies: - whatwg-encoding: 3.1.1 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 http-errors@2.0.0: dependencies: @@ -8079,10 +7896,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - ieee754@1.2.1: {} ignore@5.3.2: {} @@ -8255,7 +8068,7 @@ snapshots: is-plain-obj@4.1.0: {} - is-potential-custom-element-name@1.0.1: {} + is-plain-object@5.0.0: {} is-regex@1.2.1: dependencies: @@ -8354,33 +8167,6 @@ snapshots: jsbn@1.1.0: {} - jsdom@27.2.0: - dependencies: - '@acemir/cssom': 0.9.24 - '@asamuzakjp/dom-selector': 6.7.4 - cssstyle: 5.3.3 - data-urls: 6.0.0 - decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - parse5: 8.0.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 6.0.0 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 8.0.0 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 15.1.0 - ws: 8.18.3 - xml-name-validator: 5.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - jsesc@0.5.0: {} jsesc@3.1.0: {} @@ -8506,8 +8292,6 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.2: {} - lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -8532,8 +8316,6 @@ snapshots: math-intrinsics@1.1.0: {} - mdn-data@2.12.2: {} - media-typer@0.3.0: {} merge-descriptors@1.0.3: {} @@ -8896,11 +8678,9 @@ snapshots: parse-passwd@1.0.0: {} - parse5@7.3.0: - dependencies: - entities: 6.0.1 + parse-srcset@1.0.2: {} - parse5@8.0.0: + parse5@7.3.0: dependencies: entities: 6.0.1 @@ -9175,8 +8955,6 @@ snapshots: require-directory@2.1.1: {} - require-from-string@2.0.2: {} - require-package-name@2.0.1: {} resolve-dir@1.0.1: @@ -9255,9 +9033,14 @@ snapshots: safer-buffer@2.1.2: {} - saxes@6.0.0: + sanitize-html@2.17.0: dependencies: - xmlchars: 2.2.0 + deepmerge: 4.3.1 + escape-string-regexp: 4.0.0 + htmlparser2: 8.0.2 + is-plain-object: 5.0.0 + parse-srcset: 1.0.2 + postcss: 8.5.5 scheduler@0.23.2: dependencies: @@ -9604,8 +9387,6 @@ snapshots: react: 18.3.1 use-sync-external-store: 1.5.0(react@18.3.1) - symbol-tree@3.2.4: {} - synckit@0.11.11: dependencies: '@pkgr/core': 0.2.9 @@ -9672,12 +9453,6 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 - tldts-core@7.0.19: {} - - tldts@7.0.19: - dependencies: - tldts-core: 7.0.19 - tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -9688,16 +9463,8 @@ snapshots: toidentifier@1.0.1: {} - tough-cookie@6.0.0: - dependencies: - tldts: 7.0.19 - tr46@0.0.3: {} - tr46@6.0.0: - dependencies: - punycode: 2.3.1 - ts-api-utils@1.4.3(typescript@5.9.2): dependencies: typescript: 5.9.2 @@ -9916,10 +9683,6 @@ snapshots: vary@1.1.2: {} - w3c-xmlserializer@5.0.0: - dependencies: - xml-name-validator: 5.0.0 - wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -9928,19 +9691,6 @@ snapshots: webidl-conversions@3.0.1: {} - webidl-conversions@8.0.0: {} - - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@4.0.0: {} - - whatwg-url@15.1.0: - dependencies: - tr46: 6.0.0 - webidl-conversions: 8.0.0 - whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -10019,12 +9769,6 @@ snapshots: wrappy@1.0.2: {} - ws@8.18.3: {} - - xml-name-validator@5.0.0: {} - - xmlchars@2.2.0: {} - y18n@5.0.8: {} yallist@3.1.1: {} From efbb9d8bd44e1ee6d5fd0c83a4d42858ee519d78 Mon Sep 17 00:00:00 2001 From: Aman Raj <113578582+huamanraj@users.noreply.github.com> Date: Sat, 29 Nov 2025 19:30:23 +0530 Subject: [PATCH 4/4] fix: ui repsnsiveness and design --- apps/web/package.json | 3 +- apps/web/src/app/(main)/dashboard/layout.tsx | 2 +- .../dashboard/oss-programs/ProgramsList.tsx | 8 ++- .../dashboard/oss-programs/[slug]/page.tsx | 8 ++- .../oss-programs/[slug]/program-styles.css | 61 +++++++++++++++++-- .../components/oss-programs/ProgramCard.tsx | 8 ++- .../oss-programs/ProgramSection.tsx | 23 ++++--- pnpm-lock.yaml | 45 +++++++++++--- 8 files changed, 125 insertions(+), 33 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index c0572117..53f7d69c 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -28,7 +28,6 @@ "framer-motion": "^11.15.0", "geist": "^1.5.1", "gray-matter": "^4.0.3", - "sanitize-html": "^2.11.0", "lucide-react": "^0.456.0", "marked": "^17.0.0", "next": "15.5.3", @@ -39,6 +38,7 @@ "react-dom": "^18.2.0", "react-qr-code": "^2.0.18", "react-tweet": "^3.2.1", + "sanitize-html": "^2.11.0", "superjson": "^2.2.5", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", @@ -50,6 +50,7 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@types/sanitize-html": "^2.16.0", "depcheck": "^1.4.7", "eslint": "^8", "eslint-config-next": "15.0.2", diff --git a/apps/web/src/app/(main)/dashboard/layout.tsx b/apps/web/src/app/(main)/dashboard/layout.tsx index 18c43598..257e025a 100644 --- a/apps/web/src/app/(main)/dashboard/layout.tsx +++ b/apps/web/src/app/(main)/dashboard/layout.tsx @@ -16,7 +16,7 @@ export default function DashboardLayout({ const { showFilters } = useFilterStore(); const { showSidebar, setShowSidebar } = useShowSidebar(); return ( -
+
{showFilters && }