Skip to content

Add Markee protocol integration#317

Open
pglavin2 wants to merge 27 commits intogitcoinco:mainfrom
pglavin2:markee-integration
Open

Add Markee protocol integration#317
pglavin2 wants to merge 27 commits intogitcoinco:mainfrom
pglavin2:markee-integration

Conversation

@pglavin2
Copy link
Copy Markdown

@pglavin2 pglavin2 commented Apr 8, 2026

Summary

  • Adds a Markee sign to the homepage hero -- an on-chain leaderboard where anyone can pay ETH to put their message front and center on gitcoin.co
  • Includes a buy/boost modal with wallet connection (wagmi + RainbowKit on Base)
  • View tracking (eye icon + count) via markee.xyz proxy
  • Content moderation system: admin wallets can flag messages, flagged content is blurred for regular users
  • Integration health check endpoint at /api/markee/health

New files

Path Description
src/lib/markee.ts Contract address, ABI, and shared constants
src/components/MarkeeSign.tsx Homepage card -- displays top message, view count, flag button
src/components/MarkeeModal.tsx Buy/boost modal with tab UI and wagmi transaction flow
src/components/moderation/ ModerationProvider, ModeratedContent, FlagButton
src/lib/moderation/config.ts Admin wallet addresses and moderation defaults
src/providers/Web3Provider.tsx wagmi + RainbowKit + TanStack Query provider
src/app/api/markee/ Server-side proxies for leaderboard data, view tracking, health check
src/app/api/moderation/route.ts Flag/unflag API backed by Vercel KV

Modified files

Path Change
src/app/layout.tsx Wraps app in Web3Provider and ModerationProvider
src/app/page.tsx Adds MarkeeSign to homepage hero, centered above "Your Map" label
src/app/api/chat/route.ts Lazy-init OpenAI client to prevent build-time crash when OPENAI_API_KEY is absent
src/components/layouts/AppSidebarClient.tsx Removes old sidebar placement of MarkeeSign

Required env vars

Two env vars need to be added in the Vercel project settings:

NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID (required for wallet connection)

Get a free project ID at https://cloud.walletconnect.com. Without this, the buy modal will not work for mobile wallets. The app logs a warning at startup if this is missing.

KV_REST_API_URL + KV_REST_API_TOKEN (required for moderation)

Create a KV store in the Vercel dashboard (Storage tab) and link it to the project. These vars are auto-populated when you link a KV store. Without them, the moderation API returns 500 and flag/unflag actions silently roll back on the client.

NEXT_PUBLIC_BASE_RPC_URL (optional, recommended)

Set to a dedicated Base RPC URL (e.g. Alchemy or Infura) to avoid rate limiting on the boost tab leaderboard reads. Falls back to the public Base RPC if not set.

Review feedback addressed (latest commit)

  • Form state lifted to MarkeeSign so message/name/ETH amount persist when the modal closes and reopens (e.g. during wallet connect)
  • Wallet connect reopen fixed: openConnectModal moved to MarkeeSign; a pendingReopenModal flag reopens the dialog after RainbowKit closes -- fixes the unmounted component issue
  • isError handled on boost tab contract reads -- shows "Failed to load messages. Please try again." instead of hanging in a loading state (avoids confusion on RPC rate limit errors)
  • Whole card clickable -- cursor: pointer on the card container, FlagButton stops propagation
  • UX copy: "Loading..." capitalized, "Refreshing in a moment..." replaced with "Your message may take up to a minute to appear."
  • Contrast: text-gray-600 bumped to text-gray-500 on owner name, view count, and footer text

Test plan

  • Homepage loads and shows the Markee card in the hero section
  • Clicking anywhere on the card (not just the message text) opens the buy modal
  • Wallet connect flow: clicking "Connect Wallet" opens RainbowKit, form data is preserved when the Markee modal reopens after connecting
  • Wallet connects and transaction flow completes on Base
  • View count appears (eye icon, bottom right of card)
  • Boost tab shows error message if contract reads fail (not a stuck loading spinner)
  • /api/markee/health returns { overall: "ok" } after env vars are set
  • Admin wallet can flag/unflag messages (requires KV vars)

🤖 Generated with Claude Code

pglavin2 and others added 24 commits April 7, 2026 15:19
Adds a community-funded message widget powered by the Markee protocol.
Anyone can pay ETH to set the featured message displayed site-wide.
The widget polls for updates every 60 seconds and requires no config.
- Add wagmi, viem, RainbowKit, TanStack Query
- Add Web3Provider wrapping the app in layout.tsx
- MarkeeSign: minimal inline display, hover reveals price badge, click opens modal
- MarkeeModal: full buy flow in Gitcoin theme (gray-900/teal), leaderboard toggle,
  ETH amount picker, wallet connection, chain switching -- no handoff to markee.xyz
