Skip to main content

Places

Status: Proposed 2026-09-24, scaffolded in the API (list, get, submit, approve); ingest rules added 2026-09-29; lists, reviews, and check-ins match the API as of 2026-10-24

Places are The Trick Book's Spots with the sport swapped for the cause. A Place is a sanctuary, restaurant, cafe, grocery, shop, community garden, organization, or venue with a pin on the map, a vegan level, and community verification. Places are public and carry no member data, which makes them the safest feature to ship first.

Why​

An activist new to an area asks three questions: where can I eat, where can I volunteer, where do people meet. A map that answers all three with data the community keeps honest is the reason to open the app on a Tuesday, which is what makes the Saturday action discoverable.

What ships in v1​

  • A map (MapLibre, OpenFreeMap tiles) with clustered pins, driven by the viewport's bounding box. The default view leans fully vegan: veganLevel: full only, chains hidden. "Include vegan options" and "show chains" are opt-in toggles, and fully vegan places sort first everywhere.
  • A Place page: name, type, vegan level (full or options), address, postcode, hours, phone, website, tags (cuisine, wheelchair, outdoor seating, takeaway, delivery), photos, reviews, upcoming events at this place, and the source attribution.
  • Community gardens (type: garden, always full) from OpenStreetMap, so a Grove can find a place to grow food together.
  • Submit a place (signed in): pin drop or address search, type, vegan level, a photo. Enters pending; an admin approves. The submitter is never shown.
  • Reviews: rating, text, the month visited, and an opt-in to show the author's handle. One active review per member per place.
  • Check-ins: a separate, anonymous confirmation of the vegan level, one per member per place per UTC month. The page shows the count and the latest month.
  • Place lists: private collections ("want to try", "volunteer here"). isPublic is stored for future friend sharing and is not published yet. Another member's list, including one with the flag set, is not readable.
  • Farmers and produce markets from OpenStreetMap, stored as grocery with the tag market:farmers. See data sources.
  • Seed data: OpenStreetMap diet:vegan tags for the SoCal bounding box (531 tagged places at the time of writing) plus a curated sanctuary list, all imported as pending and approved by hand. See data sources and the ingest rules for places.

Data and visibility​

places (public once approved, including the check-in aggregates), place_reviews (public text, handle only if showHandle), place_checkins (one row per member per place per UTC month; only the aggregates are public), place_lists (the owner only; isPublic is stored and not a visibility grant yet). The data model has the schema. Geo queries are bounding-box only; no point ever leaves the device (ADR-0005).

API​

GET /api/places?bbox=&type=&veganLevel=&includeChains=&q=, GET /api/places/map-pins (pins only, no cursor), GET /api/places/:slug, POST /api/places (member, pending), POST /api/ingest/places (ingest key, see ingest), GET/POST /api/places/:id/reviews, GET/POST /api/places/:id/check-ins, place-list routes under /api/place-lists (owner only), admin GET /api/admin/places/pending, PUT /api/admin/places/:id/approve|reject, and admin review hide and restore. The shapes, status codes, and the isPublic rule are on the API endpoints page. Public reads return approved places only; a non-approved place is visible to its submitter and admins, and a list can still embed a pending place its owner saved.

Screens​

Web: /places (map plus list), /places/[slug]. Mobile: the Places tab (map with a list toggle), a place sheet, submit-a-place, my lists.

Verification​

Community verification is what keeps the vegan level honest. See verification.

Open questions​

  • Hours: import from OSM when present, let members correct; do we show "hours unverified" until a member confirms?
  • Claiming: a business can claim its Place to fix details. Claimed status is public; the claimant is not. Scope for M2 or later.