An interactive community map where visitors can explore user-submitted pins and optionally add their own. Submissions are anonymous, go into a moderation queue, and only appear on the public map after approval.
The app is built as a lightweight SPA with React + Vite, uses MapLibre GL with the hosted Protomaps basemap, and stores data in Supabase (Postgres + Row-Level Security).
- Create a
.envfile with your credentials:
VITE_SUPABASE_URL=<your supabase project url>
VITE_SUPABASE_ANON_KEY=<anon key>
VITE_PROTOMAPS_KEY=<protomaps api key>
# Optional: override the default light theme style URL
VITE_PROTOMAPS_STYLE_URL=<protomaps style url>Security note: Only use the Supabase anon key in your
.env. Do not expose the service role key to the browser; privileged moderation tooling now lives outside this app.
- Install dependencies and run the dev server:
npm install
npm run dev- Open
http://localhost:5173to view the map.
If the map fails to load, check that VITE_PROTOMAPS_KEY or VITE_PROTOMAPS_STYLE_URL is set.
-
Interactive world map
- Pan/zoom basemap using MapLibre GL + Protomaps.
- Approved pins rendered as circle markers.
- Inline banner messaging if the map fails to load.
-
Anonymous pin submission
- Users click on the map to choose a location.
- Sidebar form to describe themselves / their interests and optionally add contact handles.
- Submissions are stored as
pendingand do not appear on the map until approved.
-
Moderation pipeline
- Pins remain pending until reviewed with the external moderator tools.
- This repository only contains the public map and submission flow.
-
Safety by design
- Supabase Row-Level Security (RLS):
- Public users can insert new pins as
pending. - Public users can only read
approvedpins.
- Public users can insert new pins as
- Supabase Row-Level Security (RLS):
Rough layout:
community-map/
├─ public/
├─ src/
│ ├─ App.jsx # Main map + sidebar + submission form
│ ├─ MapView.jsx # MapLibre map & pins rendering with map status banners
│ ├─ main.jsx # React entry, React Router setup
│ ├─ index.css # Global styles
│ └─ supabaseClient.js # Supabase JS client
├─ index.html
├─ package.json
├─ vite.config.js
├─ .gitignore
└─ README.md