Rest App is a premium-style restaurant reservation app inspired by products like Resy and OpenTable, with a more editorial and discovery-focused UI. The project uses a Next.js frontend, a FastAPI backend, PostgreSQL, SQLAlchemy, and Alembic.
The current app supports:
- homepage discovery and hero search
- restaurant search by location, restaurant name, or cuisine
- restaurant browsing with a split-view results page
- restaurant location detail pages with location-specific availability
- reservation creation and cancellation
- JWT signup and login
- an authenticated "My Reservations" page
- an admin page for creating availability and reviewing bookings by location
- Frontend: Next.js 15 + React 19 + TypeScript
- Styling: Tailwind CSS
- Backend: FastAPI
- Database: PostgreSQL
- ORM: SQLAlchemy
- Migrations: Alembic
- Auth: JWT + Argon2 password hashing
- The homepage includes a large hero search form
- Users can search using:
- loc / city
- restaurant name
- cuisine
- Optional search inputs:
- date
- time
- party size
- The
/restaurantspage shows:- a searchable restaurant location list
- a selected restaurant preview panel
- links into the full restaurant detail page
Restaurantstores shared brand dataRestaurantLocationstores the physical bookable listing- search returns one result per location, not one result per brand
- example:
Negroni — BrickellNegroni — DoralNegroni — Wynwood
- Open a restaurant location detail page
- Select a date
- View available slots
- Log in if needed
- Book a reservation
- View upcoming reservations on
/reservations - Cancel a reservation
- Sign in as the configured admin email
- Open
/admin - Create availability slots for a location table
- Review bookings for a location on a selected date
- See booking user name and email
- JWT-based signup and login
- Protected reservation creation
- Protected "My Reservations" page
- Admin-only availability tools
- Search endpoint compatible with the current frontend
- Real restaurant
priceRangeandratingvalues stored in the database - Real location
address,website, andphone - Seed data with multiple restaurants, two locations per restaurant, location-specific tables, and location-specific availability slots
- Shared app shell with reusable logo and footer
Rest-app/
├── backend/
│ ├── alembic.ini
│ ├── app/
│ │ ├── api/
│ │ │ ├── admin.py
│ │ │ ├── auth.py
│ │ │ ├── health.py
│ │ │ ├── me.py
│ │ │ └── restaurants.py
│ │ ├── core/
│ │ │ ├── auth.py
│ │ │ ├── config.py
│ │ │ └── security.py
│ │ ├── db/
│ │ │ ├── base.py
│ │ │ ├── seed.py
│ │ │ └── session.py
│ │ ├── models/
│ │ │ ├── availability_slot.py
│ │ │ ├── reservation.py
│ │ │ ├── restaurant.py
│ │ │ ├── restaurant_location.py
│ │ │ ├── restaurant_table.py
│ │ │ └── user.py
│ │ ├── schemas/
│ │ │ ├── auth.py
│ │ │ └── restaurant.py
│ │ └── main.py
│ ├── migrations/
│ │ └── versions/
│ └── requirements.txt
├── frontend/
│ ├── public/
│ ├── src/
│ │ ├── app/
│ │ │ ├── admin/
│ │ │ ├── login/
│ │ │ ├── reservations/
│ │ │ ├── restaurants/
│ │ │ ├── signup/
│ │ │ ├── globals.css
│ │ │ ├── icon.tsx
│ │ │ ├── layout.tsx
│ │ │ └── page.tsx
│ │ ├── components/
│ │ └── lib/
│ ├── package.json
│ └── tsconfig.json
├── .env.example
├── docker-compose.yml
└── README.md
The app currently uses six main models:
User- account email
- password hash
- admin flag
Restaurant- shared brand-level data
- name
- cuisine
- description
- price range
- rating
- hero image
RestaurantLocation- one physical customer-facing listing
- belongs to one
Restaurant - location name
- city
- neighborhood
- address
- website
- phone
- image
Table- physical table inside one restaurant location
- seat count
AvailabilitySlot- one bookable time for one table
- belongs to one restaurant location
- party size
- booked flag
Reservation- ties together:
- one user
- one restaurant brand
- one restaurant location
- one table
- one availability slot
- ties together:
- Next.js App Router pages render the product UI
- Server components fetch data for:
- homepage
- restaurants page
- restaurant detail page
- Client components handle:
- login/signup
- booking
- reservation cancellation
- admin tools
- nav auth state
- JWT auth state is stored in
localStoragefor now
- FastAPI exposes:
- public routes
- authenticated routes
- admin-only routes
- SQLAlchemy models map to PostgreSQL tables
- Alembic manages schema changes
- shared auth dependencies resolve the current user from the JWT on protected requests
- Homepage hero submits search params to
/restaurants /restaurantscalls the backend search endpoint when filters are present- Search is currently compatible with:
- location / city
- restaurant name
- cuisine
- date
- time
- party size
- Search results are built from
RestaurantLocationjoined withRestaurant - If a date is supplied, the backend can also return preview
availableTimesper location
GET /healthGET /restaurantsGET /restaurants/search?city=&date=&time=&party_size=GET /restaurants/{location_slug}GET /restaurants/locations/{location_id}/availability?date=YYYY-MM-DDPOST /auth/signupPOST /auth/login
POST /restaurants/locations/{location_id}/reservationsGET /me/reservationsDELETE /me/reservations/{reservation_id}
GET /admin/meGET /admin/locations/{location_id}/tablesPOST /admin/locations/{location_id}/availabilityGET /admin/locations/{location_id}/reservations?date=YYYY-MM-DD
- Node.js 20+
- npm 10+
- Python 3.11+
- PostgreSQL locally or Docker Desktop
cp .env.example .envImportant:
ADMIN_EMAILshould be a valid email address- if you change
.env, restart the backend - after schema updates, rerun migrations and the seed command
If you use Docker:
docker compose up -dIf you use a local PostgreSQL install instead:
- make sure PostgreSQL is running
- update
DATABASE_URLin.env
python3 -m venv .venv
.venv/bin/pip install -r backend/requirements.txt.venv/bin/alembic -c backend/alembic.ini upgrade headcd backend
../.venv/bin/python -m app.db.seed
cd ..The seed currently creates:
- restaurants
- two locations per restaurant
- location-specific tables
- location-specific availability slots
- real
price_rangevalues - real
ratingvalues - real location
address,website, andphonevalues
cd frontend
npm install
cd ..From the project root:
.venv/bin/uvicorn backend.app.main:app --reloadIn a second terminal:
cd frontend
npm run dev- Frontend: http://127.0.0.1:3000
- Backend: http://127.0.0.1:8000
- Health check: http://127.0.0.1:8000/health
- Sign up with any valid email + password
Set the same email in .env:
ADMIN_EMAIL=owner@example.comThen:
- restart the backend
- sign up or log in with that exact same email
The backend marks a user as admin when the login/signup email matches ADMIN_EMAIL.
The app currently enforces:
- passwords are hashed with Argon2
- protected routes require a valid JWT
- users can only access their own reservations
- one user can only book one reservation per restaurant location per day
- one availability slot can only be booked once
- admin routes require
is_admin = true
The current frontend includes:
- a reusable
Logocomponent - a shared top nav
- a shared footer
- a homepage hero search
- an editorial featured section
- a split-view restaurant browsing page
- a premium-style restaurant detail page
lsof -i :8000
kill -9 REAL_PID
.venv/bin/uvicorn backend.app.main:app --reloadcd frontend
rm -rf .next
npm run devYou need the latest migration:
.venv/bin/alembic -c backend/alembic.ini upgrade headYou added the newest restaurant fields but haven’t migrated yet:
.venv/bin/alembic -c backend/alembic.ini upgrade headThen reseed:
cd backend
../.venv/bin/python -m app.db.seed
cd ..Run the latest migrations first, then reseed:
.venv/bin/alembic -c backend/alembic.ini upgrade head
cd backend
../.venv/bin/python -m app.db.seed
cd ..- use a real email format such as
owner@example.com - password must be at least 8 characters
Check:
.envcontains the correctADMIN_EMAIL- backend was restarted after changing
.env - you logged in again with that same email
- replace
localStorageauth with HTTP-only cookies - add real search ranking and richer filtering
- store real popularity / editorial ranking instead of random homepage picks
- add true restaurant collections
- finish removing legacy brand-level inventory columns once location migration is complete
- add owner-managed restaurant and location records
- add profile management
- add password reset and email verification
- add testing coverage for search and booking flows
- move footer placeholder links to real pages
This project demonstrates:
- full-stack TypeScript/Python product work
- FastAPI + SQLAlchemy + PostgreSQL architecture
- JWT auth and protected route design
- reservation flow design and booking validation
- admin tooling
- iterative UI refinement in Next.js
- practical product thinking across frontend and backend