- Sits below Case Studies in the blank space using mt-auto flex layout
- Naturally fills sidebar width and responds to resize (180-520px)
- Hidden on mobile (sidebar is desktop-only)
- Price badge on hover; pb-6 prevents badge clipping by overflow-hidden
- Remove from footer
… shared constants

- Extract LEADERBOARD_ADDRESS, API_URL, MIN_INCREMENT, LEADERBOARD_ABI to lib/markee.ts
- Add res.ok checks before res.json() in both MarkeeSign and MarkeeModal
- Switch from writeContract to writeContractAsync so try/catch actually catches errors
- Fix Connect Wallet flow: open RainbowKit without closing the dialog; use
  connectModalOpen to reopen dialog after wallet connection instead of broken
  hiddenForConnect + dialogRef.close() pattern
- Add console.error warning when WalletConnect projectId is missing
- Remove unused http import from Web3Provider
viem and wagmi both require ES2020-capable environments; BigInt literals
(0n, 1n) used in MarkeeModal and MarkeeSign require at minimum ES2020.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…projectId

Passing an invalid string causes WalletConnect to initialize and fail at
runtime. Passing undefined lets RainbowKit skip the connector gracefully.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…res string not undefined

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…API_KEY is absent

Next.js imports route modules at build time to collect metadata; top-level
new OpenAI() throws immediately if the env var is not set. Defer construction
to first request via a lazy getter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lable

When the markee.xyz API is unreachable (e.g. CORS on staging), the sign
previously disabled itself and showed "unavailable". Now it silently falls
back to DEFAULT_DATA so the modal stays openable and usable via contract reads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Client-side fetches to markee.xyz require CORS headers the markee team
would need to configure. A local proxy route fetches server-side instead,
making the integration self-contained for any site doing this integration.

Caches 60s at the CDN edge to match the upstream TTL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Leaderboard now reads all top markees directly from contract via
  getTopMarkees(10) + useReadContracts, instead of the API which only
  returned the single top entry
- Wallet connect modal no longer appears behind the dialog: dialog is
  closed before openConnectModal() fires, reopens when it closes
- Header: title changed to "Change Gitcoin's Markee Message", subtitle removed
- Modal width: max-w-md -> max-w-md sm:max-w-xl for larger screens
- Message textarea text is centered
- Dedicated low-balance banner shown when connected balance < minimumPrice
- Wrong network Switch button label updated to "Switch to Base"
- Bottom copy updated with Gardens community link for Markee Network

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tab bar: "Buy a Message" / "Boost Existing Message"
- Boost tab: top 5 messages from contract, click to select, add funds
  via addFunds(markeeAddress); take-top-spot amount calculated per entry;
  "Add Funds to this Message" button; see-more / edit link below list
- Success state: full-panel confirmation with Basescan tx link
- Wallet connect: dialog closes before openConnectModal fires
- Balance: clickable to fill ETH amount; inline warning when amount exceeds balance
- Left-justified text in all message fields (removed text-center)
- Markee logo added to modal header
- Wrong network + low balance banners on both tabs
- MARKEE_ABI and getTopMarkees added to src/lib/markee.ts

Note: wallet console errors (Cannot redefine property: ethereum,
MetaMask provider conflict) are browser extension conflicts between
multiple wallet extensions -- not fixable in app code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Network detection: use useAccount().chainId (account-bound) instead of
  useChainId() to stay in sync with connected wallet across multi-extension
  environments; isOnBase guards false when chainId is undefined
- Chain mismatch errors from writeContractAsync now caught and shown as
  "Wrong network" message rather than generic "Transaction failed"
- Balance click now floors to 3 decimal places to avoid exceeding actual balance
- Boost tab: note shown when selected message already holds top spot
- Edit/see-more link moved above payment section in boost tab
- Label "ETH to Add" renamed to "Amount to Pay"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Current message box and tab bar are hidden when isSuccess is true,
  so only the success panel (checkmark + Basescan link) is visible
- Removed the 3s auto-dismiss setTimeout; modal stays open until the
  user manually closes it
