setup()
setup() runs once at the start of the sketch. Here, we build the entire chat UI using p5.js's HTML creation functions (createDiv, createInput, createButton) and CSS styling. Notice how .parent() connects elements to containers, creating a hierarchy. The keypressListener is stored in a variable so we can remove it later when the dark screen easter egg triggers—this teaches you that event listeners must be managed carefully.
function setup() {
noCanvas();
// --- Create Main Flex Container ---
mainContainer = createDiv();
mainContainer.style("display", "flex");
mainContainer.style("flex-direction", "column");
mainContainer.style("height", "100vh"); // Make it full height
// --- Create the Title Element ---
titleElement = createElement('h1', 'POTATO AI 1.0🥔'); // Updated title to potato theme
titleElement.style("text-align", "center");
titleElement.style("padding", "10px");
titleElement.style("margin", "0");
titleElement.style("background-color", "#f8f8f8");
titleElement.style("border-bottom", "1px solid #ddd");
titleElement.parent(mainContainer);
chatContainer = createDiv();
chatContainer.style("flex-grow", "1"); // Make chatContainer fill available space
chatContainer.style("overflow-y", "auto");
chatContainer.style("padding", "10px");
chatContainer.style("display", "flex");
chatContainer.style("flex-direction", "column");
chatContainer.parent(mainContainer); // Parent to mainContainer
inputArea = createDiv(); // Declared globally
inputArea.style("display", "flex");
inputArea.style("padding", "10px");
inputArea.style("background-color", "#f0f0f0");
inputArea.parent(mainContainer); // Parent to mainContainer
inputBox = createInput();
inputBox.style("flex", "1");
inputBox.style("padding", "10px");
inputBox.style("font-size", "16px");
inputBox.parent(inputArea);
sendButton = createButton("Send");
sendButton.style("padding", "10px 20px");
sendButton.style("margin-left", "5px");
sendButton.parent(inputArea);
sendButton.mousePressed(sendMessage);
// Store the listener function
keypressListener = function(e) {
if (e.key === "Enter") sendMessage();
};
inputBox.elt.addEventListener("keypress", keypressListener);
// --- Add the Exit Button ---
let exitButton = createButton('X');
exitButton.style('position', 'fixed');
exitButton.style('top', '10px');
exitButton.style('right', '10px');
exitButton.style('padding', '10px 15px');
exitButton.style('font-size', '18px');
exitButton.style('background-color', '#ff0000'); // Red for exit
exitButton.style('color', 'white');
exitButton.style('border', 'none');
exitButton.style('border-radius', '5px');
exitButton.style('cursor', 'pointer');
exitButton.style('z-index', '1000'); // Ensure it's on top of other elements
exitButton.mousePressed(() => {
window.open('https://www.canva.com/design/DAHBhUmxxCY/xn8SvJ7_G7hOoDC68lXviw/view', '_blank'); // Open in a new tab
});
}
Line-by-line explanation (16 lines)
🔧 Subcomponents:
noCanvas();
Tells p5.js not to create a drawing canvas—this sketch uses HTML elements instead
mainContainer = createDiv();
mainContainer.style("display", "flex");
mainContainer.style("flex-direction", "column");
mainContainer.style("height", "100vh");
Creates the outermost container that stacks the title, chat area, and input field vertically and fills the entire viewport
keypressListener = function(e) {
if (e.key === "Enter") sendMessage();
};
inputBox.elt.addEventListener("keypress", keypressListener);
Allows users to press Enter to send a message instead of clicking the button; stores the listener function so it can be removed later
exitButton.mousePressed(() => {
window.open('https://www.canva.com/design/DAHBhUmxxCY/xn8SvJ7_G7hOoDC68lXviw/view', '_blank'); // Open in a new tab
});
Creates a fixed red X button that opens an external link when clicked
noCanvas();- Tells p5.js to skip creating a canvas—this sketch is purely HTML-based, so we don't need to draw pixels
mainContainer = createDiv();- Creates a new HTML div element that will hold all other UI elements
mainContainer.style("display", "flex");- Enables flexbox layout on the main container so child elements stack and align easily
mainContainer.style("flex-direction", "column");- Stacks child elements vertically (column) instead of side-by-side
mainContainer.style("height", "100vh");- Sets the container height to 100% of the viewport, making it fill the entire screen
titleElement = createElement('h1', 'POTATO AI 1.0🥔');- Creates an h1 heading element with the title text; createElement() is a p5.js function to make HTML tags
titleElement.parent(mainContainer);- Adds the title as a child of mainContainer—it will appear inside and be organized by the flex layout
chatContainer.style("flex-grow", "1");- Tells the chat container to expand and fill all available vertical space between the title and input area
chatContainer.style("overflow-y", "auto");- Allows the chat area to scroll vertically if there are many messages, preventing content overflow
inputBox = createInput();- Creates an HTML text input field where users can type their messages
inputBox.style("flex", "1");- Tells the input field to expand horizontally and take up all available space in the input area
sendButton = createButton("Send");- Creates a clickable button labeled 'Send'
sendButton.mousePressed(sendMessage);- Connects the button to the sendMessage() function—when clicked, sendMessage runs
keypressListener = function(e) { if (e.key === "Enter") sendMessage(); };- Defines a function that listens for keyboard events and calls sendMessage() if the Enter key is pressed; storing it in a variable lets us remove it later if needed
inputBox.elt.addEventListener("keypress", keypressListener);- Attaches the keypressListener to the input field so pressing Enter while typing will send the message
exitButton.style('z-index', '1000');- Sets a very high z-index (stacking order) so the exit button always appears on top of other elements like the dark screen GIF