Overview
- The worker integrates with up to four Notion databases
- Database ids are set as
[vars]inwrangler.toml; the API key is a Wrangler secret NOTION_DATABASE_IDis required for live event data; shifts, announcements, and an explicit tender-directory DB are optional- If
NOTION_API_KEYis not configured,/api/eventsfalls back to placeholder data instead of live Notion results
Sources: worker.js (CONFIG section), wrangler.toml
Credentials
wrangler secret put NOTION_API_KEYThe integration token must have read access to every database the worker touches.
Optional QR sync credentials
If you want the Worker to generate Short.io tender QR codes and write them back into Notion, also configure:
wrangler secret put NOTION_QR_SYNC_API_KEY
wrangler secret put SHORT_IO_API_KEY
wrangler secret put TENDER_QR_SYNC_TOKENNOTION_QR_SYNC_API_KEYshould point at a narrower integration with write access to the Pub Tender DBSHORT_IO_API_KEYis the Short.io API token used to create or update links and QR SVGsTENDER_QR_SYNC_TOKENprotectsPOST /api/sync-tender-qrs
Events Database (NOTION_DATABASE_ID)
Drives both todayEvents and weekEvents in the API response.
Required properties
| Notion property | Type | Notes |
|---|---|---|
Name | Title | Event name |
Event Start | Date | Start date/time, ideally with timezone |
Event End | Date | End date/time, optional but recommended |
Include on Pub TV | Checkbox | Must be checked for the event to appear |
Optional properties
| Notion property | Type | Notes |
|---|---|---|
Location | Rich text or Select | Displayed inline with the time on the TV and iPad board. No longer used for filtering — any location value (or none) is fine. |
Duration (hrs) | Number | Used to estimate end time if Event End is not set |
Source Email Subject | Rich text | Scanned for RC-Direct or RC-Affiliate substrings |
TV include gate
The
Include on Pub TVcheckbox is the sole gate. Location is no longer required to contain"pub"— events at any location can appear on the display.
Sources: worker.js (PROP_TV_INCLUDE, PROP_SOURCE_EMAIL_SUBJECT, PROP_LOCATION)
Shifts Database (NOTION_SHIFTS_DATABASE_ID)
Drives the pub-tender footer and the weekly pub-hours grid.
Required properties
| Notion property | Type | Notes |
|---|---|---|
Date/Time | Date with end | Full shift window including setup and cleanup |
Not in Pub | Checkbox | If checked, the shift is excluded from the pub display |
Optional properties
| Notion property | Type | Notes |
|---|---|---|
Operational Timeframe | Date with end | Narrower serving window used for hours display and footer state |
Last Call | Number | Minutes before operational end to enter the last-call state |
Shift Status | Select or Status | Informational only; not currently used in rendering |
Assignments DB | Relation | Links shifts to assignment rows |
Shift state logic
Full shift window: |------------------------------------|
Operational timeframe: |----------------------|
Last call window: |---|
setup active last-call closedSources: worker.js (fetchPubTenderFromNotion, deriveShiftNote)
Assignments relation
The Shifts DB links to an Assignments DB via the Assignments DB relation. Each assignment row links to individual Pub Tender pages via the Pub Tenders DB relation.
flowchart LR SHIFT["Shifts DB page"] -- "Assignments DB" --> ASSIGN["Assignment page"] ASSIGN -- "Pub Tenders DB" --> TENDER["Pub Tender page"] TENDER -- "Name (always)" --> FOOTER["TV footer"] TENDER -- "Picture / QR when opted in" --> SLIDE["TV tender slide"]
Sources: worker.js (fetchTenderInfoFromAssignment, fetchTenderInfoFromAssignmentPage)
Pub Tender Database (NOTION_PUB_TENDERS_DATABASE_ID)
This optional env var points directly at the tender directory database used by GET /api/tenders.
If it is not set, the worker can still discover the directory database by following:
Shifts DB -> Assignments DB -> Pub Tenders DB
Setting NOTION_PUB_TENDERS_DATABASE_ID explicitly is still recommended because it is easier to reason about and troubleshoot.
Required properties
| Notion property | Type | Notes |
|---|---|---|
Name | Title | Tender’s full display name |
Active | Checkbox | Must be checked for the tender to appear in /api/tenders and /tenders/ |
Optional properties
| Notion property | Type | Notes |
|---|---|---|
Tender ID | Text / Unique ID / Rich text | Required for stable /tenders/?tender=<id> links and automated QR sync |
Bio | Rich text | Used in the directory modal on /tenders/ |
Picture | Files and media | Used in both the directory and TV tender slides |
Meet your Tender | Checkbox | Must be checked for the tender to appear in TV tender slides |
QR | Files and media | Pre-rendered QR image shown on TV tender slides |
Zelle | Rich text / URL / Phone / Email | Used by the /tenders/ modal payment button |
Venmo | Rich text / URL | Used by the /tenders/ modal payment button |
QR Link | URL / Rich text | Written by the QR sync flow when available |
Short.io Link ID | Rich text / Text | Written by the QR sync flow when available |
Page URL | URL | General profile URL metadata |
URL | URL | Alternate URL metadata |
Link | URL | Alternate URL metadata |
Current behavior by property
| Property | Used by | Current behavior |
|---|---|---|
Active | /api/tenders | Gates directory inclusion |
Meet your Tender | /api/events → TV slides | Gates whether the tender becomes a TV profile slide |
Tender ID | /tenders/?tender=<id>, QR sync | Canonical id for deep links and Short.io slug generation |
Bio | /api/tenders | Shown in the /tenders/ modal |
Picture | Both | Used in the directory and TV |
QR | TV slides, QR sync | TV reads only the QR image file; QR sync writes the SVG here |
Zelle | /tenders/ modal | Frontend converts email to mailto: and phone-like values to tel: |
Venmo | /tenders/ modal | Frontend accepts either a full Venmo URL or an @handle-style value |
PayPal / Paypal / PayPal URL / Paypal URL | /tenders/ modal | Frontend accepts a full PayPal URL or a PayPal handle-style value |
QR Link / Short.io Link ID | QR sync | Used to track or update existing Short.io links |
Page URL / QR Link / URL / Link | Directory metadata | Used to resolve pageUrl on tender objects |
QR behavior on TV
The current TV implementation only renders
qrImageUrl, which comes from the tender page’sQRfile property. The recommended path is to keep that property populated viaPOST /api/sync-tender-qrs. URL properties likeQR LinkandPage URLare not turned into a runtime-generated QR on the TV.
Meet your Tender gate
If
Meet your Tenderis unchecked, the tender can still appear in/tenders/ifActiveis checked and can still appear by first name in the TV footer if assigned to the active shift. The checkbox only gates the TV profile slide.
Property name casing
The
Meet your Tendercheckbox lookup is case-insensitive.
Sources: worker.js (fetchTenderInfoFromAssignmentPage, transformTenderDirectoryPage, extractUrlPropertyByNames)
Announcements Database (NOTION_ANNOUNCEMENTS_DATABASE_ID)
Drives announcement slides in the TV slideshow and the /announcements/ page.
Required properties
| Notion property | Type | Notes |
|---|---|---|
Name | Title | Fallback announcement text if Content is empty |
Include on Pub TV | Checkbox | Must be checked for the announcement to be returned |
Optional properties
| Notion property | Type | Notes |
|---|---|---|
Content | Rich text | Preferred announcement text source |
Priority | Select | Optional styling hint; currently used for high slides |
Duration | Number | Optional slide duration in seconds |
Picture / Image / PNG | Files and media | Optional announcement image used by both /tv/ and /announcements/ |
No date filtering
Announcements are not currently filtered by date. Archive or remove stale rows to keep the display clean.
Announcement image routing
The worker rewrites announcement images to same-origin
/api/image/announcement/:pageIdURLs before handing them to the frontend. This helps embedded TV browsers handle the images more reliably.
Sources: worker.js (fetchAnnouncementsFromNotion)
wrangler.toml configuration
[vars]
NOTION_DATABASE_ID = "<32-char hex ID from Events DB URL>"
NOTION_SHIFTS_DATABASE_ID = "<32-char hex ID from Shifts DB URL>"
NOTION_ANNOUNCEMENTS_DATABASE_ID = "<32-char hex ID from Announcements DB URL>"
NOTION_PUB_TENDERS_DATABASE_ID = "<32-char hex ID from Pub Tenders DB URL>"
PUBLIC_SITE_URL = "https://pub.ihnyc-rc.org"
SHORT_IO_DOMAIN = "go.example.org"Database ids are the 32-character hex string in the Notion URL before the ? query string.