Alex Pizza Assistant is organized as a minimal static site with no build tooling — every file is served directly by the browser or a static host. There is no bundler, no framework, no package manager, and no compilation step. The HTML, CSS, JavaScript, and JSON files are all standalone and reference each other by relative URL, which means the project can be opened from the filesystem or dropped onto any static hosting service with zero configuration.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/alex-pizza-assistant/llms.txt
Use this file to discover all available pages before exploring further.
File Structure
index.html
index.html is the single interactive page. It is structured in three regions: a sticky pizzeria header, a two-column main layout, and a footer.
Header (<header class="pizzeria-bar">) — displays the Alex Pizza Assistant brand mark with a 🍕 icon badge and a navigation bar linking to the Case Study, Article, and Source Map pages.
Main layout (<main id="pizzaApp" class="order-layout">) — a CSS Grid container with two columns:
- Chat window (
<section class="chat-window">) — contains the scrollable message feed, the step counter/status badge, the question label, the text input, the Continue button, and the inline validation message. - Receipt panel (
<aside class="receipt-panel">) — contains a live receipt card that updates after each answer and a static menu-logic summary card.
<footer class="pizzeria-footer">) — copyright notice and secondary navigation links.
Key element IDs
app.js queries the DOM by ID on startup and throughout the ordering flow. Every ID below must be present in index.html for the chatbot to work correctly.
| ID | Element | Purpose |
|---|---|---|
#chatFeed | <div> | Scrollable container where bot and user chat bubbles are appended |
#chatForm | <form> | Wraps the input field and Continue button; submit event drives the order flow |
#chatInput | <input type="text"> | Customer text entry field |
#questionLabel | <label> | Displays the current step prompt above the input |
#validationMessage | <p role="alert"> | Displays inline validation errors without a page reload |
#orderStatus | <span> | Shows “Step N of 12” progress or “Complete” when the order is finished |
#newOrder | <button> | Triggers resetOrder() to wipe state and restart the conversation |
#rName | <dd> | Receipt: customer name |
#rMethod | <dd> | Receipt: carry out or delivery |
#rPayment | <dd> | Receipt: payment method string |
#rSubtotal | <dd> | Receipt: order subtotal |
#rTax | <dd> | Receipt: calculated sales tax |
#rDeliveryFee | <dd> | Receipt: delivery fee (zero for carry-out orders) |
#rTip | <dd> | Receipt: driver tip amount |
#rTotal | <strong> | Receipt: grand total |
#rItems | <div> | Receipt: dynamically generated pizza item cards |
js/app.js
app.js is the entire application. It declares global state, the ordered steps array, DOM references, event listeners, and all functions. There are no imports or external dependencies.
| Function | Purpose |
|---|---|
handleSubmit(event) | Form submit handler — validates raw input against the current step, prevents default, dispatches to save/respond/advance pipeline |
saveAnswer(id, value) | Persists a validated, normalized answer to the order state object or the currentPizza sub-object |
respondToAnswer(id, value) | Emits contextual bot reply bubbles after an answer is saved (e.g., greeting by name, pizza confirmation, payment confirmation) |
advanceStep(id, value) | Calculates the next step index with full branching logic — handles the add-another loop, carry-out vs. delivery fork, cash vs. card fork, and tip step for delivery |
normalizeValue(id, value) | Coerces raw user input to a canonical form before saving (e.g., lowercases size, collapses “pickup”/“carryout” to “carry out”, converts quantity to Number) |
showCurrentStep() | Updates #questionLabel text, clears and focuses #chatInput, and refreshes the #orderStatus step counter |
finishOrder() | Disables the form, emits the total bubble and coupon message, triggers the ETA animation sequence, and updates the receipt one final time |
runFastEta() | Dispatches a series of timed setTimeout calls that append ETA countdown bot bubbles (3 min → 2 min → 1 min → ready) at 450 ms intervals |
resetOrder() | Wipes all state back to defaults with Object.assign, resets currentStep to 0, clears #chatFeed, re-enables the form, and restarts the greeting |
createBlankPizza() | Returns a fresh { size, toppings, crustType, quantity } object used as the template for each new pizza in a multi-pizza order |
addCurrentPizzaToOrder() | Shallow-copies order.currentPizza and pushes it onto order.pizzas[] when the quantity step is confirmed |
calculateTotals() | Recomputes order.subtotal, order.tax, order.deliveryFee, and order.total from the current order.pizzas[], TAX_RATE, DELIVERY_FEE, and order.tip |
updateReceipt() | Syncs every receipt DOM element (#rName, #rSubtotal, #rItems, etc.) with the current order state |
getPizzaSummary() | Builds and returns an HTML string of <div class="receipt-item"> cards — one per pizza — for injection into #rItems |
getPaymentLabel() | Formats the payment method display string (e.g., “card ending in 4242” or “cash”) |
addBubble(text, type) | Creates a <div class="bubble {type}"> element, sets its text content, appends it to #chatFeed, and scrolls the feed to the bottom |
isValidMoney(value) | Regex validator (/^\$?\d+(\.\d{1,2})?$/) used by the tip step to accept amounts like 3, 3.50, $5, or 0 |
getStepIndex(id) | Finds and returns the index of a step in the steps array by its id string — used by advanceStep for non-sequential jumps |
formatMoney(value) | Formats a number as a USD string using toLocaleString with exactly two decimal places (e.g., $14.99) |
The
steps array at the top of app.js is the single source of truth for order flow. Each entry declares an id, a label (shown in #questionLabel), a validate function, and an error string. Adding, removing, or reordering steps here controls the entire conversation sequence.data/menu.json
menu.json stores configurable display values: pizza prices, the sales tax multiplier, the delivery fee, and the coupon threshold. The file is not fetched at runtime — its values are mirrored as constants at the top of app.js. Update both locations when changing any pricing value.
Configuration reference
Full field-by-field documentation for every property in menu.json and the matching app.js constants.
css/styles.css
styles.css owns all visual presentation. It is organized into four layers:
-
CSS custom properties — nine named color tokens on
:root(--oven-black,--deep-red,--tomato,--cheese,--cream,--flour,--basil,--ink,--muted) plus utility shadow values. All component colors reference these tokens. -
Layout classes —
pizzeria-bar(header),order-layout(two-column CSS Grid),chat-window(left column), andreceipt-panel(right column). The grid collapses to a single column at 900 px via a media query. -
Component classes —
bubble bot,bubble user, andbubble resultstyle the three chat bubble variants;receipt-paper,receipt-item,receipt-totals, andtotal-rowstyle the live receipt card;menu-cardstyles the static pricing summary;chat-entrystyles the input form area. -
Article/case-study classes —
article-pageandarticle-cardstyle the prose pages (article.html,case-study.html,source-map.html) with the same border-radius and box-shadow design language as the main app.
Original Python Source
Alex Pizza Assistant is a browser adaptation of a Python console chatbot originally written for a CIS110 course assignment (CIS110 Pizza Ordering Chatbot). The original Python project included:CIS110_Pizza_Ordering_Chatbot.py— the main console ordering scriptCIS110 Pizza Ordering Chatbot.pyproj— Visual Studio project fileCIS110 Pizza Ordering Chatbot.sln— Visual Studio solution file
docs/source-map.md but are not included in this repository. The browser version preserves all original logic (name prompt, size/topping/crust/quantity validation, multi-pizza loop, carry-out/delivery branch, cash/card checkout, simulated card flow, tip prompt, delivery fee, sales tax, coupon threshold, and reset behavior) while replacing Python’s input()/print() console I/O with a DOM-based chat interface.