Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,43 @@ This repository builds the **Hack Michigan (HackMI)** marketing site. It started

## [Unreleased]

## [1.1.4] - 2026-05-19

### Added

- Typed Sanity fetch layer (`src/lib/sanity/fetchers.ts`): `safeFetch` wrappers, optional strict mode via `PUBLIC_SANITY_STRICT_MODE`, and `getChallengeWinners()` for sponsor challenge winners.
- **`awardingSponsor`** on hackathon projects in Sanity (radio list, one winner per sponsor) with Studio validation preventing duplicate winners (`studio-hack-michigan-/schemaTypes/hackathonProject.ts`).
- Shared sponsor-challenge metadata (`src/lib/sanity/challengeSponsors.ts`, `studio-hack-michigan-/schemaTypes/challengeSponsors.ts`) kept in sync between Studio and the site.
- **`SponsorWinnersSection`** on `/projects/` — highlights DTE, StartMidwest, AI Collective Detroit, and Compass Detroit challenge winners with logos and links to project detail pages (`src/components/SponsorWinnersSection.astro`).
- Static winner fallbacks (`src/data/challengeWinnerFallbacks.ts`) until every winning project is tagged in Sanity.
- Team **`teamDescription`** portable text (up to 1,000 plain-text characters) and wide-logo guidance on team documents; rendered on `/projects/team/[slug]/` (`studio-hack-michigan-/schemaTypes/team.ts`).
- **`hasSanityImage`** image guard and `teamLogo` URL helper in the Astro Sanity client layer.
- **`portableTextPlainLength`** utility in Studio for consistent portable-text length validation (`studio-hack-michigan-/schemaTypes/portableTextUtils.ts`).
- **Media** and **Fuel** sponsor tiers; logos for Why Not Collab (media) and Luminesso Coffee (fuel).
- AI Collective Detroit as a **community** sponsor.
- Navigation **scroll-spy** (IntersectionObserver) so active nav links track the section in view (`src/components/Navigation.astro`, `src/data/nav.ts`).
- `rel="sponsored"` on external sponsor links via `MaybeLink` (`src/components/primitives/MaybeLink.astro`).
- Shared deploy **rate-limit** module (`src/lib/deploy/rate-limit.js`).
- Vitest coverage for challenge sponsors, fetchers, team logos, `MaybeLink`, and sponsor logo data.
- Playwright visual-regression baselines for the projects grid and related UI updates.

### Changed

- Playwright E2E specs updated to match the new `/projects/` route for the “Projects” navigation link (instead of asserting `/hackathon/`).
- Canonicalized the legacy `/hackathon/` listing URL by redirecting it to `/projects/` (detail routes under `/hackathon/*` remain unchanged).
- Hackathon browsing moved under **`/projects/`**: listing, project detail, team detail, and variants routes now live in `src/pages/projects/` (removed `src/pages/hackathon/index.astro`).
- **Vercel redirects** send `/hackathon/` and legacy `/hackathon/project/*` and `/hackathon/team/*` URLs to their `/projects/` equivalents (`vercel.json`).
- Playwright E2E specs updated for the `/projects/` “Projects” nav target (replacing `/hackathon/`).
- Refactored **project cards** and project/team detail layouts (`src/components/cms/ProjectCard.astro`, `src/pages/projects/project/[slug].astro`, `src/pages/projects/team/[slug].astro`).
- Event **schedule/agenda** aligned with the finalized three-day agenda (`src/data/eventAgenda.ts`).
- Landing-page **section order** matches navigation; dim secondary text uses a shared `--font-size-body` fluid scale (`src/styles/global.css`).
- Sponsor logo data expanded (additional tiers/logos, `rel=sponsored` behavior, tests in `src/data/sponsorLogos.test.ts`).
- Sanity Studio dependency refresh (`studio-hack-michigan-/package.json`).

### Fixed

- Team description validation counts **plain-text characters**, not Portable Text blocks.
- Duplicate `.team-description` wrapper and unsupported `max-width: stretch` on team pages.
- Luminesso logo **light surface** treatment and fuel-tier grid layout.
- Sponsor link UX, register URLs, mobile breakpoints, and Playwright CI routing.

## [1.1.3] - 2026-05-01

