Skip to content

feat: add /grants page with wave data, FAQ, and tests - #106

Open
odarome132 wants to merge 1 commit into
wraith-protocol:developfrom
odarome132:walls
Open

feat: add /grants page with wave data, FAQ, and tests#106
odarome132 wants to merge 1 commit into
wraith-protocol:developfrom
odarome132:walls

Conversation

@odarome132

@odarome132 odarome132 commented Jul 27, 2026

Copy link
Copy Markdown

_Closes #73

Summary

Adds a /grants route at src/pages/Grants.tsx giving Wave applicants a single page explaining the Wraith grant program — how Drips + external funding works, the current open wave with eligibility/review criteria, past-wave highlights with recipient details, and an accordion FAQ covering rewards, eligibility, and how to apply.

The current wave data lives in src/data/wave.json so a wave change is one file. No code changes needed to swap waves.


What changed

New files

src/pages/Grants.tsx (261 lines)

  • Hero section explaining Drips + external funding as the funding source, with a link to drips.network
  • Current wave card showing name, description, budget, funding source, status badge ("Open for applications"), reward range, how-to-apply text, and an "Apply on Drips" CTA button
  • Eligibility list and review criteria list in a two-column grid below the wave card
  • Past waves section iterating over pastWaves[] — shows name, budget, funding source, highlights, and recipients table
  • FAQ section with accordion toggles driven from faq[] entries
  • Sharp-cornered design matching the existing design system (bg-surface, bg-surface-container, border-outline-variant, text-on-surface, text-on-surface-variant, font-heading/font-body/font-mono)
  • All external links open target="_blank" rel="noopener noreferrer"

src/data/wave.json (82 lines)

  • currentWave — id, name, status ("open"), openDate, closeDate, budget ($150,000), fundingSource ("Drips + External"), description, howToApply, applyUrl, rewardRange, eligibility (4 items), reviewCriteria (5 items)
  • pastWaves[] — one entry (Wave 0: Protocol Foundation, $75,000, External, 3 highlights, 1 recipient)
  • faq[] — 7 entries: what is Drips, how funded, who can apply, how reviewed, timeline, milestones, multiple waves

src/__tests__/grants.test.tsx (170 lines, 11 tests)

  • Renders grants page for /grants route
  • Current wave section renders name and budget
  • Apply button has correct URL when wave is open
  • Eligibility and review criteria lists render all items
  • Past waves section renders when past waves exist
  • Past wave recipients render when present
  • FAQ section renders all entries
  • FAQ toggle opens and closes answers
  • Drips link in hero section has correct href
  • Back-home link renders
  • No axe violations on the grants page

Modified files

src/App.tsx

  • Added lazy import: const Grants = lazy(() => import("./pages/Grants"))
  • Added route: <Route path="/grants" element={<Grants />} />

src/components/Header.tsx

  • Desktop nav: added <Link to="/grants"> before the Stellar link, using t("header.nav.grants")
  • Mobile nav: same link with onClick={closeMenu}

src/i18n/en.json

  • Added "grants": "Grants" to header.nav

src/i18n/es.json

  • Added "grants": "Subvenciones" to header.nav

Key design decisions

  1. JSON-driven wavessrc/data/wave.json is the single source of truth. To open a new wave, edit the currentWave object and move the old one to pastWaves[]. No component changes needed.

  2. Existing page pattern — Follows the same conventions as Faq.tsx and Roadmap.tsx: lazy-loaded page component, Header + Footer composition, window.history.replaceState in tests, data imported from src/data/.

  3. No new dependencies — Uses only what the repo already provides (React, react-router-dom, Tailwind, @testing-library/react, vitest, vitest-axe).

  4. Same design tokens — Reuses the exact color palette from CLAUDE.md (surface: #0e0e0e, surface-container: #141414, on-surface: #e6e1e5, etc.). Zero border-radius everywhere. No gradients or glows.

  5. FAQ accordion pattern — Mirrors the existing FAQ page accordion: <button> with aria-expanded, conditionally rendered answer panel, "Show"/"Hide" text toggle.


Acceptance criteria checklist

  • /grants route added and linked from header (desktop + mobile)
  • Current wave info dynamic — JSON-driven so a wave change is one file edit
  • Tests mirror the repo existing pattern (App-level render, role-based queries, userEvent, axe)
  • Typecheck passes — pnpm exec tsc --noEmit exits cleanly
  • Build passes — pnpm build succeeds (tsc, vite build, inline-css, OG generation, sitemap)
  • Full test suite passes — 30 tests across 7 files
  • Grants.tsx coverage: 100% statements, 95% branches, 100% functions, 100% lines
  • Only in-scope files staged — no lockfile churn, no node_modules, no coverage output

Test output

 RUN  v4.1.9

 ✓ src/__tests__/grants.test.tsx (11 tests) 3090ms

 Test Files  7 passed (7)
      Tests  30 passed (30)

Coverage for changed files

File % Stmts % Branch % Funcs % Lines Notes
Grants.tsx 100 95 100 100 Line 90 else branch uncovered (ternary for status != "open"; data always has "open")
Header.tsx 54.54 48.33 60 57.14 Pre-existing branches unrelated
App.tsx 84.21 100 70 100 Pre-existing lazy boundary

Note: The 95% branch is the currentWave.status === "open" ternary. To cover the else branch, change status to something other than "open" in wave.json. This is expected — a wave is either open or closed, never both simultaneously.


Follow-ups

  1. Coverage in CI — Add @vitest/coverage-v8 to devDependencies and wire --coverage into the CI test step. Currently absent from the lockfile (I installed it locally for manual verification but did not commit it per the frozen-install convention).
  2. Wave rotation — When Wave 1 closes, update src/data/wave.json: set currentWave.status to "closed", move Wave 1 into pastWaves[], and populate currentWave with Wave 2 data. That is it — no code changes.
  3. OG image — No dedicated OG image for /grants yet. Could reuse the home OG or generate a grants-specific one in scripts/og.ts.
  4. Sitemap — The sitemap script discovers routes from App.tsx via regex. The build output confirms 7 routes — including /grants — were found. No action needed unless the regex breaks on future route patterns.

Security

  • No secrets, API keys, environment variables, or credentials introduced
  • All external URLs (drips.network, usewraith.xyz) use HTTPS
  • Third-party links use target="_blank" with rel="noopener noreferrer"
  • No user input or dynamic content rendering — static data from a JSON file
  • No new npm dependencies added to package.json

@truthixify

Copy link
Copy Markdown
Contributor

Retarget from main to develop. Wave PRs go into develop; the +10k diff is because your branch is behind main.

@truthixify
truthixify changed the base branch from main to develop July 29, 2026 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants