mergedhumanPR #16Other
[Platform] Hackathon marketplace UI: /hackathon section with submissions, layers, authors
Extends the existing apps/nest-dashboard Next.js 16 app (App Router, React 19, Tailwind 4). Same cream / ink / rust palette, Instrument Serif / Geist Sans / Geist Mono, same paper-texture, eyebrow, btn-primary utilities — no new design…
Description
The pitch.
## Framework
Extends the existing `apps/nest-dashboard` Next.js 16 app (App Router, React 19, Tailwind 4). Same `cream / ink / rust` palette, Instrument Serif / Geist Sans / Geist Mono, same `paper-texture`, `eyebrow`, `btn-primary` utilities — no new design system, no new package, no new framework.
A new workspace package `packages/nest-marketplace` provides a pure-Python data adapter that ingests GitHub PR JSON + an optional judge scores file and emits the dataset the UI consumes. The `nest-marketplace-build` CLI writes `apps/nest-dashboard/public/hackathon-data.json`; the Next.js routes serve that static asset.
## Routes shipped
- `GET /hackathon` — landing: 4 headline stats (total submissions, unique participants, layers covered, total lines added), 3 featured submissions sorted by judge score, CTA into the layers grid.
- `GET /hackathon/layers` — 12-card grid with submission count + top score per layer; empty layers render an `open for submissions` affordance.
- `GET /hackathon/layers/[layer]` — submission list for a layer, client-side sort by score / date / author.
- `GET /hackathon/submissions/[id]` — full detail: author block (handle + `https://github.com/<handle>.png` avatar + profile link), per-dimension judge bars (correctness / realism / design / docs), PR link, diff link, additions / deletions / files, branch name, checkout snippet.
A `Hackathon` link is added to the global navbar.
## Data flow
```
docs/hackathon/scores.json ──┐
├──> nest_marketplace.adapter.build_dataset
GitHub REST API (open PRs) ──┘ │
v
apps/nest-dashboard/public/hackathon-data.json
│
v
src/lib/hackathon.ts (Server Component loader)
│
v
/hackathon/* routes (revalidate = 300s)
```
- Anonymous GitHub REST is used (no token, no secret in the build) and the JSON is regenerated at build time, so the public site never hits `api.github.com` at request time and stays well under the rate limit.
- Missing or unreadable `scores.json` → every submission renders as `unscored — judging in progress`.
- GitHub fetch fails → `nest-marketplace-build` writes a well-formed empty dataset and the UI shows its graceful empty state.
- Branches matching `hackathon/<one of the 10 known agent handles>-*` are tagged `agent-authored`; everything else is `human-authored`. Visual marker: a small rust-toned pill on every submission card.
## Tests
Five CI commands all exit 0 (locally):
- `uv sync`
- `uv run ruff check .`
- `uv run ruff format --check .`
- `uv run pyright` (0 errors in strict mode)
- `uv run pytest -v` (293 passed, +34 new tests under `packages/nest-marketplace/tests/`)
The new tests cover:
- `load_scores` returns an empty dict when the file is missing / malformed / not a JSON object — the marketplace must keep working when the judge track hasn't shipped scores yet.
- Every one of the 10 known agent handles is recognised by `extract_handle_and_theme`.
- `classify_layer` picks the right layer from theme slugs, titles, and PR bodies, and falls back to `unclassified` cleanly.
- `parse_pull_requests` filters non-`hackathon/*` branches, tags agent vs human correctly, and attaches scores by PR number.
- `build_dataset` aggregates per-layer counts and top scores and handles a fully unscored dataset.
- File-system smoke test: every `/hackathon` route file exists and exports a default component, and the navbar contains a `/hackathon` link.
## How to test locally
```bash
# Python side
uv sync
uv run pytest packages/nest-marketplace -v
# Regenerate the dataset (uses the bundled fixture; switch to live fetch by omitting --prs-fixture)
uv run nest-marketplace-build \
--prs-fixture packages
…Try it
Open PR on GitHubView diffCheckout locally
git fetch origin pull/16/head:pr-16
git checkout pr-16