Expand Down Expand Up @@ -134,6 +167,7 @@ _Initial [astro-darkness](https://github.com/kpab/astro-darkness) template relea
- @astrojs/rss for feed generation
- @astrojs/sitemap for SEO optimization

[1.1.4]: https://github.com/Compass-Detroit/hackmi26/compare/v1.1.3...v1.1.4
[1.1.3]: https://github.com/Compass-Detroit/hackmi26/compare/v1.1.2...v1.1.3
[1.1.2]: https://github.com/Compass-Detroit/hackmi26/compare/v1.1.1...v1.1.2
[1.1.1]: https://github.com/Compass-Detroit/hackmi26/compare/v1.1.0...v1.1.1
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Marketing site and hackathon showcase for **Hack Michigan** — [hackmichigan.co

![Hack Michigan social card](public/social-card.jpg)

[![Version](https://img.shields.io/badge/version-1.1.1-blue)](https://github.com/Compass-Detroit/hackmi26/releases)
[![Version](https://img.shields.io/badge/version-1.1.4-blue)](https://github.com/Compass-Detroit/hackmi26/releases)
[![Astro](https://img.shields.io/badge/Astro-5-purple)](https://astro.build/)
[![Three.js](https://img.shields.io/badge/Three.js-0.160-blue)](https://threejs.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hackmichigan",
"type": "module",
"version": "1.1.1",
"version": "1.1.4",
"description": "Hack Michigan (HackMI) — marketing site and hackathon showcase for the Detroit tech corridor, built with Astro + Sanity.",
"keywords": [
"astro",
Expand Down
130 changes: 130 additions & 0 deletions src/components/SponsorChallengeSection.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
import Button from "./primitives/Button.astro";
import { EVENT_URLS } from "../data/event";
---

<section class="sponsor-challenge" aria-labelledby="sponsor-challenge-heading">
<div class="sponsor-copy">
<p class="sponsor-challenge__eyebrow">Sponsor an AI challenge</p>
<h2 id="sponsor-challenge-heading">
Put a real business problem in front of builders.
</h2>
<p>
Hack Michigan sponsors can design an AI challenge around a workforce,
operations, civic, or customer problem they need solved. Teams spend the
hackathon building toward that use case, giving sponsors a direct path
from support to working prototypes, fresh talent, and clearer next steps.
</p>
</div>

<div class="sponsor-panel">
<h3>What sponsorship can look like</h3>
<ul>
<li>Bring a practical AI use case from your organization.</li>
<li>Help shape judging criteria and success outcomes.</li>
<li>Meet teams solving problems tied to your work.</li>
<li>Support workforce development with measurable builder output.</li>
</ul>
<Button href={EVENT_URLS.sponsorInquiry}>Start a sponsor challenge</Button>
</div>
</section>

<style>
.sponsor-challenge {
display: grid;
grid-template-columns: minmax(0, 1.2fr) minmax(18rem, 0.8fr);
gap: var(--space-lg);
align-items: stretch;
margin-bottom: var(--space-2xl);
padding: clamp(1.5rem, 4vw, 2.5rem);
border: 1px solid var(--color-border);
border-radius: var(--radius-xl);
background:
radial-gradient(
circle at 15% 20%,
rgb(139 92 246 / 24%),
transparent 35%
),
var(--surface-glass-raised-bg);
box-shadow: var(--shadow-glass);
}

.sponsor-copy {
align-self: center;
}

.sponsor-challenge__eyebrow {
margin: 0 0 var(--space-xs);
color: var(--color-accent-orange);
font-size: 0.82rem;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
}

.sponsor-copy h2,
.sponsor-panel h3 {
color: var(--color-text);
line-height: 1.1;
}

.sponsor-copy h2 {
max-width: 12ch;
margin-bottom: var(--space-sm);
font-size: clamp(2rem, 6vw, 3.5rem);
}

.sponsor-copy p {
max-width: 690px;
color: var(--color-text-dim);
font-size: 1.08rem;
line-height: 1.7;
}

.sponsor-panel {
display: flex;
flex-direction: column;
gap: var(--space-sm);
padding: var(--space-md);
border: 1px solid rgb(130 177 254 / 30%);
border-radius: var(--radius-lg);
background: rgb(2 6 23 / 48%);
}

.sponsor-panel h3 {
font-size: 1.35rem;
}

.sponsor-panel ul {
display: grid;
gap: var(--space-xs);
margin: 0;
padding-left: 1.1rem;
color: var(--color-text-dim);
line-height: 1.55;
}

.sponsor-panel li::marker {
color: var(--color-accent-orange);
}

.sponsor-panel :global(.btn) {
align-self: flex-start;
margin-top: auto;
}

@media (max-width: 48rem) {
.sponsor-challenge {
grid-template-columns: 1fr;
margin-bottom: var(--space-xl);
}

.sponsor-copy h2 {
max-width: 100%;
}

.sponsor-panel :global(.btn) {
align-self: stretch;
}
}
</style>
Loading
Loading