- Closing after a successful transaction calls onSuccess() so MarkeeSign
  refreshes its data, same as before

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…repo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Proxy view tracking POST/GET to markee.xyz/api/views
- ModerationProvider with optimistic flag/unflag (Vercel KV + wallet sig)
- ModeratedContent blurs flagged messages; FlagButton for admin wallets
- MarkeeSign fires view tracking on load, displays formatted view count
- MarkeeModal boost entries wrapped with ModeratedContent + FlagButton
- formatViews: 999 → 1.0k → 999.9k → 1.0M → 1.0B (floor at each boundary)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Checks leaderboard API reachability, view tracking API, and moderation
KV connectivity. Returns overall ok/warn/error with per-component detail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Places the Markee message card above the "Your Map of the Funding Trends"
label in the top center of the homepage hero section, matching the
semi-transparent bg-gray-900 style of the search bar. Removes it from
the left sidebar footer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reduce top padding (pt-16→pt-8, md:pt-24→md:pt-12) to close the gap
between the nav and the Markee card. Increase bottom margin on the card
(mb-4→mb-8) to breathe against the "Your Map" label.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 8, 2026

@pglavin2 is attempting to deploy a commit to the Allo Capital Team on Vercel.

A member of the Team first needs to authorize it.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gitcoin-co-30 Ready Ready Preview, Comment Apr 15, 2026 2:54pm

Request Review

cristinalare
cristinalare previously approved these changes Apr 9, 2026
@pglavin2
Copy link
Copy Markdown
Author

Hey @cristinalare - I just pushed a couple fixes for the conflicts that were flagged in the merge. Now awaiting your review.

<>
{leaderboardLoading ? (
<p className="text-xs text-gray-500 font-mono py-2">loading...</p>
) : leaderboardEntries.length === 0 ? (
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message is displayed also when there is an error (i see some 429 Too Many Requests on mainnet.base.org sometimes). Maybe it would be worth handling the isError state from useReadContract to show an error message + integrate a dedicated Base RPC to avoid the rate limiting

Comment thread src/components/MarkeeModal.tsx Outdated
};

const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {
if (e.target !== dialogRef.current || isFormDirty) return;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when the form is dirty (not empty) the backdrop click to close the modal is blocked to prevent accidental data loss. this is great but i would suggest instead that we allow closing the modal but lift the form state in the parent (MarkeeSign) so it's preserved when the modal is reopened. This would also fix the wallet connect flow so that form data doesnt get lost when the markee modal is closed to connect the wallet.

Comment thread src/components/MarkeeModal.tsx Outdated
dialogRef.current?.showModal();
}, []);

// Reopen dialog after RainbowKit connect modal closes
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tries to reopen the dialog after wallet connection which is great, but is not running because the component has already unmounted by the time it should have ran. Fix: move openConnectModal up to MarkeeSign

@cristinalare
Copy link
Copy Markdown
Collaborator

Hey @cristinalare - I just pushed a couple fixes for the conflicts that were flagged in the merge. Now awaiting your review.

tysm Paul! this looks great. just dropped a few comments.

also, i can see a few very small UI/UX related improvements that we can do:

  • Set cursor: pointer to all existing clickable elements/buttons
  • Capitalise ‘loading…’
  • Improve contrast for text that has text-gray-600
  • Make Markee sign/container clickable, not just the message
  • Remove ‘Refreshing in a moment…’ since the modal stays open on the success state. We can replace it with "Your message may take up to a minute to appear". Open to discuss any ideas!

i would be happy to make these changes unless you'd prefer to handle them yourself, just let me know what works best for you! thank you

…rror handling, UX tweaks

- Lift message/name/ethAmount/boostAmount state from MarkeeModal to MarkeeSign so form data
  persists when modal closes and reopens (e.g. during wallet connect flow)
- Fix wallet connect reopen: move openConnectModal to MarkeeSign, use pendingReopenModal flag
  to reopen the dialog after RainbowKit connect modal closes (fixes unmounted component issue)
- Handle isError from useReadContract/useReadContracts on boost tab -- show error message
  instead of hanging loading state (avoids confusion on RPC rate limit errors)
- Add optional NEXT_PUBLIC_BASE_RPC_URL transport to Web3Provider for dedicated Base RPC
- Make whole Markee sign container clickable (cursor-pointer, FlagButton stops propagation)
- Capitalize "Loading..." in boost tab leaderboard loading state
- Replace "Refreshing in a moment..." with "Your message may take up to a minute to appear."
- Improve text contrast: text-gray-600 -> text-gray-500 on owner name, view count, and footer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@pglavin2
Copy link
Copy Markdown
Author

Hi @cristinalare thanks for the comments - I went ahead and pushed a batch of updates based on your suggestions. Take a look, and if there are any other improvements or fixes you see feel free to go for them.

@cristinalare
Copy link
Copy Markdown
Collaborator

Hi @cristinalare thanks for the comments - I went ahead and pushed a batch of updates based on your suggestions. Take a look, and if there are any other improvements or fixes you see feel free to go for them.

thanks a lot Paul, appreciate it. just pushed a few UI changes to improve the design consistency. This is now ready to go live imo @owocki feel free to merge.

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