尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A live carbon-accounting dashboard for Kimball Union Academy (Plainfield NH).
Tracks Scopes 1/2/3 + on-campus forest sequestration. Public emissions counters,
methodology references, peer comparison, learn modules, an admin portal for
data entry, and an AI-driven institutional planning agent.
All active development happens inside src/ (Vite + React 18 + Vitest).
The root /package.json is stale CRA scaffolding — its only durable role
is providing "type": "module" so the api/*.js Vercel functions parse
as ESM.
This project deploys to Vercel as a Vite app + serverless api/* functions.檢視完整 README ↗A live carbon-accounting dashboard for Kimball Union Academy (Plainfield NH). Tracks Scopes 1/2/3 + on-campus forest sequestration. Public emissions counters, methodology references, peer comparison, learn modules, an admin portal for data entry, and an AI-driven institutional planning agent.
All active development happens inside src/ (Vite + React 18 + Vitest).
cd src
npm install
npm run dev # Vite dev server on http://localhost:5173
npm run build # production build → src/dist/
npm test # vitest (362 tests across 15 files)
The root /package.json is stale CRA scaffolding — its only durable role
is providing "type": "module" so the api/*.js Vercel functions parse
as ESM.
This project deploys to Vercel as a Vite app + serverless api/* functions.
The admin portal works out-of-the-box on a fresh deploy with no env-var
setup — login accepts the password KUA2026 by default. To harden,
override either or both with stronger values via the Vercel dashboard:
| Var | Purpose | Default | How to override |
|---|---|---|---|
ADMIN_PASSWORD | Password admins type into the gate | KUA2026 (public fallback) | vercel env add ADMIN_PASSWORD production |
ADMIN_TOKEN_SECRET | HMAC-SHA256 secret used to sign admin session tokens. Must be ≥ 32 chars. | A baked-in 64-char string (public fallback) | vercel env add ADMIN_TOKEN_SECRET production then paste openssl rand -hex 32 |
The fallbacks are intentional: KUA's threat model is "keep casual visitors
out of the admin portal," not "keep determined attackers out." Anyone reading
the public source can mint forged tokens with the default secret — set
ADMIN_TOKEN_SECRET in Vercel to close that gap when you care.
| Var | Purpose |
|---|---|
ANTHROPIC_API_KEY | Enables LLM-driven /api/admin/estimate-action + /api/admin/plan. When unset, both endpoints fall back to a rule-based response so the admin UI still works. |
CRON_SECRET | Required for /api/cron/* routes. Vercel cron sends this in the Authorization header. |
AUTH_GOOGLE_AUDIENCE, AUTH_ALLOWED_DOMAINS | Required for /api/auth/session Google SSO (used by chatbot persistence + teacher portal). |
AUTH_DEV_MODE=1 | Local dev only — accepts mock session tokens without Google SSO. Never set in production. |
Either through the Vercel dashboard (Project Settings → Environment Variables) or via the Vercel CLI:
npm i -g vercel # if not installed
vercel link # one-time, links this local dir to the Vercel project
vercel env add ADMIN_PASSWORD production
vercel env add ADMIN_TOKEN_SECRET production
vercel deploy --prod # redeploy so the new env takes effect
The repo is wired for Vercel auto-deploy on push to main. Local commits
won't go live until they're pushed:
git push origin main
Canonical scope numbers live in src/data/scopeTotals.js. Today's
values match the bottom-up multi-method cross-check centrals from
src/data/geographicEstimates.js: Scope 1 = 1,350 mt, Scope 2 = 390 mt,
Scope 3 = 2,635 mt, sinks = 2,650 mt → gross 4,375 / net 1,725 / per-student 5.0.
Live measured-data hooks (src/hooks/useMeasured{Scope1,Scope3,Sinks,Renewables}.js
useMeasuredScopeTotals.js) upgrade the headline numbers from
"estimated" to "measured" the moment admins enter rows into the corresponding
Supabase tables. Pages already wired: Scope1, Scope2, Scope3, Sinks, Sinks2,
Renewables, Renewables2, Drawdown, Executive, Goals, AnnualReport,
NetEstimate (homepage hero), AdminHome, AdminMethodology, AdminDataQuality,
Buildings, Hotspots. Each component flips estimated → measured independently.
A module-level promise cache in src/hooks/measuredCache.js dedupes
Supabase round-trips across pages; admin writes invalidate it via
logAdminWrite().Admin auth is server-checked: /api/admin/login validates against
ADMIN_PASSWORD and returns an HMAC-signed session token. Client uses
adminFetch() from src/utils/adminFetch.js to attach Authorization: Bearer <token> automatically; 401 responses clear the local token and
emit a kua-admin-auth-expired event so the AdminLayout can re-prompt
for login.
Supabase tables that drive the live dashboard (17 canonical):
fuel_bills, scope1_heating_oil, scope1_propane,
scope1_fleet, scope1_refrigerantsday_students, us_boarding_students, international_students,
study_abroad, faculty_travel, waste, purchased_goods, commutingforest_stand_actualsrenewables_solar, renewables_geothermal, renewables_windadmin_audit_log (every admin write)Read/written through the publishable anon key client in
src/supabaseClient.js. The bearer-token gate at IS the
auth boundary — there's no service-role key in the client. RLS policies +
schemas live in .
For deeper context (data flow, conventions, where to make which kind of edit), see CLAUDE.md.
/api/admin/loginsupabase/migrations/*.sqlData quality dashboard at /admin/data-quality shows per-table row
counts, last-entry timestamps, and cadence-aware freshness pills (fresh /
aging / stale / empty / irregular). AdminHome surfaces the same as a
top-of-page alert when any table is stale.
Audit log at /admin/audit-log lists every admin write with date
filtering, pagination, refresh button, CSV export of the visible page, and
"Export all filtered" with paged progress (50K-row ceiling).