The HWP

Table of contents
The Hungry for Waffles Problem
Background
I’ve been in Mississippi a lot lately (I grew up there), and it reminded me that the Waffle House (WH) density on the MS Gulf Coast is markedly superior to that of the Austin, Texas area where I am typing this. WH is slowly building up their presence here, but there’s still room for improvement.
Anyway, I thought I’d use this as an excuse to come up with a more relatable version of the Traveling Salesman Problem. Let’s call it the Hungry for Waffles Problem (HWP).
Technical
Waffle House location data
Let’s see if there’s a simple way to get a list of WHs. Their site has a FIND A STORE link that takes you to https://locations.wafflehouse.com
It turns out the response to the root URL contains all the info I care about. There’s a script tag with store data JSON. Here’s an excerpt
<script id="__NEXT_DATA__" type="application/json">
{
"props": {
"pageProps": {
"lng": "",
"frontPage": true,
"locations": [
{
"storeCode": "100",
"businessName": "Waffle House #100",
"addressLines": [
"2842 PANOLA RD"
],
"city": "LITHONIA",
"state": "GA",
"country": "US",
"custom": {
"operated_by": "WAFFLE HOUSE, INC",
"online_order_link": "https://order.wafflehouse.com/menu/waffle-house-100"
},
"postalCode": "30058",
"latitude": 33.704706,
"longitude": -84.169849,
"phoneNumbers": [
"(770) 981-1914"
],
"websiteURL": "https://locations.wafflehouse.com///lithonia-ga-100",
"businessHours": [
[
"00:00",
"00:00"
],
[
"00:00",
"00:00"
],
[
"00:00",
"00:00"
],
[
"00:00",
"00:00"
],
[
"00:00",
"00:00"
],
[
"00:00",
"00:00"
],
[
"00:00",
"00:00"
]
],
"specialHours": null,
"formattedBusinessHours": [
"Monday - Sunday| 24 hours"
],
"slug": "lithonia-ga-100",
"localPageUrl": "/lithonia-ga-100",
"_status": "A"
},
...
Save it locally, rip out what we need, and put it in a CSV file.
% curl -s https://locations.wafflehouse.com/ > locations_wafflehouse.html
% sed -n '/<script id="__NEXT_DATA__" type="application\/json">/,/<\/script>/ { s/<script id="__NEXT_DATA__" type="application\/json">//; s/<\/script>//; p; }' locations_wafflehouse.html > wafflehouse.json
% sed 's/<\/body><\/html>//' wafflehouse.json > wafflehouse2.json
% jq -r '.props.pageProps.locations[] | [.storeCode, .businessName, .addressLines[0], .city, .state, .postalCode, .latitude, .longitude] | @csv' wafflehouse2.json > wafflehouse_locations.csv
% head wafflehouse_locations.csv
"100","Waffle House #100","2842 PANOLA RD","LITHONIA","GA","30058",33.704706,-84.169849
"1000","Waffle House #1000","2850 E COLLEGE AVE","DECATUR","GA","30030",33.775215,-84.273744
"1001","Waffle House #1001","12923 SHELBYVILLE RD","LOUISVILLE","KY","40243",38.243594,-85.513206
"1002","Waffle House #1002","1161 RAMBLING OAKS DR","NORMAN","OK","73072",35.232444,-97.489044
"1003","Waffle House #1003","1002 HWY 90","BAY SAINT LOUIS","MS","39520",30.313246,-89.356576
"1004","Waffle House #1004","1900 COMMERCE ST","CULLMAN","AL","35055",34.205996,-86.875404
"1005","Waffle House #1005","15228 US HIGHWAY 19 S","THOMASVILLE","GA","31757",30.857419,-83.946469
"1006","Waffle House #1006","6840 EAST FRONT ST","KANSAS CITY","MO","64120",39.1301810758,-94.5017801864336
"1007","Waffle House #1007","3735 ROSWELL RD","ATLANTA","GA","30342",33.857012,-84.38203
"1008","Waffle House #1008","8994 UNIVERSITY BLVD","NORTH CHARLESTON","SC","29406",32.976556,-80.06627
Database time
I think I’ve used up my free tier allotment on Supabase. Let’s use Neon for this.
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE TABLE IF NOT EXISTS waffle_houses (
id SERIAL PRIMARY KEY,
store_code VARCHAR(10),
business_name VARCHAR(100),
address TEXT,
city VARCHAR(50),
state VARCHAR(2),
postal_code VARCHAR(10),
latitude FLOAT,
longitude FLOAT,
geom GEOMETRY(POINT, 4326)
);
Load the CSV
% psql 'postgresql://neondb_owner:****@ep-blue-credit-aesgjhbz-pooler.c-2.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require' -c "\copy waffle_houses (store_code, business_name, address, city, state, postal_code, latitude, longitude) FROM 'wafflehouse_locations.csv' WITH (FORMAT CSV, HEADER);"
COPY 2037
% psql 'postgresql://neondb_owner:****@ep-blue-credit-aesgjhbz-pooler.c-2.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require' -c "SELECT * FROM waffle_houses LIMIT 1;"
id | store_code | business_name | address | city | state | postal_code | latitude | longitude | geom
----+------------+--------------------+--------------------+---------+-------+-------------+-----------+------------+------
1 | 1000 | Waffle House #1000 | 2850 E COLLEGE AVE | DECATUR | GA | 30030 | 33.775215 | -84.273744 |
(1 row)
Add some info for PostGIS
UPDATE waffle_houses SET geom = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326);
% psql 'postgresql://neondb_owner:****@ep-blue-credit-aesgjhbz-pooler.c-2.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require' -c "SELECT * FROM waffle_houses LIMIT 1;"
id | store_code | business_name | address | city | state | postal_code | latitude | longitude | geom
----+------------+--------------------+--------------------+---------+-------+-------------+-----------+------------+----------------------------------------------------
1 | 1000 | Waffle House #1000 | 2850 E COLLEGE AVE | DECATUR | GA | 30030 | 33.775215 | -84.273744 | 0101000020E61000007ADE8D05851155C0302FC03E3AE34040
(1 row)
App time
The initial feature for the app is, given a location (either current or provided), locate Waffle Houses within the configured radius. From there use openrouteservice’s optimization API to determine the best path between them. Finally, display the route on the map as well as list the stores along the route.
I scaffolded a Vite + React + Typescript app, and turned Cursor loose on it.
% npm create vite@latest hungry-for-waffles -- --template react-ts
Need to install the following packages:
create-vite@7.0.3
Ok to proceed? (y)
npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE package: 'create-vite@7.0.3',
npm warn EBADENGINE required: { node: '^20.19.0 || >=22.12.0' },
npm warn EBADENGINE current: { node: 'v20.16.0', npm: '10.8.1' }
npm warn EBADENGINE }
> npx
> create-vite hungry-for-waffles --template react-ts
│
◇ Scaffolding project in /Volumes/ExternalSSD/Developer/fun/hungry-for-waffles...
│
└ Done. Now run:
cd hungry-for-waffles
npm install
npm run dev
Here’s what it looks like right now.
Repo https://github.com/ThatOrJohn/hungry-for-waffles
And the live magic https://hungry-for-waffles.vercel.app/
Subscribe to my newsletter
Read articles from John Walley directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
