CivRails Railway Network

Stations and routes live in a private Google Sheet, served through a Netlify Function. Edit the sheet — this page updates itself.
Connecting…
Admin: how this is wired up

This page calls /api/routes?sheet=Stations and /api/routes?sheet=Routes on its own domain to read live data, and /api/suggest to accept public suggestions. Two Netlify Functions (routes.js read-only, suggest.js write-only into the review tabs) talk to the Google Sheets API as a service account — no Apps Script, no public link, credentials never reach the browser.

One-time setup:

  1. Google Cloud Console → enable the Google Sheets API → create a Service Account → download its JSON key.
  2. Share the Google Sheet with the service account's client_email as Editor (Viewer isn't enough now — suggestions need to write into the review tabs).
  3. Sheet needs 4 tabs: Stations, Routes (the live data — keep these as the only ones the site reads from) and Suggested Stations, Suggested Routes (where public suggestions land — never read by the site, only written to).
  4. Deploy this folder to Netlify. In Site settings → Environment variables, set GOOGLE_SERVICE_ACCOUNT_EMAIL, GOOGLE_PRIVATE_KEY, and SPREADSHEET_ID. Redeploy.

Routes sheet has one row per directed connection (From → To). This network's connections aren't all mirrored, so add both directions as separate rows if a new connection should work both ways.

Reviewing suggestions: open the Suggested Stations / Suggested Routes tabs, check each row, then copy the matching columns (they line up with the live tabs) into Stations / Routes and delete the reviewed row. Nothing a user submits goes live automatically. The form itself already checks both the live tabs and these review tabs before writing — someone submitting a station or route that already exists (or is already pending review) is told so directly and nothing duplicate gets added.

Suggest a new station or route
Goes into a review tab in the sheet — nothing goes live automatically.

Route Found