Fujimod
Try your camera firmware in the browser and build Fujimod SD boot files.
Most food apps give you endless recs. Locals tells you where to go tonight.
Translation pending
LifestyleGitHub @harrisonmangitwongOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗I was traveling in Taiwan and ran into a problem I couldn't shake: I'd open Google Maps, search for food nearby, and the top results were clearly tourist traps — high ratings, thousands of reviews, packed with visitors, but locals I talked to had never heard of them.
The star rating wasn't measuring quality. It was measuring tourist attention volume.
I came back and noticed the same problem in NYC. One of the most reviewed cities in the world, but the rankings are polluted by one-time visitors who have no stake in whether a neighborhood restaurant actually holds up. The places real New Yorkers return to every week were buried under spots that had learned to optimize for foot traffic, not food.
That's what Locals is built to fix.
Google Maps has enormous amounts of data. The problem isn't data quality — it's that all reviewers are treated equally.
A tourist visiting New York once and a local who's eaten out 200 times in the city carry completely different signal value. If you know who is leaving the review, you can re-weight the ratings to surface what locals actually think.
1. Score every reviewer
Each reviewer gets a localness score from 0 to 1, built from three signals:
2. Re-weight the ratings
Using those scores, every restaurant gets two separate ratings: a local-weighted rating and a tourist-weighted rating. The gap between them is one of the strongest signals of whether a place is a neighborhood staple or riding tourist hype.
3. Run a classifier
I hand-labeled 205 restaurants as "local-approved" or not to create training data, then trained a Random Forest on 20 features — review statistics, NLP signals from review text (quality language, local vs. tourist patterns), price range, and rating distribution.
It's graded only on restaurants it didn't train on (5-fold cross-validation, repeated 10 times with different shuffles). It ranks a local-approved place above one that isn't about 70% of the time (AUC ~0.70), against 60% for sorting by Google stars.
The model outputs a confidence score for each restaurant. That score drives the final ranking.
4. Surface it cleanly
The app lets you filter by neighborhood, cuisine, price range, and whether a place is open now. Restaurant pages show the local take in plain language — no jargon, no bar charts, just: "locals rate it 4.4 vs. tourists' 3.8 — regulars love it more than visitors do."
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, TypeScript, Tailwind CSS |
| Backend | FastAPI, Python |
| Database | Supabase (PostgreSQL) |
| Auth | Supabase Auth (Google OAuth) |
| ML | scikit-learn (Random Forest), pandas, numpy |
| Data collection | Apify (Google Maps scraper) |
| Deployment | Vercel (frontend), Railway (backend) |
Dataset: 78,000+ reviews · 2,100+ restaurants scraped · 384 on the live list · 205 hand-labeled training examples · 20 classifier features
Backend
pip install -r requirements.txt
python3 -m uvicorn backend.main:app --port 8000
Frontend
cd frontend
npm install
npm run dev
App runs at http://localhost:3000.
Create frontend/.env.local:
NEXT_PUBLIC_API_URL=http://localhost:8000
AUTH_SECRET=<your-secret>
AUTH_GOOGLE_ID=<your-google-client-id>
AUTH_GOOGLE_SECRET=<your-google-client-secret>
NEXT_PUBLIC_SUPABASE_URL=<your-supabase-url>
SUPABASE_SERVICE_ROLE_KEY=<your-supabase-service-role-key>
locals/
├── backend/
│ ├── main.py # FastAPI app — recommendations, filters, open-now logic
│ └── data.csv # Enriched restaurant dataset (ML scores + metadata)
├── frontend/
│ ├── app/
│ │ ├── recommendations/ # Main discovery page with filters
│ │ ├── restaurant/[id]/ # Restaurant detail page
│ │ ├── favorites/ # Saved restaurants (per-user, Supabase-backed)
│ │ └── api/ # Auth + saved/visited API routes
│ └── components/ # RestaurantCard and shared UI
├── data/
│ ├── reviews.csv # Raw reviews (48k+)
│ └── restaurants.csv # Raw restaurant metadata
├── pipeline.py # ML training pipeline (reviewer scoring → classifier)
├── enrich_data.py # Enrichment from raw Apify output
└── scrape_google_maps.py # Apify scraper config