Skip to content

Releases: jchette/CourtPin

v2.0.0 - Event access support

20 Mar 01:34
375ef65

Choose a tag to compare

What's new in v2.0.0

🎉 Major feature — CourtReserve event access

Members registered for events now receive door access automatically, just like court reservations. Three access modes are available via the new EVENT_ACCESS_MODE environment variable.


Access modes

pin_individual (default)
Each registrant receives their own unique UniFi visitor record and PIN.
Works identically to court reservations.

pin_shared
One UniFi visitor and PIN is created for the event. All registrants receive the same PIN. New registrants who sign up after the initial notification always receive the PIN on the next cycle.

unlock
Door(s) in UNIFI_RESOURCES are unlocked for the full event window and automatically relock when the event ends. No PINs generated.
Set EVENT_UNLOCK_NOTIFY=true to send registrants a "facility open" notification. New registrants are notified on the next cycle.


Additional improvements

  • Late registrants and new sign-ups always receive notifications - per-registrant delivery is tracked independently of visitor creation
  • Events processed until end time so registrants who sign up while an event is in progress still receive access
  • Admin portal cards show an Event, Event (shared PIN), or Event (door unlock) badge to distinguish from reservations
  • Detail field label shows Event instead of Court on event cards
  • Email label correctly shows Event: instead of Court: for events

New environment variables

EVENT_ACCESS_MODE=pin_individual
EVENT_ACCESS_BUFFER_MINUTES=30
EVENT_UNLOCK_NOTIFY=false

Add these to Railway → Variables → Raw Editor.

New CourtReserve API role required

Enable EventRegistrationReport → Read on your API key: CourtReserve Admin → Settings → API Access

Files changed

  • index.js
  • env.example
  • docs/configuration.md

How to update

Replace all three files in your GitHub repo — Railway redeploys automatically.

Verified

✅ pin_individual — confirmed working in production
✅ pin_shared — confirmed working in production including late registrants
✅ unlock — confirmed working in production

v1.1.0 - Configurable PIN mode

17 Mar 02:10
4269dab

Choose a tag to compare

What's new in v1.1.0

🔑 New feature — configurable PIN mode

A new PIN_MODE environment variable controls how door PINs are generated:

Mode Behavior
random New random PIN generated each reservation (default, existing behavior)
static Member's CourtReserve OrganizationMemberId used as their PIN

Static mode benefits:

  • Members learn their PIN once and reuse it for every future reservation
  • No need to check email — members always know their PIN
  • Staff can look up any member's PIN directly from their CourtReserve profile
  • No PIN recovery needed

Static mode requirement:
UniFi Access PIN mode must be set to Variable Length
Access → Settings → General → PIN → Variable Length

New Railway variable:

PIN_MODE=random

Leave as random to keep existing behavior unchanged.

Files changed

  • index.js
  • env.example
  • docs/configuration.md

How to update

Replace all three files in your GitHub repo — Railway redeploys automatically.

Verified

✅ Both modes confirmed working in production

v1.0.2 - SMS message improvements

17 Mar 01:33
83dadf2

Choose a tag to compare

What's new in v1.0.2

📱 SMS message improvements

Complete rewrite of the SMS template for clarity and correctness:

  • Club name is now fully dynamic from BRAND_CLUB_NAME — no hardcoded text
  • Club name and subject on separate lines for readability with longer names
  • Clear instruction to use the PIN at the front door keypad
  • States exactly how early the PIN activates based on ACCESS_BUFFER_MINUTES
  • Clarifies the PIN is valid for this reservation only
  • Removed STOP opt-out line to avoid member confusion on transactional messages

New SMS format:

Your Club Name
Your Door Access PIN

PIN: 67203419
Court: Court 1
Reservation: Mar 15, 12:00 PM

Enter this PIN at the front door keypad. Your PIN is
active 30 minutes before your reservation and is valid
for this reservation only.

Do not share this PIN.

🧹 Documentation cleanup

  • Updated SMS example in docs/email-setup.md to use generic placeholder values

Files changed

  • index.js
  • docs/email-setup.md

How to update

Replace both files in your GitHub repo — Railway redeploys automatically.

Verified

✅ Confirmed working in production

v1.0.1 - Visitor cleanup fix

16 Mar 00:13
9833e56

Choose a tag to compare

What changed

🐛 Bug fix — orphaned UniFi visitor cleanup

Previously, cleanup only ran against entries tracked in state.json. If Railway restarted and cleared /tmp/state.json, orphaned visitor records would remain in UniFi indefinitely — PINs never expired.

Cleanup now runs two passes every minute:

Pass Method Catches
Pass 1 Reads state.json Visitors CourtPin created in this session
Pass 2 Queries UniFi directly Orphaned visitors from any previous session

You will see this in Railway logs when Pass 2 fires:

[INFO] Cleaning up orphaned UniFi visitor {"visitorId":"..."}

How to update

Replace index.js in your GitHub repo — Railway redeploys automatically.

Verified

✅ Confirmed working in production

v1.0.0 - Initial release

16 Mar 00:10
b8576b9

Choose a tag to compare

CourtPin v1.0.0

First public release.

Features

  • Automatic PIN delivery via email and optional SMS
  • Time-limited UniFi Access visitor creation
  • Branded emails with club name and colors
  • Mobile-friendly admin portal for PIN lookup and resend
  • Multi-player reservation support
  • Auto-cleanup of expired visitor records
  • Supports Railway, Raspberry Pi, Docker, NAS, VPS, Windows

Requirements

  • CourtReserve account with API access
  • UniFi Access 1.9.1+
  • Resend account (free) or SMTP