Skip to main content
Planet Positive Sport — hero image
Web App Live 2026

Planet Positive Sport

A multi-tenant sustainability assessment and CO₂ reporting platform for international sports events

Tech Stack

Fastify TypeScript HTMX fluent-html Tailwind CSS Prisma PostgreSQL Redis S3 Puppeteer

Overview

Planet Positive Sport (PPS) is a multi-tenant sustainability assessment and CO₂ reporting platform for major sporting events, built for an international sports federation. A local organizing committee runs a guided, multi-category assessment for an event, pulls footprint data straight from its suppliers, sets objectives and action plans, and produces a CO₂-calculated report that an independent sustainability expert reviews before sign-off — all in one server-rendered tool.

What looks like a single questionnaire is, underneath, a full platform: five distinct user roles, a per-tenant federation model with white-label branding, a no-code questionnaire builder with a safe deploy engine, an emission-factors model, an account-free supplier data pipeline, a complete expert-review loop, and a privacy-respecting analytics suite. The work previously scattered across spreadsheets, email threads, and manual carbon math now lives in one place, designed for overwhelmed, non-technical organizers: clean, familiar, and low on cognitive load.

Planet Positive Sport screenshot

Who it's for

  • Local organizing committees (LOC) — the primary users, who create and run an event's sustainability assessment, manage venues and suppliers, and invite collaborators
  • Federation administrators — validate organizations and users, approve incoming supplier data, invite and assign experts, manage events, and oversee every assessment from one operational dashboard
  • External suppliers — hotels, caterers, venues, mobility and energy partners who fill specialized, pre-populated forms via an email link, with no account required
  • Sustainability experts — invited, per-event reviewers who read a submitted assessment read-only and leave structured feedback before final sign-off
  • Supplier accounts — a lightweight role for partners who manage data forms across multiple events
Planet Positive Sport screenshot

The Challenge

Sustainability reporting for a major sporting event is a coordination problem before it's an environmental one. The footprint data lives with dozens of third parties — the venue, the hotels, the caterer, the freight and mobility providers — and the organizer has to chase all of it, normalize it, run the carbon calculations by hand, and turn the result into something credible. Most organizing committees are volunteers doing this around a full-time job, with no sustainability background and no tooling.

The hard part isn't any single calculation. It's making a multi-party, multi-category, multi-role assessment feel manageable: knowing what to ask, who to ask, what "good" looks like, and where you stand — without drowning the organizer in a spreadsheet, and without losing the auditability a federation needs to stand behind the result.

Planet Positive Sport screenshot

The Solution

PPS turns the assessment into a guided path with a state machine underneath. The LOC picks an official event from a curated list (auto-filling discipline, type, participants, dates, and country), adds its venues with country-scoped city pickers, then works category by category: set objectives and an action plan, answer a mix of primary and secondary questions with comments and document uploads, and watch a single progress engine keep the percentage in sync everywhere it appears.

Suppliers never need an account. The organizer invites each one by email, and the platform sends a category-specific form pre-populated with the event's details and any answers already saved, ready to resume. Submitted data goes through admin review — approve, edit-and-approve, or reject-with-feedback — and approved figures flow into a read-only Calculator category, where a year-aware emission-factors model turns numeric inputs into CO₂e, rolled up per venue where it matters.

When every category is complete, the owner submits the assessment for review. An assigned expert opens the same questionnaire in a locked, read-only mode and layers in three kinds of feedback: non-blocking recommendations, blocking action-needed comments that send the assessment back, and per-category sign-offs. Final confirmation is gated on every category being signed off with zero unresolved blocking comments. Once it clears, the event is marked completed and a branded, downloadable PDF report is generated.

Roles & workspaces

PPS is genuinely multi-role: five user roles (administrator, organizer, collaborator, expert, supplier) each get their own dashboard, permissions, and access rules. Authorization is layered — authenticated, then email-verified, then approved — with finer per-event roles resolved on top (owner, collaborator, assigned expert, admin) so the same screens can serve different audiences safely.

Crucially, the LOC overview, category page, and questionnaire are built once and reused across all three review audiences via an audience flag. The same component tree renders as an editable organizer surface, a read-only expert review with inline comments, or an admin view — no duplicated UI, one source of truth for layout and copy.

The assessment workflow

A finite event-status state machine — not started, in progress, in review, fix needed, completed — drives every contextual call-to-action, lock, and badge across the dashboard, the event overview, the questionnaire, and the expert and admin surfaces. The "Submit" gate is computed from the exact same completeness predicate the server runs on write, deliberately decoupled from the rounded display percentage, so the UI can never enable a button the backend would reject. Once an assessment goes into review, every write path re-checks status server-side before persisting, guarding against stale or tampered clients even though the UI already hides the affordance.

The questionnaire itself is rich: multiple question types (single-choice, multi-select, numeric, free text, and a matrix table), inline autosave on change, per-question comments and file attachments, answered/unanswered/has-expert-comment filters, and per-venue iteration that multiplies question slots and progress by the number of venues. Alongside the questions sit an objectives-and-action-plan editor — objectives with achievement status and evidence, action items linked to a primary objective plus additional ones, and an optional per-category quote — with the card the user is editing kept open across every HTMX swap.

