Skip to content

Latest commit

Β 

History

240 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

   ____            _         ____  _
  / ___|_ __ _   _| |__     / ___|| |_ __ _ _ __ ___
 | |  _| '__| | | | '_ \    \___ \| __/ _` | '__/ __|
 | |_| | |  | |_| | |_) |    ___) | || (_| | |  \__ \
  \____|_|   \__,_|_.__/    |____/ \__\__,_|_|  |___/

🍽️ Your All-in-One Restaurant Intelligence Tool 🍽️

Ruby License PRs Welcome


A restaurant reviews aggregator that brings together ratings, reviews, photos, and videos from multiple sources into a single, fast, local database. Access your aggregated data through a modern web UI, REST API, or command-line interface.

Why grub-stars?

Stop switching between Yelp, Google Maps, TripAdvisor, Instagram, and TikTok to research restaurants. grub-stars indexes your area once, then lets you search locally without repeated API calls.

Key Features:

  • πŸͺ Multi-source aggregation - Combine data from Yelp, Google Maps, TripAdvisor, Instagram, and TikTok
  • πŸš€ Fast local search - Index once, search instantly from SQLite
  • πŸ”‘ BYOK (Bring Your Own Key) - Use your own API keys
  • πŸ“ Geographic indexing - Index specific areas as needed
  • πŸ”— Lightweight storage - Store URLs to media, not the files themselves
  • πŸ”„ Smart deduplication - Automatically merges the same restaurant from different sources

Live Demo

Try it now: https://grub-stars-test.fly.dev

The test environment runs with a mock server that simulates responses from Yelp, Google Maps, and TripAdvisor. You can explore the full functionality without needing any API keys.

Demo data available for:

  • Location: "Barrie, Ontario"
  • Various restaurant categories (bakeries, cafes, etc.)

Features to try:

  • πŸ” Search for restaurants by name or category
  • πŸ“ Index the demo location to populate the database
  • 🏷️ Browse restaurants by categories
  • πŸ“± View detailed restaurant information with photos and reviews

The demo resets periodically, so feel free to experiment!

Quick Start

Installation

git clone https://github.com/aleccool213/grub-stars.git
cd grub-stars
gem install bundler -v 2.5.23
bundle _2.5.23_ install

Configuration

  1. Copy the environment template:

    cp .env.example .env
  2. Add your API keys to .env:

    YELP_API_KEY=your_yelp_key_here
    GOOGLE_API_KEY=your_google_key_here
    TRIPADVISOR_API_KEY=your_tripadvisor_key_here
    

    Configure at least one adapter to get started.

Running the Web Server

Start the web server to access the web UI and REST API:

bundle _2.5.23_ exec rackup

Then open your browser to http://localhost:9292

Web UI Features:

  • πŸ” Search restaurants by name or category
  • πŸ“ Index new geographic areas
  • 🏷️ Browse by categories
  • πŸ“± Responsive design for desktop and mobile

Using the CLI (Optional)

If you prefer the command-line interface:

ruby -I lib bin/grst index --location "barrie, ontario"                    # Index all restaurants
ruby -I lib bin/grst index --location "barrie, ontario" --category bakery  # Index only bakeries
ruby -I lib bin/grst search --category bakery                              # Search locally
ruby -I lib bin/grst info --name "restaurant name"                         # Get detailed info

Architecture

grub-stars uses a clean layered architecture that separates concerns and makes the codebase testable and extensible:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚            Presentation Layer                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚   Web UI            β”‚  β”‚   REST API           β”‚   β”‚
β”‚  β”‚   (Browser)         β”‚  β”‚   (lib/api/server.rb)β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                      β”‚
β”‚  CLI (optional)                                      β”‚
β”‚  (lib/cli.rb)                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Services (lib/services/)                           β”‚
β”‚   Business operations & use cases                    β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                              β”‚
β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Domain            β”‚    β”‚  Infrastructure         β”‚
β”‚   Pure logic        β”‚    β”‚  Repositories           β”‚
β”‚   Models            β”‚    β”‚  Database (SQLite)      β”‚
β”‚   Matcher           β”‚    β”‚  External API Adapters  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Layers:

  • Presentation - Web UI (vanilla JavaScript), REST API (Sinatra), and CLI (Thor) - all thin wrappers that delegate to services
  • Services (lib/services/) - Use cases: indexing, searching, getting details, listing categories
  • Domain (lib/domain/) - Pure business logic and models (Restaurant, Rating, Review, etc.)
  • Infrastructure (lib/infrastructure/) - Repositories, database, and external API adapters

See ARCHITECTURE.md for detailed design documentation.

Data Sources

Implemented

  • βœ… Yelp - Ratings, reviews, photos
  • βœ… Google Maps - Ratings, reviews (up to 5), photos
  • βœ… TripAdvisor - Ratings, reviews, photos

Planned

  • 🚧 Instagram - Photos and videos only
  • 🚧 TikTok - Videos only

Development

Running Tests

Ruby tests (CLI, API, domain logic):

ruby -I lib $(bundle _2.5.23_ show rake)/exe/rake test              # Run all tests
ruby -I lib $(bundle _2.5.23_ show rake)/exe/rake test:integration  # Run integration tests only
ruby -I lib $(bundle _2.5.23_ show rake)/exe/rake test:unit         # Run unit tests only

JavaScript tests (Web UI):

npm test                           # Run all JS tests
npm run test:install               # Install Playwright (first time only)

Project Structure

lib/
β”œβ”€β”€ domain/          # Pure business logic (zero dependencies)
β”œβ”€β”€ infrastructure/  # Database, repositories, adapters
β”œβ”€β”€ services/        # Application use cases
β”œβ”€β”€ api/             # REST API (Sinatra)
└── cli.rb           # CLI interface (Thor)

web/                 # Web UI (vanilla JavaScript + HTML)
β”œβ”€β”€ index.html       # Search page
β”œβ”€β”€ details.html     # Restaurant details
β”œβ”€β”€ index-location.html  # Indexing page
β”œβ”€β”€ js/              # JavaScript components and tests
└── css/             # Styles

tests/
β”œβ”€β”€ unit/           # Fast tests with mocks
└── integration/    # Full-stack tests

Tech Stack

Backend:

  • Ruby - Core language
  • Sinatra - REST API framework
  • Thor - CLI framework
  • Sequel - Database ORM
  • SQLite3 - Local database
  • Faraday - HTTP client for adapters
  • dotenv - Environment management

Frontend:

  • Vanilla JavaScript - No framework dependencies
  • HTML5 & CSS3 - Modern web standards
  • Playwright - Headless testing

Getting API Keys

Documentation

How It Works

1. Indexing

When you index a location (via Web UI or CLI), grub-stars:

  1. Queries all configured adapters (Yelp, Google Maps, etc.) for restaurants in the area
  2. Uses a matcher with confidence scoring to identify duplicate restaurants across sources
  3. Stores everything in a local SQLite database

You can optionally filter by category during indexing to focus on specific restaurant types.

2. Deduplication

The matcher prevents duplicates by scoring similarity:

  • Name similarity: ~30 points
  • Address match: points based on similarity
  • GPS proximity: points based on distance
  • Phone number match: additional points

Restaurants scoring >50 are considered the same and their data is merged.

3. Searching

All searches happen locally against SQLite through the Web UI, REST API, or CLI, so they're instant. No API calls required after indexing.

REST API

The REST API provides programmatic access to all functionality:

# Start the server
bundle _2.5.23_ exec rackup -p 3000

Available Endpoints

Endpoint Method Description
/health GET Health check
/categories GET List all categories
/locations GET List all indexed locations
/restaurants/search?name=X GET Search by name
/restaurants/search?category=X GET Search by category
/restaurants/:id GET Get restaurant details
/index POST Index restaurants (body: {"location": "city", "category": "optional"})

Response Format

{
  "data": <result>,
  "meta": { "timestamp": "...", "count": 10 }
}

For detailed API examples and integration guides, see docs/api.md.

Design Principles

  • Local-first: Fast queries without repeated API calls
  • Selective indexing: Index only areas you care about, optionally filtered by category
  • Flexible refresh: Re-index anytime to get fresh data
  • Bring Your Own Key: You control your API usage and costs
  • Lightweight: Store media URLs, not files

Contributing

This is a personal project, but contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT License - see LICENSE file for details

Future Plans

  • Add Instagram adapter (photos/videos only)
  • Add TikTok adapter (videos only)
  • Add caching layer for API responses
  • Export functionality (CSV, JSON)
  • Restaurant comparison features
  • Mobile app for native iOS/Android access

Built with ❀️ using Ruby and clean architecture principles

About

A command line restaurant reviews aggregator

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages