An interactive, community-driven location review platform for New Zealand. Users can explore locations on a live map, watch embedded video reviews, leave their own star-rated community reviews, and log in with their social accounts. Admins can moderate content via a built-in panel.
Live demo URL:
YOUR_SITE_URLβ update this once deployed.
| Feature | Description |
|---|---|
| π Interactive Map | Leaflet.js map with custom markers and fly-to animations |
| β Community Reviews | Logged-in users can submit star-rated reviews per location |
| π₯ Video Embeds | YouTube, TikTok, Instagram & Facebook video embeds per location |
| π Social Login | Google OAuth, TikTok Login Kit, Meta (Instagram/Facebook) |
| π Dark / Light Mode | Toggle saved in localStorage |
| π‘οΈ Admin Panel | Report flagging, user banning, admin management |
| π Search & Sort | Filter by name/day; sort by day, score, community rating, or unvisited |
| π Rate Limiting | Per-IP review limits enforced client-side (localStorage) |
| π« Profanity Filter | Client-side word list filter applied to review submissions |
| π± Responsive | Mobile-friendly layout |
| Layer | Technology |
|---|---|
| Frontend | Vanilla HTML5, CSS3, JavaScript (ES6 modules) β no build step required |
| Map Engine | Leaflet.js v1.9.4 with CartoDB dark/light tile layers |
| Database | Supabase (PostgreSQL) β tables, Row Level Security (RLS), SECURITY DEFINER functions |
| Auth | Supabase Auth β Google OAuth, custom TikTok & Instagram flows |
| Backend Functions | Netlify Functions (Node.js) β serverless OAuth token exchange for TikTok and Instagram |
| Hosting | Netlify β static site + serverless functions |
| Fonts | Google Fonts β Outfit |
| Icons | FontAwesome 6 |
| Geocoding | Nominatim / OpenStreetMap β converts admin-entered addresses to lat/lng |
- A free Supabase account
- A Netlify account (for serverless functions & hosting)
- (Optional) Developer apps set up on TikTok for Developers and/or Meta for Developers if you want social login beyond Google
git clone https://github.com/YOUR_USERNAME/review-map.git
cd review-map- Create a new project at supabase.com.
- Go to SQL Editor β New Query and run
supabase_setup.sqlβ this creates all tables, functions, RLS policies, and seeds a few sample locations. - (Optional) If you need TikTok or Instagram login, also run:
supabase_tiktok_migration.sqlsupabase_insta_migration.sqlsupabase_tiktok_fix.sql(if needed)
- In Authentication β Providers, enable:
- Google β paste in your Google OAuth Client ID and Secret from Google Cloud Console
- (Optional) Any other providers you need
locations β Map pin records (name, coordinates, rating, review text, video URL, etc.)
profiles β Users created from social login (display name, avatar, provider, admin/ban status)
reviews β Community-submitted reviews (linked to location + user)
reports β Flagged reviews (admin moderation queue)
RLS is fully enabled. Key functions:
handle_new_user()β trigger that auto-creates a profile on first loginupsert_location(loc JSONB)β SECURITY DEFINER function for admin writes (bypasses RLS safely)is_user_admin()/is_user_banned()β used in RLS policies
After your first login, run this in the Supabase SQL Editor:
UPDATE profiles SET is_admin = TRUE WHERE id = 'paste-your-user-uuid-here';Find your UUID under Authentication β Users.
Copy the example config file and fill in your credentials:
cp js/config.example.js js/config.jsEdit js/config.js:
// Find these in your Supabase project β Settings β API
export const SUPABASE_URL = 'https://xxxx.supabase.co';
export const SUPABASE_ANON_KEY = 'your-anon-key-here';
// From your TikTok Developer App (Client Key only β secret stays on the server)
export const TIKTOK_CLIENT_KEY = 'your-tiktok-client-key';
β οΈ Never commitjs/config.jsβ it is excluded by.gitignore. Onlyconfig.example.jsis tracked.
The OAuth token exchange for TikTok and Instagram must happen server-side (the client secret must never be exposed in the browser). This is handled by two Netlify Functions in netlify/functions/:
| Function | Purpose |
|---|---|
tiktok-token.js |
Exchanges TikTok auth code for access token |
insta-token.js |
Exchanges Instagram auth code for access token |
Set the following environment variables in your Netlify dashboard (Site Settings β Environment Variables):
| Variable | Where to Find It |
|---|---|
SUPABASE_URL |
Supabase β Settings β API |
SUPABASE_SERVICE_ROLE_KEY |
Supabase β Settings β API (service role β keep secret!) |
TIKTOK_CLIENT_KEY |
TikTok Developer App |
TIKTOK_CLIENT_SECRET |
TikTok Developer App |
META_APP_ID |
Meta Developer App |
META_APP_SECRET |
Meta Developer App |
In each social platform's developer portal, you must whitelist your deployment URL as an allowed redirect. Set these based on your actual Netlify/custom domain:
Supabase (Google OAuth):
- Supabase β Authentication β URL Configuration β Site URL:
https://your-domain.com - Redirect URL:
https://your-domain.com
TikTok Developer App:
- Redirect URI:
https://your-domain.com/tiktok-callback.html
Meta Developer App (Instagram):
- Valid OAuth Redirect URIs:
https://your-domain.com/instagram-callback.html
npm install -g netlify-cli
netlify login
netlify init
netlify deploy --prod- Push your repo to GitHub.
- In Netlify, click Add new site β Import an existing project.
- Connect your GitHub repository.
- Netlify auto-detects
netlify.tomland deploys. - Add your environment variables under Site Settings β Environment Variables.
If you only need Google login (no TikTok/Instagram), you can deploy the static files to any host (GitHub Pages, Vercel, Cloudflare Pages, etc.) β no serverless functions required for Google auth. You still need to set SUPABASE_URL and SUPABASE_ANON_KEY in js/config.js.
review-map/
βββ index.html # Main app shell
βββ privacy.html # Privacy Policy
βββ terms.html # Terms of Service
βββ tiktok-callback.html # TikTok OAuth callback handler
βββ instagram-callback.html # Instagram OAuth callback handler
βββ styles.css # All styles (dark/light theme, layout, components)
βββ favicon.svg # SVG favicon
βββ netlify.toml # Netlify build config
βββ supabase_setup.sql # Full DB schema + seed data (run this first)
βββ supabase_tiktok_migration.sql
βββ supabase_insta_migration.sql
βββ supabase_tiktok_fix.sql
βββ netlify/
β βββ functions/
β βββ tiktok-token.js # Serverless: TikTok OAuth token exchange
β βββ insta-token.js # Serverless: Instagram OAuth token exchange
βββ js/
βββ config.js # β οΈ YOUR CREDENTIALS (gitignored)
βββ config.example.js # Template β copy this to config.js
βββ main.js # App entry point β wires everything together
βββ appState.js # Global UI state (user session, theme, admin mode)
βββ state.js # LocationState class β Supabase data layer
βββ components/
β βββ Map.js # Leaflet map, markers, popups, review forms
β βββ Sidebar.js # Location list, search, sorting
β βββ AdminModal.js # Add/edit location modal + toast notifications
βββ services/
β βββ SupabaseClient.js # Supabase JS client singleton
β βββ AuthService.js # Google + social login orchestration
β βββ TikTokAuthService.js
β βββ InstaAuthService.js
β βββ ReviewService.js # CRUD for reviews, profanity filter, cache
βββ data/
β βββ locations.js # Static sample locations (fallback / seed reference)
βββ utils/
βββ embeds.js # Video URL β embed HTML converter
js/config.jsis gitignored β only placeholder credentials are tracked viaconfig.example.js.- The Supabase service role key is only ever used inside Netlify Functions (server-side). It is never exposed to the browser.
- TikTok and Instagram client secrets are stored exclusively as Netlify environment variables.
- Row Level Security (RLS) is enforced on all Supabase tables.
- The
upsert_locationRPC usesSECURITY DEFINERwith an explicit admin check to safely bypass RLS for admin writes only.
This project was built as a community review map for New Zealand locations, but it's generic enough to adapt for any use case:
- Change the map centre β edit
setView([-40.9006, 174.8860], 6)injs/components/Map.js - Expand beyond NZ β remove or adjust
nzBoundsand thecountrycodes=nzgeocoding parameter inAdminModal.js - Change the colour scheme β edit the CSS variables at the top of
styles.css - Remove social logins you don't need β comment out the relevant buttons in
index.htmland skip those migrations/env vars
MIT β free to use, modify, and distribute. See LICENSE for details.