ContextQR: The QR Code That Becomes a Different App for Every Stadium Moment

A deterministic Next.js system routes fans to the right guidance by zone, time, and accessibility needs, without guessing, hallucinating, or making people download a giant stadium app.

8 min read • View on GitHub • More from ramshaa01

A single QR placard on a stadium column splits into three distinct paths after a scan. One path leads to gate guidance, one to seat guidance, and one to a medical triage screen, showing how one code can resolve into different experiences depending on context. It explains the core idea that routing, not scanning, is the real product.
One QR code, three outcomes. Context decides what the scan becomes.
Key Takeaways

One QR Code, Three Realities

ContextQR is built around a simple but potent idea: the same physical QR code should not behave like the same product everywhere. A scan at the gate, a scan in the stands, and a scan near a medical post should each resolve to the right thing for that moment.

That is why the project feels more like a routing layer than a fan app. It reads the scene, then chooses a path. The user does not need to browse a venue map just to find the one answer they need right now.

The repo frames this as context-aware branching, and that is the right lens. The value is not novelty in the QR code itself. The value is turning a single entry point into a decision system.

Why Stadium Software Should Not Guess

In a stadium, ambiguity is expensive. A fan who needs an accessible route should not get a generic directions page. Someone with symptoms should not be funneled through a broad navigation flow when the right response is triage.

That is why the project avoids LLM-style interpretation and uses deterministic logic instead. The code can decide from known inputs, which makes the behavior testable, repeatable, and safer under pressure.

The important shift is philosophical as much as technical. ContextQR treats accessibility and urgency as first-class routing constraints, not as post-processing or cosmetic UI states.

The Decision Engine Is the Product

The heart of the repo lives in its decision logic. The engine maps time into match phases, checks zone-specific rules, and folds in user profile flags before returning a response. That is what makes a scan feel smart without making the system opaque.

A scan does not pick a screen at random. It moves through a rule chain that resolves the right response from known inputs.

// lib/decisionEngine.js
function detectTimeContext(now = new Date()) {
  const hour = now.getHours();
  if (hour < 14) return 'pre-match';
  if (hour < 17) return 'live';
  if (hour < 18) return 'half-time';
  return 'post-match';
}

export function gateDecision({ zoneId, userProfile, now }) {
  const matchPhase = detectTimeContext(now);
  const response = {
    matchPhase,
    zoneId,
    guidance: getZoneGuidance(zoneId, matchPhase)
  };

  if (userProfile?.isWheelchairUser) {
    response.accessibleRoute = getAccessibleRoute(zoneId);
  }

  return response;
}
A close-up mechanical switchboard routes three labeled inputs, Zone, Match Phase, and Accessibility Profile, into a central core. One lever is locked into place, while output rails lead to accessible route, medical triage, and zone guidance, illustrating deterministic branching instead of probabilistic guesswork.
The intelligence here is rule-based. Inputs move through a switchboard, not a black box.

The repo also makes the time model explicit. A simple detectTimeContext function maps the day into phases like pre-match, live, half-time, and post-match. That means the system can alter guidance when the venue itself changes state, which is exactly what situational software should do.

This is the part that matters most: the product stays legible because the logic is visible. You can test it. You can reason about it. You can trust it in a way you cannot trust a fuzzy interpretation layer.

Accessibility Is Wired Into the Branches

ContextQR does not bolt accessibility onto the edge of the experience. It routes around it. A wheelchair user does not get the same output with larger type. They get a different path, because step-free navigation is a routing requirement.

That design shows up in the repo’s accessible route handling and in its motion system. The custom motion hook respects reduced-motion preferences, and the stadium mini map uses high-contrast cues and a text fallback for screen readers.

That is the right mental model for inclusive product design. Accessibility is not decoration on top of a flow. It changes the flow itself.

// app/scan/medical-post/page.js
if (triageResult.severity === 'urgent') {
  setAnnouncement('Medic notified');
  setDispatchState('active');
}

return (
  <div aria-live="assertive">
    {triageResult.message}
  </div>
);

The medical path makes this especially clear. When the triage engine flags urgency, the UI shifts immediately into an assertive state and surfaces a dispatched response. The interface is designed to reduce hesitation, not invite it.

DimensionContextQRTraditional stadium app
Entry frictionScan and routeDownload first, then navigate
Personalization methodDeterministic branching from zone, time, and profileBroad user journeys and menu depth
Accessibility handlingStep-free routing is a branch conditionOften a setting or a separate layer
Emergency flowUrgent triage can trigger an immediate dispatch stateUsually buried inside general support flows
Reliability modelPredictable rules and testable outputsHeavier feature surface with more ambiguity
Best use caseRight-now guidance in a specific venue momentGeneral fan engagement and account-based features

Medical Triage Without Panic

The medical-post flow is where the repo stops feeling like a convenience layer and starts feeling like infrastructure. The API evaluates symptoms, classifies severity, and returns a response that the UI can surface immediately.

That matters because urgency is an interface problem as much as a backend problem. If the screen hesitates, hedges, or buries the result, the whole point is lost.

ContextQR keeps the interaction narrow. It does not ask a distressed user to do more than the moment requires. It just gets them to the next correct action.

What It Replaces

The conventional stadium app tries to be everything at once. ContextQR does the opposite. It is narrow, situational, and willing to change its behavior with the moment rather than with the account.

That tradeoff is the story. A QR code at the venue entrance can become a gate assistant, a seat navigator, or a medical interface without asking anyone to install a heavier product they may never open again.

For operators, that means less app churn and more relevant guidance. For fans, it means less searching and less waiting.

Why This Pattern Matters Beyond Stadiums

The bigger idea is portable. Airports, campuses, transit hubs, and hospitals all have moments where location and urgency change the right answer. A deterministic QR router can be a good pattern anywhere the environment matters more than the profile.

That is the open-source value of ContextQR. It is not just a venue demo. It is a way to think about physical spaces as systems that should route people, not just inform them.

The strongest projects do that. They take a familiar object and make it behave like an interface for the real world.