The Worker needs a Notion integration token and an explicit database allowlist. The allowlist controls database selection in the admin interface; the Notion integration itself must also have access to each database.

Required page properties

Linked pages use fixed property names:

PropertyTypeStatus options
Voting StatusStatusNot started, In Voting, Done
Results LinkURL
NameTitle or rich text
DescriptionRich text or text
AttachmentsFiles and media

See Notion integration for which direction each property moves and the current route constraints.

1. Connect the integration

Create or select a Notion integration, then share each eligible database with it. Copy the integration token for NOTION_API_KEY.

Use actual Notion database ids in the allowlist. Names such as NOTION_DB_ID_ANY_VOTING are not variable references in this parser; if entered literally, the Worker sends that literal string to Notion as the database id.

2. Set Worker values

npx wrangler secret put NOTION_API_KEY
npx wrangler secret put NOTION_DATABASE_ALLOWLIST

For local development, put both values in .dev.vars and do not commit that file.

3. Format the allowlist

JSON is the clearest format:

[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Council elections"
  }
]

name is optional; the Worker displays the id when it is absent.

The parser also accepts comma-separated id:name pairs:

a1b2c3d4-e5f6-7890-abcd-ef1234567890:Council elections

Or ids without display names:

a1b2c3d4-e5f6-7890-abcd-ef1234567890,11111111-2222-3333-4444-555555555555

An empty or missing allowlist produces an empty database list.

4. Run locally

npm ci
npm run dev

Open the new-election admin page and confirm the database selector is populated. The relevant JSON check is:

GET /admin/notion/databases

A configured response has this shape:

{
  "databases": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Council elections"
    }
  ]
}

Then query a selected database:

GET /admin/notion/databases/:databaseId/pages

If the first route works but page lookup fails, check that NOTION_API_KEY is available and the database has been shared with that integration.

5. Deploy

npm run deploy

After deployment, repeat the authenticated database and page checks against the production Worker before linking an election.

Current limits

  • The allowlist parser checks configured ids but does not verify that a selected page’s parent matches the submitted database id during linking.
  • Page search with query targets a property literally named title; browsing without a query still discovers a title-type property for display.
  • Property names and status values are not configurable through the current routes.

Sources

Verified against ihnyc-rc-vote commit 2451aa1.

  • src/utils/notion.ts
  • src/routes/admin.ts
  • src/templates/admin-election-new.tsx
  • .dev.vars.example