Scale & complexity

  • ~325 TypeScript files, ~59,000 lines across 20+ feature modules
  • 229 route definitions across 38 typed route groups, 40 Prisma models, and 16 enums underpinning the domain
  • Five user roles, a four-state account lifecycle, a five-state event state machine, supplier and expert sub-lifecycles, and per-event role resolution layered on top
  • Around a dozen assessment categories, each split into scored assessment and footprint data-capture sections, spanning five question types
  • Five fully-shipped UI locales (English, Japanese, Portuguese, Thai, Chinese) across 18 translation namespaces, with CLDR-correct pluralization
  • Multi-tenant federation architecture with per-tenant white-label branding propagated into every layout and email

Key Features

  • Guided multi-category assessment — around a dozen sustainability categories, each with scored questions and footprint data-capture sections, objectives and action plans, document uploads, and per-venue handling
  • No-code questionnaire builder — admins create, duplicate, import, and edit hierarchical questionnaires (category → subcategory → question → choices/matrix) through an HTMX tree editor with live validation, version history, and a safe, non-destructive deploy that diffs against existing answers before applying changes
  • Account-free supplier data collection — suppliers fill pre-populated, localized forms via a single email link; organizers and admins can invite, resend, edit-and-approve, or reject-with-feedback, and approved data flows into the carbon totals
  • CO₂ Calculator — a read-only category populated from admin-approved supplier submissions, backed by a maintained, year-aware emission-factors model with per-venue rollups
  • Complete expert-review loop — per-event invitations with accept/reject, a read-only review of the organizer's answers, three feedback types (recommendations, blocking action-needed comments, category sign-offs), and a gated final confirmation
  • Action-plan scoring — a permission-gated screen for experts and admins to score organizers' action items on a fixed scale, under a hard per-event cap enforced with concurrency-safe locking
  • Multi-role workspaces — tailored dashboards and permissions for organizer, admin, expert, collaborator, and supplier, with per-tenant data isolation
  • Federation administration — create and brand tenants (logos, colors, partners, custom domains), manage users, organizations, experts, events, and reference data from one panel
  • Collaboration — invite collaborators per event by email with owner-only submission and deletion, delivery-failure feedback, and one-click resend
  • Lifecycle notifications & email — branded, per-recipient localized transactional emails across the full event lifecycle, with click-tracked, role-aware redirect links
  • Reports — on-the-fly category PDFs and a reviewed, full-event PDF report with CO₂ calculations and federation branding
  • Product analytics — a privacy-respecting, fully server-side suite with an AARRR funnel, cohort retention, a one-metric-that-matters trend, top pages, and acquisition attribution
  • Soft-delete & recovery — projects and supplier records are recoverable before permanent deletion

Technical highlights

  • Server-rendered, near-zero client JS — Fastify v5 + TypeScript rendered with fluent-html (our type-safe HTML builder) and updated through HTMX morphing swaps, so a data-heavy, multi-step, multi-role app stays fast without a SPA
  • Type-safe from database to HTML — Prisma generates types from the schema, fluent-html enforces valid markup with fluent Tailwind styling, type-safe route and DOM-target definitions drive HTMX, and JSON Schema validates every input
  • Multi-tenant isolation by construction — a Prisma query extension auto-injects the tenant id into reads and writes as a single defensive layer, complemented by explicit per-handler scoping and a branded "resolved federation" type that a layout can't render until image keys are resolved
  • Single source-of-truth progress & scoring — one engine computes category completeness, per-category 0–5 scores (weighted across primary and secondary questions and normalized to a comparable scale), and the overall roll-up, reused identically by the dashboard, questionnaire, PDF reports, and admin views, with agreement tests guarding against drift
  • Safe questionnaire deploy engine — a transactional, natural-key-based upsert that preserves existing answer and action-plan references through structural edits, with a pre-flight drift report that surfaces exactly what would be deleted or orphaned before an operator can confirm a destructive change
  • Defense-in-depth authorization — composable Fastify preHandler guards (authenticated → verified → approved, plus role, permission, and per-event access checks), Redis-cached user and permission lookups with database fallback, and server-side re-checks on every locked-assessment write path
  • Constant-memory file pipeline — multipart uploads stream straight to S3-compatible storage through a custom byte counter that aborts the instant a per-context size cap is crossed, with authorization run before any bytes stream and short-lived signed URLs for download
  • From-scratch i18n — a namespaced translation engine with {{param}} interpolation, CLDR-correct pluralization via Intl.PluralRules, and cached date/number/currency formatters, delivered through fluent-html scoped context rather than prop drilling
  • Server-rendered PDF reports — a single-round-trip Prisma query feeds pure, test-exposed transforms (scoring, per-venue expansion, contributor filtering) into a headless-browser HTML-to-PDF step, with local logos inlined as data URLs for reliable rendering
  • Privacy-respecting analytics — fully server-side page-view and session tracking written fire-and-forget so it never blocks request latency, with batched queries powering cohort retention and funnel reporting
  • Hardened HTTP surface — Helmet CSP, rate limiting on sensitive endpoints, typed environment validation that fails fast on misconfiguration, request-ID propagation, and a no-JSON SSR error and 404 handler