Skip to content

feat(sponsors): curated sponsor ad zones, tracking, and funding model#705

Merged
smmariquit merged 9 commits into
stagingfrom
feat/sponsor-ads
Jul 21, 2026
Merged

feat(sponsors): curated sponsor ad zones, tracking, and funding model#705
smmariquit merged 9 commits into
stagingfrom
feat/sponsor-ads

Conversation

@smmariquit

@smmariquit smmariquit commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Who are you?

  • Maintainer / agent: full QA below plus issue hygiene for linked specs.

Summary

Adds the curated sponsor ad system funding the project: four ad zones (status bar badge, dismissable side panel banner, /sponsors showcase page, static-page strip), first-party impression/click tracking (/api/sponsor-event → new sponsor_impressions table, migration 0038), sponsor config in public/sponsors.json (sample sponsor ships inactive, so no ads render until a real sponsor is activated), plus funding-model and ad-policy docs, GitHub FUNDING.yml, and sponsored-content sections on Privacy/Terms.

No ad networks, no third-party scripts, no cookies: images are self-hosted and SW-precached; impressions are sessionStorage-deduped and bot-filtered server-side; every placement is labeled "Sponsored". /sponsors is added to the workbox navigateFallbackDenylist (same trap as /planner) so returning PWA users don't get the map shell.

Developer checklist

  • bun run test (362 pass; new src/lib/sponsors.test.ts)
  • bun run lint (Biome, clean)
  • Heavy CI: run/e2e label set (new e2e/smoke/sponsors-page.spec.ts)

QA Summary (code changes)

Automated:

  • Unit: bun run test — 362 pass
  • Components: bun run test:components — 130 pass (new SponsorBanner.component.test.ts: render, inactive-config empty state, dismiss persistence)
  • Integration: 3 new POST /api/sponsor-event tests in integration/http/public.integration.test.ts (valid beacon, missing fields → 400, bot UA dropped)
  • E2E: e2e/smoke/sponsors-page.spec.ts — 6/6 pass locally (desktop + mobile)
  • Full lint passed (local)
  • Build passed (local, with DATABASE_URL)

If auth, routing, or schema changed:

  • Migration applied on Supabase0038_sponsor_impressions.sql applied and verified (sponsor_impressions exists). Note: schema_migrations ledger was freshly baselined during this session and already records 0038, so the release workflow will not re-run it — the table is live. Route degrades gracefully (200, no insert) if the table is ever missing.

If map chrome, editor, or side panel changed:

  • Verified at 320px and 1280px headless with sample sponsor temporarily activated: status bar badge renders without overflow, side panel banner renders on entity detail and dismisses for the session, no horizontal overflow, no page errors. Test beacon rows deleted from the DB afterwards.

Manual browser check with a real activated sponsor on staging preview is the remaining gap (sample sponsor is inactive by design, so staging shows no ads — flip active: true in public/sponsors.json on a preview to eyeball placements).

Notes for reviewers

  • sponsor_impressions is server-only — deliberately not added to PGlite SYNCED_TABLES, so no pglite-schema regen needed.
  • E2E reset registers 0038 + truncates sponsor_impressions.
  • Prerendered sponsor surfaces (/sponsors, footer strip) evaluate the active window at build time; a sponsor whose start date passes after the latest deploy appears on the next build (documented in docs/ad-policy.md).

Note

Medium Risk
Touches payments (PayMongo secret), new DB migration for sponsor analytics, and visible map/side-panel UI; sponsor route degrades if migration is missing but donations require correct env configuration.

Overview
Introduces a curated sponsor system driven by public/sponsors.json (sample sponsor ships inactive): status-bar Gold badge, dismissable side-panel banner on entity detail views, static-page strip, /sponsors showcase, and up to three sponsored map pins on real places entities with session-deduped impressions/clicks via POST /api/sponsor-event into new sponsor_impressions (migration 0038). PWA precache/denylist covers /sponsors and /donate.

/donate is rebuilt around POST /api/donate (PayMongo QR Ph checkout, optional PAYMONGO_SECRET_KEY); GCash details are removed from campus config. Funding/ad-policy docs, README sponsors section, FUNDING.yml, and Privacy/Terms sponsor copy ship with the change.

Contributor ledger gains editor_published rows when editors publish directly (sessionPublishingActor), GET /api/contributions/mine, Account settings “My contributions”, and leaderboard filtering to active users who opted into public credits.

Minor: AMIS normalize bracket cleanup, planner E2E selector fixes, transit integration cleanup.

Reviewed by Cursor Bugbot for commit 1b821cc. Bugbot is set up for automated code reviews on this repo. Configure here.

Fund the project with curated campus-relevant sponsors (no ad networks,
no third-party scripts, no cookies):

- Zone A: status bar "Supported by" badge (gold sponsor)
- Zone B: dismissable side panel banner (gold+silver, daily rotation)
- Zone C: prerendered /sponsors showcase page
- Zone D: sponsor strip above SiteFooter on static pages
- First-party impression/click beacons via /api/sponsor-event into new
  sponsor_impressions table (0038); session-deduped, bot-filtered,
  degrades gracefully when the table is missing
