Skip to content

Repository files navigation

Epicure

A restaurant discovery and ordering platform — browse restaurants and chefs, filter by cuisine/price/rating/distance, view dish menus, and check out with a live order history.

Built as an Nx monorepo: a Next.js frontend, a NestJS API layer, and a Strapi CMS backing content and orders.

Epicure homepage

Table of contents

Features

  • Restaurant discovery — browse by tab (All / Popular / New / Open Now / Map), filter by price, rating, cuisine, and distance from your location
  • Map view — restaurant markers on an interactive map (MapTiler + Leaflet), with a user-location dot and recenter button
  • Search — live-filtered search across restaurants, cuisines, and chefs from the header and homepage hero
  • Restaurant & dish detail — meal-time tabs (Breakfast/Lunch/Dinner), dish type icons (spicy/vegan/vegetarian), signature dishes
  • Chefs — chef profiles, "Chef of the Week" highlight, modal bios, deep-linking from search results
  • Cart & checkout — per-user cart (survives login/logout with conflict resolution on merge), delivery + payment form, order summary, success confirmation
  • Order history — past orders with re-order and order-summary views
  • Auth — register/login, JWT-based session, auto-logout on token expiry
  • Infinite scroll — restaurants, chefs, and order history all paginate as you scroll (see useInfiniteScroll)

Tech stack

Layer Tech
Frontend Next.js 16 (App Router, Turbopack), React 19, SCSS (SMACSS)
Backend NestJS 11
CMS Strapi 5 (SQLite)
Shared TypeScript, Nx 22 monorepo, npm workspaces
Maps MapTiler + Leaflet / react-leaflet
Testing Jest, React Testing Library, Playwright (e2e)

Architecture

Frontend (Next.js, :3000)
    │  fetch/post
    ▼
Backend (NestJS, :3333)
    │  proxies + transforms
    ▼
Strapi CMS (:1337)

The frontend never calls Strapi directly — the NestJS backend acts as a proxy layer: it fetches from Strapi, reshapes the responses into clean REST endpoints, and is the only service that holds the Strapi admin token used for order read/write.

Backend endpoints:

  • GET /api/restaurants, GET /api/restaurants/:id
  • GET /api/chefs, GET /api/chefs/:id
  • GET /api/dishes, GET /api/dishes/:id
  • POST /api/auth/login, POST /api/auth/register
  • POST /api/orders, GET /api/orders

Monorepo structure

apps/
  frontend/       Next.js 16 app (React, Turbopack, App Router) — port 3000
  frontend-e2e/   Playwright e2e tests
  backend/        NestJS 11 REST API — port 3333
  backend-e2e/    Jest integration tests
libs/
  shared-types/   TypeScript interfaces shared between frontend & backend
  ui-components/  React component library (StarRating, RestaurantCard, DishCard, ChefCard, ...)
  utils/          Shared utility functions
strapi/           Strapi 5 CMS — port 1337 (separate ecosystem, own node_modules)

Getting started

Prerequisites

  • Node.js 24 (the lockfile is generated with npm 11)
  • npm

Install

npm install
cd strapi && npm install && cd ..

Configure environment

Copy the Strapi env template and fill in real secrets:

cp strapi/.env.example strapi/.env

Create apps/backend/.env with a Strapi admin API token (generate one in the Strapi admin panel after first boot — see Environment variables):

STRAPI_ADMIN_TOKEN=your-strapi-full-access-token

Create apps/frontend/.env.local with a MapTiler API key (needed for the restaurants map view):

NEXT_PUBLIC_MAPTILER_KEY=your-maptiler-key

Run

npm run dev:all     # frontend + backend + strapi together

Or run just the app (frontend + backend) if Strapi is already running elsewhere:

npm run dev

Then visit:

On first boot, create a Strapi admin user, add some restaurants/chefs/dishes content, and generate a Full access API token under Settings → API Tokens — paste it into apps/backend/.env as STRAPI_ADMIN_TOKEN.

Environment variables

Variable Where Default Purpose
STRAPI_URL backend http://localhost:1337 Strapi base URL the backend proxies to
STRAPI_ADMIN_TOKEN apps/backend/.env (gitignored) — Strapi Full-access token; required for order read/write. Must be regenerated after any Strapi DB reset
PORT backend 3333 Backend listen port
NEXT_PUBLIC_BACKEND_URL frontend http://localhost:3333 NestJS base URL used by the frontend
NEXT_PUBLIC_STRAPI_URL frontend http://localhost:1337 Base URL for building Strapi image URLs
NEXT_PUBLIC_MAPTILER_KEY apps/frontend/.env.local (gitignored) — MapTiler API key for map tiles

Available scripts

All tasks run through Nx — prefer these over calling the underlying tooling directly.

npx nx run-many -t lint test build --exclude strapi   # what CI runs
npx nx run @org/frontend:dev                            # frontend only
npx nx run @org/backend:serve                            # backend only
npx nx e2e @org/frontend-e2e                              # Playwright e2e
npx nx affected -t test                                   # only what changed

Testing & CI

.github/workflows/ci.yml runs on every push to main and every PR:

  1. npm ci (Node 24)
  2. npx nx run-many -t lint test build --exclude strapi

Strapi is excluded from CI since it's a separate ecosystem with its own dependency tree.

Contributing

  • main is protected — all changes go through a PR and need approval from a CODEOWNERS reviewer
  • Nx Cloud is intentionally disabled for this repo
  • See CLAUDE.md for detailed conventions (SCSS architecture, component patterns, known gotchas) if you're using an AI coding assistant on this repo

About

Epicure is a full-featured restaurant discovery and ordering platform. Browse restaurants and chefs, filter by cuisine/price/rating/distance, view menus, and checkout with order history. Built as an Nx monorepo with Next.js frontend, NestJS backend API, and Strapi CMS for content management and real-time order tracking.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages