Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A single-page, dependency-light web calendar showing competitive Pokémon events (TCG, VGC, GO, prereleases, community) from six public Google Calendars. Plain HTML/CSS/JS — no framework, no build step. Deployed on GitHub Pages and embedded into carrd.co pages as an auto-sizing iframe widget.檢視完整 README ↗
A single-page, dependency-light web calendar showing competitive Pokémon events (TCG, VGC, GO, prereleases, community) from six public Google Calendars. Plain HTML/CSS/JS — no framework, no build step. Deployed on GitHub Pages and embedded into carrd.co pages as an auto-sizing iframe widget.
Live: https://pizzacatz.github.io/pokemon-calendar-webapp/
pokedata.ovh ICS feeds
│ (Google Apps Script sync, daily — lives in the private
│ pizzacatz/pokemon-calendar repo; copies in *.gs here)
▼
6 public Google Calendars ──Google Calendar API──▶ this app (FullCalendar 6.1.21)
│
▼
GitHub Pages ─▶ carrd.co iframes
| File | Role |
|---|---|
index.html | page shell, CDN script tags, filter panel + modal markup |
app.js | config, calendar setup, filtering, custom week view, modals, embed plumbing |
styles.css | dark theme (#1A1A1A / #1F1F1F / gold #FFD180), mobile rules |
pokemon_calendar_sync*.gs | reference copies of the Apps Script pipeline (not used by the app) |
pokemon-events-calendar-PRD.md | original spec + addendum of post-launch changes |
app.js)GOOGLE_CALENDAR_API_KEY — public by design; must stay restricted in
Google Cloud Console to the Calendar API + HTTP referrers
(pizzacatz.github.io/*, localhost:8000/*).DISPLAY_TIME_ZONE — fixed America/New_York; times are labeled "ET".CALENDARS — one entry per category (id, chip label, color, Google Calendar
ID). Add/remove categories by editing only this list.Every calendar must be public with "See all event details" — the free/busy-only sharing level strips titles/locations and events render as "(untitled)".
Important: carrd "pages" are sections of ONE HTML document, so every embed
on the site coexists in the same DOM. Never target the iframe by id (ids
collide and all height messages land on the first iframe — some embeds stay
clipped, others inflate with empty space). Match by e.source instead.
Each embed is just an iframe (vary view=/cats= per page):
<iframe
src="https://pizzacatz.github.io/pokemon-calendar-webapp/?embed=1"
style="width:100%; height:900px; border:0;"
scrolling="no"
allow="clipboard-write"
title="Pokémon Events Calendar"></iframe>
Plus this listener once anywhere on the site (per-embed duplicates are harmless — it routes each message to the iframe that sent it):
<script>
window.addEventListener('message', function (e) {
if (e.origin !== 'https://pizzacatz.github.io') return;
if (!e.data || e.data.type !== 'pokecal:height') return;
document.querySelectorAll('iframe').forEach(function (f) {
if (f.contentWindow === e.source) f.style.height = e.data.height + 'px';
});
});
</script>
The app posts its content height (pokecal:height) whenever it changes —
view switches, data loads, modals opening/closing — so each iframe grows AND
shrinks to fit and the page never double-scrolls. The 900px is only a
pre-load fallback.
| Param | Values | Effect |
|---|---|---|
embed=1 | — | bare widget: hides the app's own header/footer |
view= | month, week, list (alias agenda) | initial view; default month |
cats= | comma list of tcg-cups, tcg-challenges, vgc, go, prerelease(s), community | pre-activates those filter chips at load (visitors can still change them) |
Examples for dedicated pages:
TCG page (month): ?embed=1&view=month&cats=tcg-cups,tcg-challenges
VG/GO page (agenda): ?embed=1&view=agenda&cats=vgc,go
Prerelease page (agenda): ?embed=1&view=agenda&cats=prereleases
Everything (default): ?embed=1
Any number of widgets can coexist — the e.source-matching listener above
routes each height message to its own iframe automatically.
docs/VOCABULARY.md → "UI names".<…> so Discord shows no preview). The official link is the first non-image
URL in the description.
Uses navigator.clipboard with an execCommand('copy') fallback, so it
works inside cross-origin iframes even without allow="clipboard-write"., US, , City/US tail.Visitors submit events through a Google Form; the owner approves them in the
linked response sheet; an Apps Script (community_event_form.gs) publishes
approved rows to the Community Events calendar, which the widget already
displays. Nothing goes live without approval.
Form questions — titles must match community_event_form.gs's Q map exactly:
| Question title | Type | Required |
|---|---|---|
Game | Multiple choice (TCG / VGC / GO / Other) | no (becomes the title prefix) |
Event name | Short answer | yes |
Event Date | Date | yes |
Start Time | Time | no (blank = all-day event) |
End Time | Time | no (blank = start + 2h) |
Venue name | Short answer | yes (goes in the title: "… @ VENUE") |
Venue Address | Short answer | yes |
Description | Paragraph | no |
Event link | Short answer | no |
Image url | Short answer | no (renders in the event popup) |
Published titles follow the site convention GAME Event name @ VENUE, and
the location field is Venue name, Venue Address.
Setup: create the form → link responses to a new spreadsheet → in that
spreadsheet Extensions → Apps Script → paste community_event_form.gs →
set the project time zone to America/New_York (Project Settings) → run
setup() once and authorize. Recommended form settings: collect email
addresses (verified) to deter spam.
Moderation: each submission emails NOTIFY_EMAIL and sits at
PENDING. In the sheet, set Status to APPROVED to publish (script fills
in the Event ID and flips it to PUBLISHED), REJECTED to decline, or
REMOVE on a published row to delete the event. The sheet's
"Community events → Process all rows now" menu re-sweeps everything if a
trigger is ever missed.
python3 -m http.server 8000 # serve from the repo root
# http://localhost:8000 (localhost:8000 must be in the API key's referrer list)
Deploy = git push — the "Deploy to GitHub Pages" Actions workflow
(.github/workflows/pages.yml) publishes the repo as-is, typically in under
a minute. Check on a deploy with gh run list. (The legacy Jekyll Pages
build was abandoned in July 2026 after repeated 20-minute stalls and opaque
"Page build failed" errors.)
timeZone and no timezone plugin,
FullCalendar's event.start/end are Dates whose UTC fields hold the
Eastern wall time. Format with timeZone:'UTC' and label "ET" manually;
formatting with America/New_York double-shifts.body.scrollHeight misses the last element's collapsed
bottom margin and floors fractional heights — report +16px or the bottom
border clips. Modals are position:fixed (invisible to body height), so
they're measured separately.fixed + centered = middle of the whole
grown iframe, not the visitor's screen. The app anchors modal boxes to the
last click's Y position when embedded.isConnected.MouseEvents can lose coordinates in
iframes; only trusted input proves click-anchoring.