- Sponsor config in public/sponsors.json; images self-hosted and
  SW-precached; /sponsors added to workbox denylist so returning
  PWA users don't get the map shell
- Funding model (40/30/30 split, tier pricing) and ad policy docs;
  GitHub FUNDING.yml; privacy/terms sponsored-content sections
Copilot AI review requested due to automatic review settings July 16, 2026 20:23
@smmariquit smmariquit added the run/e2e Re-run integration + blocking/advisory E2E + bundle (~30 min) label Jul 16, 2026
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
saan-ang-room Ready Ready Preview, Comment Jul 21, 2026 6:47am

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_f2892958-9a3f-4a24-b3cd-303d6872aabf)

staging HEAD fails the verify job's biome check on these two files;
mechanical fixes only (import wrapping, bracket-to-dot access).
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_eb2a1f6a-8b99-48e1-8f8d-dc39fd180c40)

@smmariquit

Copy link
Copy Markdown
Collaborator Author

CI status: verify, migrations, CodeQL, bundle all green on 48f058d.

The gated e2e / e2e job failed on the first commit with Preview failed to starterror: preload not found "integration/preload.ts" — this is pre-existing staging breakage, not from this PR: the E2E staging run on the staging branch itself (2026-07-16, before this PR) fails identically. Locally against a live server: the new sponsors e2e spec passes 6/6 (desktop+mobile), integration beacon tests verified end-to-end (rows inserted into sponsor_impressions, bots dropped, then cleaned up). Re-add run/e2e once the staging E2E pipeline is fixed if a green gated run is wanted before merge.

@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_310f4bfd-385d-435b-ba52-d7310b776cd7)

- Fictional demo sponsor (active, gold) with generated logo/banner art so
  every zone can be eyeballed on preview; deactivate before prod release
- Side panel drawer is row flex: banner rendered as a side column; wrap
  so the full-width banner lands below the entity content
- Banner art already carries name/tagline: keep text for screen readers
  only, avoiding visual duplication
- Fix swallowed spaces around inline links on /sponsors (Astro trims
  text-node whitespace at element boundaries across newlines)
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_a3929817-7059-4ac3-8ee8-75184f7456d7)

@smmariquit

Copy link
Copy Markdown
Collaborator Author

f1d7b5b adds Kape Kalabaw, a fictional demo sponsor (active, gold tier, generated art) so all four zones can be eyeballed on the preview deploy: status bar badge, side panel banner, /sponsors hero card, footer strip on legal/changelog pages.

⚠️ Deactivate before releasing to prod — flip active: false on kape-kalabaw-demo in public/sponsors.json (or delete the entry) in the release batch, or production shows a fake coffee shop ad.

Also in this commit: side panel drawer flex-wrap fix (banner was rendering as a side column next to entity content), banner text now screen-reader-only when banner art is present, and whitespace fixes around inline links on /sponsors.

Gold/Silver sponsors with a real place entity get their existing map pin
highlighted: static gold ring, always-visible "Sponsored" label, max 3
at once with gold priority. Anchored via sponsors.json placeName ->
places.name so pins can never point at fabricated locations; clicking
opens the normal place detail panel. map_pin impression/click beacons
reuse the session-deduped tracker. Ad policy amended: pins are the one
map-surface exception, everything else on the canvas stays ad-free.
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_0a944782-b9dc-4222-9ab4-1ca4275e1672)

/donate page (preset + custom amounts, optional message) posts to
/api/donate, which creates a PayMongo Checkout Session (QR Ph, PHP
10-50k, kape.stimmie.dev pattern) and redirects to the hosted checkout;
no payment data touches the server. PAYMONGO_SECRET_KEY is an optional
astro:env secret so the route degrades to 503 when unset. /donate added
to SW precache + navigate denylist, footer/README/FUNDING links, and
the funding-model doc.
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_3ae4fca9-b5f1-4738-8048-779f2af587a5)

…butions"

Editor-published edits now append a ledger row (source: editor_published)
alongside proposal approvals, and signed-in editors can see their own
contribution history via GET /api/contributions/mine and a new section
in Account Settings. Leaderboard queries now filter to active,
credit-opted-in contributors.
@cursor

cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_3576b965-c389-4bb0-9e53-3eb9915bbd74)

@cursor

cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_cb8c4f41-1ffd-41c0-b21e-fc5f93f0f66a)

# Conflicts:
#	.github/FUNDING.yml
#	README.md
#	src/lib/amis/normalize-class.ts
#	src/pages/donate.astro
@smmariquit
smmariquit merged commit f3710be into staging Jul 21, 2026
5 of 6 checks passed
@smmariquit
smmariquit deleted the feat/sponsor-ads branch July 21, 2026 06:47
@cursor

cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_ea5b158b-d137-4d21-b8fa-346bc11edb66)

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.3.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released run/e2e Re-run integration + blocking/advisory E2E + bundle (~30 min)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants