From 6fc4660355e6da5df403089d2aeee4614ae8ef3c Mon Sep 17 00:00:00 2001
From: Ruizhi Chen
Date: Sun, 11 Oct 2026 00:46:24 -0400
Subject: [PATCH 1/2] Separate competition years and simplify the 2026 homepage
---
README.md | 12 ++-
about/index.html | 112 ++++++++++++++++++++
competitions/2024/index.html | 112 ++++++++++++++++++++
competitions/2025/index.html | 114 +++++++++++++++++++++
config/lighthouserc.json | 57 +++++++++--
index.html | 14 +--
public/images/logos/x-camp.svg | 79 ++++++++++++++
public/sitemap.xml | 5 +-
src/components/layout/Footer.module.css | 11 ++
src/components/layout/Footer.tsx | 16 ++-
src/components/layout/Header.module.css | 58 ++++++++++-
src/components/layout/Header.tsx | 38 +++++--
src/components/layout/pages.ts | 7 +-
src/data/competitions.ts | 63 ++++++++++++
src/data/faq.tsx | 104 +++++--------------
src/data/site.ts | 20 +---
src/data/sponsors.ts | 35 ++++---
src/entries/about.tsx | 5 +
src/entries/archive2024.tsx | 5 +
src/entries/archive2025.tsx | 5 +
src/features/home/FormatSection.module.css | 2 +-
src/features/home/FormatSection.tsx | 40 ++------
src/features/home/HighlightsSection.tsx | 11 +-
src/features/home/HomeHero.tsx | 36 ++-----
src/features/home/ResultsSection.tsx | 10 +-
src/features/home/SponsorsSection.tsx | 11 +-
src/pages/AboutPage.tsx | 31 ++++++
src/pages/ArchivePage.tsx | 49 +++++++++
src/pages/CompetitionPage.module.css | 24 +++++
src/pages/HomePage.tsx | 37 ++++---
vite.config.ts | 7 ++
31 files changed, 887 insertions(+), 243 deletions(-)
create mode 100644 about/index.html
create mode 100644 competitions/2024/index.html
create mode 100644 competitions/2025/index.html
create mode 100644 public/images/logos/x-camp.svg
create mode 100644 src/data/competitions.ts
create mode 100644 src/entries/about.tsx
create mode 100644 src/entries/archive2024.tsx
create mode 100644 src/entries/archive2025.tsx
create mode 100644 src/pages/AboutPage.tsx
create mode 100644 src/pages/ArchivePage.tsx
create mode 100644 src/pages/CompetitionPage.module.css
diff --git a/README.md b/README.md
index 5e24075..9f3fc8f 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,7 @@ CI rejects JavaScript or CSS growth beyond the limits in
the current production build and should be raised only with an explanation in
the pull request.
-Lighthouse runs three times against both generated pages. Accessibility, SEO,
+Lighthouse runs three times against all five generated pages. Accessibility, SEO,
layout stability, blocking time, and best-practice regressions fail CI;
performance-score and largest-contentful-paint regressions initially warn while
the project establishes a stable baseline.
@@ -72,3 +72,13 @@ The Cloudflare Pages project should use:
Do not set `SKIP_DEPENDENCY_INSTALL`. Cloudflare copies `public/_headers` into
the production build and applies those response headers to static assets.
+
+## Competition editions
+
+The homepage is the current 2026 competition. Past editions live at
+`/competitions/2024/` and `/competitions/2025/`; organization content lives at
+`/about/`. Competition-specific sponsors, photos, and results are assigned in
+`src/data/competitions.ts`, with shared logo definitions in `src/data/sponsors.ts`.
+Archives only display available historical content, never current registration
+information. New editions need a static HTML entry, Vite input, sitemap entry,
+and Lighthouse URL in addition to their competition data.
diff --git a/about/index.html b/about/index.html
new file mode 100644
index 0000000..ec26ede
--- /dev/null
+++ b/about/index.html
@@ -0,0 +1,112 @@
+
+
+
+
+
+ About MACSO | Massachusetts Computer Science Olympiad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/competitions/2024/index.html b/competitions/2024/index.html
new file mode 100644
index 0000000..742b062
--- /dev/null
+++ b/competitions/2024/index.html
@@ -0,0 +1,112 @@
+
+
+
+
+
+ MACSO 2024 Archive | Massachusetts Computer Science Olympiad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/competitions/2025/index.html b/competitions/2025/index.html
new file mode 100644
index 0000000..de750e8
--- /dev/null
+++ b/competitions/2025/index.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+ MACSO Fall 2025 Archive | Massachusetts Computer Science Olympiad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/lighthouserc.json b/config/lighthouserc.json
index 5d1255e..50a9254 100644
--- a/config/lighthouserc.json
+++ b/config/lighthouserc.json
@@ -2,18 +2,59 @@
"ci": {
"collect": {
"staticDistDir": "./dist",
- "url": ["http://localhost/", "http://localhost/careers/"],
+ "url": [
+ "http://localhost/",
+ "http://localhost/careers/",
+ "http://localhost/about/",
+ "http://localhost/competitions/2024/",
+ "http://localhost/competitions/2025/"
+ ],
"numberOfRuns": 3
},
"assert": {
"assertions": {
- "categories:performance": ["warn", { "minScore": 0.9 }],
- "categories:accessibility": ["error", { "minScore": 0.95 }],
- "categories:best-practices": ["error", { "minScore": 0.9 }],
- "categories:seo": ["error", { "minScore": 0.95 }],
- "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
- "total-blocking-time": ["error", { "maxNumericValue": 300 }],
- "largest-contentful-paint": ["warn", { "maxNumericValue": 2500 }]
+ "categories:performance": [
+ "warn",
+ {
+ "minScore": 0.9
+ }
+ ],
+ "categories:accessibility": [
+ "error",
+ {
+ "minScore": 0.95
+ }
+ ],
+ "categories:best-practices": [
+ "error",
+ {
+ "minScore": 0.9
+ }
+ ],
+ "categories:seo": [
+ "error",
+ {
+ "minScore": 0.95
+ }
+ ],
+ "cumulative-layout-shift": [
+ "error",
+ {
+ "maxNumericValue": 0.1
+ }
+ ],
+ "total-blocking-time": [
+ "error",
+ {
+ "maxNumericValue": 300
+ }
+ ],
+ "largest-contentful-paint": [
+ "warn",
+ {
+ "maxNumericValue": 2500
+ }
+ ]
}
}
}
diff --git a/index.html b/index.html
index ae81620..ae44992 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,7 @@
Massachusetts Computer Science Olympiad | MACSO
@@ -60,7 +60,7 @@
/>
+
\ No newline at end of file
diff --git a/public/sitemap.xml b/public/sitemap.xml
index 6b0e860..15984a0 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -2,7 +2,7 @@
https://macso.org/
- 2026-09-14
+ 2026-10-11
monthly
1.0
@@ -12,4 +12,7 @@
monthly
0.8
+ https://macso.org/about/yearly0.6
+ https://macso.org/competitions/2024/yearly0.6
+ https://macso.org/competitions/2025/yearly0.6
diff --git a/src/components/layout/Footer.module.css b/src/components/layout/Footer.module.css
index 94929ee..4a89287 100644
--- a/src/components/layout/Footer.module.css
+++ b/src/components/layout/Footer.module.css
@@ -47,3 +47,14 @@
transition: none;
}
}
+
+.links {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ gap: 12px 24px;
+ margin: 16px 0;
+}
+.links a {
+ color: var(--accent-text);
+}
diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx
index c5acd75..555c696 100644
--- a/src/components/layout/Footer.tsx
+++ b/src/components/layout/Footer.tsx
@@ -17,16 +17,12 @@ export function Footer({ page }: FooterProps) {
Brookline Computer Science Initiative (BCSI), a 501(c)(3) non-profit
organization.
-
- Directed by{' '}
-
- Mikhail Zhernevskii
-
- , Jun 2024 - October 2024
-
+
Website is made by{' '}
diff --git a/src/components/layout/Header.module.css b/src/components/layout/Header.module.css
index f7d11c4..ac03133 100644
--- a/src/components/layout/Header.module.css
+++ b/src/components/layout/Header.module.css
@@ -143,7 +143,9 @@
}
@media (prefers-reduced-motion: reduce) {
- .nav a.hire,
+ .nav a.hire {
+ transition: none;
+ }
.themeButton,
.themeButton svg,
.brand,
@@ -152,3 +154,57 @@
transition: none;
}
}
+
+.archives {
+ position: relative;
+ font-size: 0.88rem;
+ font-weight: 700;
+}
+.archives summary {
+ cursor: pointer;
+ padding: 8px 0;
+}
+.archives summary:focus-visible {
+ outline: 3px solid var(--blue-deep);
+ outline-offset: 3px;
+}
+.archiveLinks {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ min-width: 180px;
+ display: grid;
+ gap: 4px;
+ padding: 10px;
+ background: var(--paper);
+ border: 1px solid var(--rule-strong);
+ border-radius: 8px;
+ box-shadow: var(--shadow);
+}
+.archiveLinks a {
+ padding: 10px;
+}
+.nav a[aria-current='page'] {
+ color: var(--blue-deep);
+ text-decoration: underline;
+ text-underline-offset: 5px;
+}
+@media (max-width: 520px) {
+ .header {
+ gap: 8px;
+ padding: 10px 18px;
+ }
+ .nav {
+ width: 100%;
+ gap: 4px 14px;
+ }
+ .nav a,
+ .archives {
+ font-size: 0.8rem;
+ }
+ .themeButton {
+ margin-left: auto;
+ width: 30px;
+ height: 30px;
+ }
+}
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx
index adf3694..003fcd4 100644
--- a/src/components/layout/Header.tsx
+++ b/src/components/layout/Header.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
-import { navLinks } from '~/data/site'
+import { pastCompetitions } from '~/data/competitions'
import { applyTheme, getPreferredTheme, saveTheme } from '~/lib/theme'
import { type PageId, pageMeta } from './pages'
import styles from './Header.module.css'
@@ -12,7 +12,6 @@ export function Header({ page }: HeaderProps) {
const [theme, setTheme] = useState(getPreferredTheme)
const { topId } = pageMeta[page]
const isHome = page === 'home'
- const hashBase = isHome ? '' : '/'
useEffect(() => {
applyTheme(theme)
@@ -30,11 +29,36 @@ export function Header({ page }: HeaderProps) {
macso.