Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
6d5a47f
chore(deploy): remove stale deploy-all.js, fix stale prod URLs
sacha-l May 22, 2026
ab25618
Merge pull request #146 from StadiumDevs/chore/remove-stale-deploy-to…
sacha-l May 22, 2026
0f8e0b6
copy: rename user-facing 'UNIT' label to 'ENTRY'
sacha-l May 22, 2026
b32749d
Merge pull request #147 from StadiumDevs/chore/rename-unit-to-entry
sacha-l May 22, 2026
b458df4
feat(landing): program-type spaces entry point + per-program projects…
sacha-l May 22, 2026
5f2507c
Merge pull request #148 from StadiumDevs/feat/landing-program-spaces
sacha-l May 22, 2026
0175d38
security: add helmet headers + express-rate-limit (#127, #128)
sacha-l May 22, 2026
aa78ca1
feat(programs): non-member apply flow — emails the team (#140)
sacha-l May 22, 2026
8fe9b9d
Merge pull request #149 from StadiumDevs/chore/security-hardening
sacha-l May 22, 2026
7ef2a54
Merge pull request #150 from StadiumDevs/feat/non-member-apply
sacha-l May 22, 2026
716c3c5
fix(audio): persist SoundCloud playback across navigation + now-playi…
sacha-l May 22, 2026
03b2fcc
feat(auth): server core for social sign-in (Supabase) with wallet acc…
sacha-l May 22, 2026
4e69897
feat(programs): templatable rich content sections per program
sacha-l May 22, 2026
4d6a104
docs(env): correct stale Resend comment — transport is now live
sacha-l May 22, 2026
62478d6
feat(brightness-rack): audio transport — prev/next + seek slider
sacha-l May 22, 2026
3ba026d
Merge pull request #151 from StadiumDevs/fix/soundcloud-persist-audio
sacha-l May 22, 2026
7de0982
Merge pull request #152 from StadiumDevs/feat/social-signin
sacha-l May 22, 2026
cb5bbc0
Merge pull request #153 from StadiumDevs/feat/program-content-sections
sacha-l May 22, 2026
4b8a1b8
Merge pull request #154 from StadiumDevs/chore/resend-email-config
sacha-l May 22, 2026
78475b4
Merge branch 'develop' into feat/audio-player-controls
sacha-l May 22, 2026
38b735c
fix(audio): re-integrate transport with the SoundCloudAudioProvider
sacha-l May 22, 2026
ab776f3
feat(brightness-rack): rewind/forward 15s within the current track
sacha-l May 22, 2026
b4b3da9
copy(programs): reframe the WHAT WE DO blurb around events + prizes
sacha-l May 22, 2026
3c580ae
Merge pull request #155 from StadiumDevs/feat/audio-player-controls
sacha-l May 22, 2026
db83e35
Merge pull request #156 from StadiumDevs/copy/programs-framing
sacha-l May 22, 2026
4a34641
copy: remove em-dashes from first-party app copy
sacha-l May 22, 2026
60777e4
feat(admin): email-keyed program admins + onboarding invite (backend)
sacha-l May 22, 2026
ab8e18c
feat(admin): client — email magic-link sign-in + invite-by-email UI
sacha-l May 22, 2026
b394b4f
Merge pull request #158 from StadiumDevs/feat/admin-email-invites
sacha-l May 22, 2026
b6b6fec
Merge pull request #157 from StadiumDevs/copy/remove-em-dashes
sacha-l May 22, 2026
59f5a57
fix(security): rate-limit the public non-member apply route
sacha-l May 22, 2026
c8c3a73
chore(auth): remove unused social account-linking bridge (#152)
sacha-l May 22, 2026
b1fcd1f
feat(landing): logo mark by STADIUM, looping audio, unified footer
sacha-l May 22, 2026
96d9455
Merge pull request #159 from StadiumDevs/fix/rate-limit-non-member-apply
sacha-l May 22, 2026
71f7a66
Merge pull request #160 from StadiumDevs/chore/remove-dead-social-lin…
sacha-l May 22, 2026
3bf9a17
Merge pull request #161 from StadiumDevs/feat/landing-logo-footer-audio
sacha-l May 22, 2026
fcf09b7
design: project-details typography + landing tagline + brightness tim…
sacha-l May 22, 2026
df3cd13
Merge pull request #163 from StadiumDevs/design/reland-round2-polish
sacha-l May 22, 2026
932eb92
hardening: boot secret validation, req.user.chain, shared csvCell util
sacha-l May 22, 2026
6fe5a2f
Merge pull request #164 from StadiumDevs/hardening/release-quick-wins
sacha-l May 22, 2026
50c8188
chore(release): v1.0.0 — add CHANGELOG + align client version
sacha-l May 22, 2026
7a90a19
docs(release): drop Polkadot-only framing from v1.0.0 notes
sacha-l May 22, 2026
e0b3494
feat(nav): replace ONLINE indicator with a v1.0 badge linking to the …
sacha-l May 22, 2026
d753a72
Merge pull request #165 from StadiumDevs/chore/release-v1.0.0
sacha-l May 22, 2026
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
67 changes: 67 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Changelog

All notable releases to Stadium are documented here.

## v1.0.0 — First official release

Stadium is the home for **WebZero's builder programs**. It started as the site for a single hackathon and is now a recurring-events platform: hackathons, the M2 incubator, dogfooding sessions, and PitchOff competitions all live in one place, where builders show their work, the community explores it, and organizers run each event end to end.

### Who it's for

- **Visitors & the community** — anyone who wants to browse what's been built and discover teams.
- **Builders & teams** — the people who ship projects in WebZero programs and want them seen, supported, and funded.
- **Organizers & admins** — the WebZero team (and per-event partners) who run programs, review work, and pay out winners.

---

## What you can do with Stadium

### Discover & explore — for everyone, no account needed

- **Start from the landing page**, an entry point with a "space" for each program type (Hackathons, M2 Incubator, Dogfooding, PitchOff) that explains what each is.
- **Browse the directory** of every project/entry, with search and filtering, and live index stats (total entries, winners, projects in M2, total paid out).
- **Open any program** to see all of its projects.
- **Dive into a project** across tabs — overview, milestones, team, and updates — including live links (site, repo, demo, slides) and a "seeking funding" signal when a team is raising.
- **See the winners** of past events on dedicated winners pages.
- **Set the vibe** with the hardware-style brightness rack: a time-of-day theme and a SoundCloud player that keeps playing as you move between pages.

### Show your work & take part — for builders & teams

- **Sign in with your wallet** using SIWS (Sign-In With Substrate), with multi-chain support across Substrate, Ethereum, and Solana wallets.
- **Apply to a program** as a team — or, if you don't have a Stadium project yet, **apply as a non-member** and Stadium emails the right team on your behalf.
- **Create and edit your project** — name, description, links, tech stack, and categories.
- **Manage your team and payout address**, including per-member roles and socials.
- **Post project updates** to keep the community and organizers in the loop.
- **Raise your hand for funding** by setting a funding signal on your project.
- **Run the M2 incubator track** end to end: agree on milestones, submit your final deliverables, watch your review status, and propose what comes next with a continuation ("what's next, milestone 3?").
- **Attach a contact email to your wallet** so organizers can reach you.

### Run your event — for organizers & admins

- **Sign in two ways:** with an admin **wallet** (SIWS), or via an **email magic link** for view-only program admins who don't use a wallet — with an onboarding email when they're invited.
- **Work within a tiered admin model:** app admins, global admins, and per-program admins, so partners can be scoped to just their event.
- **Create and edit programs** — hackathon, M2 incubator, dogfooding, or PitchOff — with dates, status, and rich, templatable content sections.
- **Manage sponsors** for each program.
- **Collect and triage participation** in one unified inbox that merges in-app applications and signups, **import attendees from a Luma CSV**, and **export the inbox to CSV** (hardened against spreadsheet formula-injection).
- **Apply on behalf of any project** as an admin when you need to.
- **Invite co-admins** by wallet or by email, and manage the admin list per program.
- **Review M2 submissions** — approve them or request changes.
- **Record and confirm payouts** in multiple currencies (USDC / DOT).
- **Keep an audit trail** with a per-program audit log of admin actions.

### Trust, safety & platform

- **SIWS verification** always checks the address inside the signed message, never a request header.
- **One sign-in, fewer popups:** a short-lived HMAC session token replaces repeated wallet signatures; the signing secret is validated at server boot.
- **Hardened by default:** security headers (helmet) and rate limiting on sensitive and public endpoints.
- **Privacy-aware:** public project data excludes personal contact information.

---

## Under the hood

- **Client:** React 18 + Vite + TypeScript + Tailwind + shadcn/ui, deployed to Vercel.
- **Server:** Express 5 (ESM) on Supabase (Postgres), deployed to Railway.
- **Auth:** multi-chain wallet sign-in via SIWS (Substrate, Ethereum, Solana), plus Supabase email magic-link for non-wallet admins.

Live at <https://stadium.joinwebzero.com>.
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Always run from the subdir, not the repo root.
- `npm test` — `vitest run`
- `npm start` — `node server.js`
- `npm run seed:dev`, `npm run db:migrate`, `npm run db:reset` — local Mongo tooling (destructive; run only when asked)
- `npm run verify:production`, `npm run verify:main-deployed`, `npm run deploy:all` — operational
- `npm run verify:production`, `npm run verify:main-deployed` — operational (read-only prod health checks). Deploys are automatic: merging to `main` triggers Railway (server) + Vercel (client) via their GitHub integrations.

---

Expand Down
10 changes: 9 additions & 1 deletion client/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@
# For local development:
VITE_API_BASE_URL=http://localhost:2000/api
# For production:
# VITE_API_BASE_URL=https://hw4os4c00wg4k80o.apps.joinwebzero.com/api
# VITE_API_BASE_URL=https://stadium-production-996a.up.railway.app/api

# Admin wallet addresses (comma-separated). Each entry is either `chain:address`
# or a bare address (bare ⇒ substrate). Supported chains: substrate, ethereum.
# Example: VITE_ADMIN_ADDRESSES=5Grw...,ethereum:0xAbC123...
VITE_ADMIN_ADDRESSES=

# Supabase Auth (social sign-in / email magic link). Used by the client to let
# email-invited program admins sign in without a wallet. Both must be set or
# email sign-in shows as "not configured". The ANON key is public (safe to ship
# to the browser); the server still authorizes via program_admin_emails.
# Get these from the Supabase dashboard (Project Settings → API).
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=

# Preview / offline mode: when "true", the client serves fixtures from
# src/lib/mockWinners.ts instead of calling the API. Writes are simulated in
# localStorage. Production must leave this unset or "false". Set to "true" in
Expand Down
94 changes: 94 additions & 0 deletions client/package-lock.json

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

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "client",
"private": true,
"version": "0.0.0",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down Expand Up @@ -45,6 +45,7 @@
"@radix-ui/react-toggle": "^1.1.9",
"@radix-ui/react-toggle-group": "^1.1.10",
"@radix-ui/react-tooltip": "^1.2.7",
"@supabase/supabase-js": "^2.106.1",
"@talismn/siws": "^1.0.0",
"@tanstack/react-query": "^5.56.2",
"bs58": "^6.0.0",
Expand Down
3 changes: 3 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ProjectDetailsPage from "./pages/ProjectDetailsPage";
import AdminPage from "./pages/AdminPage";
import NotFound from "./pages/NotFound";
import { useBrightness } from "@/hooks/use-brightness";
import { SoundCloudAudioProvider } from "@/components/audio/sound-cloud-audio";
import WinnersPage from "./pages/WinnersPage";
import ProgramsPage from "./pages/ProgramsPage";
import ProgramDetailPage from "./pages/ProgramDetailPage";
Expand All @@ -35,6 +36,7 @@ const App = () => {
<TooltipProvider>
<Toaster />
<Sonner />
<SoundCloudAudioProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
Expand All @@ -57,6 +59,7 @@ const App = () => {
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
</SoundCloudAudioProvider>
</TooltipProvider>
</QueryClientProvider>
</ErrorBoundary>
Expand Down
82 changes: 3 additions & 79 deletions client/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { Link, Outlet, useLocation } from "react-router-dom";
import { Outlet } from "react-router-dom";
import { SiteFooter } from "@/components/SiteFooter";

const Layout = () => {
const location = useLocation();

const isActive = (path: string) => {
if (path === "/" && location.pathname === "/") return true;
if (path !== "/" && location.pathname.startsWith(path)) return true;
return false;
};

return (
<div className="min-h-screen bg-background">
{/* Skip to main content link for keyboard navigation */}
Expand All @@ -24,76 +17,7 @@ const Layout = () => {
<Outlet />
</main>

{/* Footer */}
<footer className="border-t bg-muted/50 py-8 mt-16">
<div className="container">
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">


<div className="flex items-center space-x-2">
<span className="text-sm text-muted-foreground">
Created with ❤️ by the cracked devs at {' '}
<a
href="https://www.joinwebzero.com/"
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline transition-colors"
>
WebZero
</a>
</span>
</div>
<div className="flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4">
<div className="flex flex-wrap items-center justify-center gap-2 sm:gap-4">
<a
href="https://luma.com/blockspace-symmetry"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-primary hover:underline transition-colors"
>
Blockspace Symmetry 2024
</a>
<span className="hidden sm:inline text-muted-foreground">•</span>
<a
href="https://luma.com/blockspacesynergy"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-primary hover:underline transition-colors"
>
Blockspace Synergy 2025
</a>
<span className="hidden sm:inline text-muted-foreground">•</span>
<a
href="https://luma.com/sub0hack"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-primary hover:underline transition-colors"
>
sub0 Hack 2025
</a>
</div>
</div>
<div className="flex items-center space-x-4">
<Link
to="https://github.com/JoinWebZero/"
className="text-sm text-muted-foreground hover:text-primary transition-colors"
target="_blank"
rel="noopener noreferrer"
>
GitHub
</Link>
<Link
to="https://x.com/JoinWebZero"
className="text-sm text-muted-foreground hover:text-primary transition-colors"
target="_blank"
rel="noopener noreferrer"
>
X
</Link>
</div>
</div>
</div>
</footer>
<SiteFooter />
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/M2AgreementSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export function M2AgreementSection({
<div className="mb-5">
<div className="flex items-center gap-2 mb-2">
<CheckCircle className="w-3.5 h-3.5 text-led" />
<span className="label-hw text-display">·CORE FEATURES MUST COMPLETE</span>
<span className="label-hw text-display">·CORE FEATURES: MUST COMPLETE</span>
</div>
<div className="lcd p-4">
<ul className="space-y-2">
Expand Down Expand Up @@ -184,7 +184,7 @@ export function M2AgreementSection({
) : (
<div className="flex items-start gap-2 lcd p-3 border-destructive">
<AlertCircle className="w-3.5 h-3.5 mt-0.5 text-destructive flex-shrink-0" />
<p className="label-hw text-destructive">·ROADMAP LOCKED AFTER WEEK 4 CONTACT YOUR MENTORS IF YOU NEED CHANGES.</p>
<p className="label-hw text-destructive">·ROADMAP LOCKED AFTER WEEK 4. CONTACT YOUR MENTORS IF YOU NEED CHANGES.</p>
</div>
)}
</div>
Expand Down
Loading