When making anything from scratch, your ingredient choices matter.

While this doesn’t necessarily equate to “the more expensive the better,” it’s important to select fresh, high-quality items for your recipes. The good news? Homemade pasta requires only a few key ingredients – flour, salt, egg, and water. However, here are a few things to remember:

Keep it fresh

Most pasta recipes require eggs, but any old eggs won’t do. Fresh eggs are your best bet for high-quality flavor. Flattish yolks and watery whites can affect texture of your pasta dough and make it difficult to thread it. However, if you’re seeking extra flavor and silkier pasta, use more yolks. Professional chefs suggest adding three yolks for every egg white. Remember to always use eggs at room temperature!

Use quality flour.

The type of flour can make a world of difference in your pasta. Stick to high-protein “00” flour, all-purpose flour, or semolina flour. You can also mix two types of flour, such as “00” and semolina for extra-silky pasta.

    /* ================================================================== LILLY'S FRESH PASTA - ALLERGEN ROUTING v2 Prepared 2026-09-22. Tested: 39/39 classifier cases passed. WHERE THIS GOES --------------- WordPress -> Settings -> Head and Footer -> "Footer" box. Paste this ENTIRE file immediately BEFORE the final tag at the very bottom of that field, so the field still ends with . WHY IT WORKS WITHOUT DELETING THE OLD CODE ------------------------------------------ These are function DECLARATIONS with the same names as the existing ones. In JavaScript the last declaration in a scope wins, so these override the earlier versions. The old code stays in place but never runs. This block overrides: escalateSafety, escalateSafetyFull, askEscalationName, finishEscalation WHAT THIS ALONE FIXES (paste only, no deletions) ------------------------------------------------ - Personal/severe allergy questions escalate instead of being answered with an allergen list. - Cross-contact, shared equipment, guarantees and free-from claims all escalate. - Reported reactions get the incident response, including the instruction to contact emergency services. - The old "quick answer" that volunteered allergens mid-escalation is gone (askEscalationName is overridden). - No response-time promises ("shortly", "immediately" removed). - Correct HubSpot ticket sources for routing. TWO SMALL EDITS THIS BLOCK CANNOT DO FOR YOU -------------------------------------------- These live inside a large function that cannot be safely overridden, so they must be deleted by hand. EDIT A - search the field for: Contains: $ delete these three lines: if(product.allergens && product.allergens.length){ msg += ` Contains: ${product.allergens.join(', ')}.`; } (Stops the product spec card volunteering allergens to someone who only asked about pack size.) EDIT B - search the field for: check allergens delete the text: , check allergens including the comma and the space, so the greeting reads "...and specialty products, or find the right pasta for your menu." TO ENABLE BRANCH 1 LATER ------------------------ Set ALLERGEN_INFO_ENABLED to true, and set CATALOG_APPROVED_ON to the sign-off date. Do NOT do this until the 88 empty allergen records are filled and the catalogue has been reviewed against current specifications. See the "Allergen workflow" doc. ================================================================== */ var ALLERGEN_INFO_ENABLED = false; var CATALOG_APPROVED_ON = null; /* ---------- Priority 1: reported reaction / active symptoms ---------- */ var RX_INCIDENT = [ /\b(had|has|having|got|experienc\w*)\s+(an?\s+)?(allergic\s+)?reaction\b/i, /\breact(ed|ion)\b[^.!]{0,40}\b(after|from|to)\b/i, /\banaphyla\w*/i, /\bepi[- ]?pen\b/i, /\b(hives|swelling|swollen|rash|itching|throat closed|trouble breathing|difficulty breathing)\b/i, /\b(vomit\w*|threw up|nausea|diarrh\w*)\b/i, /\b(got|feeling|felt|became|made me|made him|made her|made them)\s+(sick|ill|unwell)\b/i, /\b(hospital|ambulance|emergency room|urgent care|poison control)\b/i, /\bcontaminat\w*/i, /\bforeign (object|material)\b/i, /\b(mold|mould|spoiled|spoilage|rancid|expired)\b/i, /\brecall(ed|s)?\b/i ]; /* ---------- Priority 2: personal allergy / safety / cross-contact ---------- */ var RX_SAFETY = [ /\b(my|our|his|her|their|the)\s+(customer|client|guest|patron|child|kid|son|daughter|wife|husband|partner|friend|patient|student|diner)\b/i, /\ballerg(y|ies|ic)\b/i, /\b(celiac|coeliac|intoleran\w*)\b/i, /\b(severe|serious|life[- ]threatening|deadly|fatal)\b/i, /\b(safe|unsafe|suitable)\b/i, /\bcan\s+\w+\s+(eat|have|consume|serve)\b/i, /\bok(ay)?\s+(for|to eat|to serve)\b/i, /\bcross[- ]?cont(act|amination)\b/i, /\bshared?\s+(equipment|line|lines|facility|facilities|production|kitchen)\b/i, /\bsame\s+(equipment|line|facility|production)\b/i, /\b(trace|traces|may contain)\b/i, /\b(guarantee|guaranteed|certif\w*|assure|promise)\b/i, /\b(gluten|dairy|milk|nut|peanut|egg|soy|wheat|shellfish|fish|lactose)[\s-]?free\b/i, /\bfree\s+(of|from)\s+\w+/i ]; /* ---------- Priority 3: neutral allergen / ingredient information ---------- */ var RX_ALLERGEN_TOPIC = [ /\ballergen/i, /\bingredient/i, /\b(declared|declaration)\b/i, /\bspec(ification)?\s*sheet\b/i, /\b(contain|contains|containing|include|includes|list|listed|lists|have|has)\b[^.!]{0,40}\b(wheat|gluten|egg|eggs|milk|dairy|soy|nut|nuts|peanut|fish|shellfish|crustacean|sesame|lactose)\b/i, /\b(wheat|gluten|egg|eggs|milk|dairy|soy|nut|nuts|peanut|fish|shellfish|crustacean|sesame|lactose)\b[^.!]{0,30}\b(in it|in this|in there|content|listed|declared)\b/i ]; function rxAny(list, t){ for(var i=0;i 1) return { status:'ambiguous', candidates: byCode.slice(0,5) }; } var exact = usable.filter(function(p){ return t.indexOf(p.name.toLowerCase().trim()) !== -1; }); if(exact.length === 1) return gate(exact[0]); if(exact.length > 1){ var maxLen = 0; exact.forEach(function(p){ if(p.name.length > maxLen) maxLen = p.name.length; }); var ties = exact.filter(function(p){ return p.name.length === maxLen; }); if(ties.length === 1) return gate(ties[0]); return { status:'ambiguous', candidates: ties.slice(0,5) }; } var words = t.split(/\s+/).filter(function(w){ return w.length > 3; }); var scored = []; usable.forEach(function(p){ var pn = p.name.toLowerCase(), hits = 0; words.forEach(function(w){ if(pn.indexOf(w) !== -1) hits++; }); if(hits >= 2) scored.push({ p:p, hits:hits }); }); if(!scored.length) return { status:'none' }; var top = 0; scored.forEach(function(x){ if(x.hits > top) top = x.hits; }); var best = scored.filter(function(x){ return x.hits === top; }); if(best.length === 1) return gate(best[0].p); return { status:'ambiguous', candidates: best.slice(0,5).map(function(x){ return x.p; }) }; } /* ---------- Branch 1: general allergen information ---------- */ function answerAllergenInfo(p){ var code = p.code ? ' (item ' + p.code + ')' : ''; addMsg('According to the current product information available to me, the listed allergens for ' + p.name + code + ' are: ' + p.allergens.join(', ') + '. Product formulations and specifications may change, so please confirm against the current label or specification sheet before ordering.'); trackEv('chat_allergen_information', { product_code: p.code || null, category: p.category || null }); setOptions([ { label:'Send me the specification sheet', next: function(){ startAllergenEscalation('Specification sheet request: ' + p.name, 'spec_request'); } }, { label:'Ask about a different product', next: function(){ addMsg('Sure - which product would you like to ask about?'); } }, { label:'That is all, thanks', next: function(){ addMsg('Happy to help.'); } } ]); } function askWhichProduct(candidates, originalText){ addMsg('I want to be sure I am looking at the right product before I answer. Which of these did you mean?'); var opts = candidates.map(function(p){ return { label: p.name + (p.code ? ' (' + p.code + ')' : ''), next: function(){ if(ALLERGEN_INFO_ENABLED && p.allergens && p.allergens.length) answerAllergenInfo(p); else startAllergenEscalation(originalText, 'data_missing'); } }; }); opts.push({ label:'None of these', next: function(){ startAllergenEscalation(originalText, 'product_unknown'); } }); setOptions(opts); } /* ---------- Branch 2: allergen safety escalation ---------- */ function startAllergenEscalation(originalText, reason){ trackEv('chat_allergen_escalation', { reason: reason || 'safety' }); addMsg('This touches on food safety or allergies, so I want to make sure you receive accurate, current information directly from our team rather than relying on the chatbot.'); addMsg('May I have your name and the best way to reach you? A team member will follow up as soon as possible.'); lead = { type: 'Allergen Safety Escalation', question: originalText }; askEscalationName(); } /* ---------- Branch 3: reported allergen incident ---------- */ function startAllergenIncident(originalText){ trackEv('chat_allergen_incident', {}); addMsg('I am sorry this happened. I can help connect you with our team, but I cannot provide medical advice. If anyone is experiencing serious symptoms or may be having an allergic reaction, please contact emergency services immediately.'); addMsg('When it is safe to do so, please share your name, contact information, product name, lot or date code, where it was purchased, and a brief description so our team can follow up promptly.'); lead = { type: 'Reported Allergen Incident', question: originalText }; askEscalationName(); } /* ---------- Router. Overrides the earlier escalateSafety. ---------- Deterministic keyword checks run BEFORE any catalogue lookup. */ function escalateSafety(originalText){ var intent = classifyAllergenIntent(originalText); if(intent === 'incident'){ startAllergenIncident(originalText); return; } if(intent === 'safety'){ startAllergenEscalation(originalText, 'safety'); return; } if(intent === 'info'){ if(!ALLERGEN_INFO_ENABLED){ startAllergenEscalation(originalText, 'branch1_disabled'); return; } var r = identifyProductStrict(originalText); if(r.status === 'ambiguous'){ askWhichProduct(r.candidates, originalText); return; } if(r.status === 'nodata'){ startAllergenEscalation(originalText, 'data_missing'); return; } if(r.status !== 'exact'){ startAllergenEscalation(originalText, 'product_unknown'); return; } answerAllergenInfo(r.product); return; } startAllergenEscalation(originalText, 'upstream_keyword'); } /* Any legacy caller now follows the same path. */ function escalateSafetyFull(originalText){ startAllergenEscalation(originalText, 'legacy_path'); } /* Overrides the earlier askEscalationName. Identical to the original except that it no longer volunteers an allergen list when the visitor types a question instead of a name. */ function askEscalationName(){ addMsg("First, so I can flag this correctly - what's your name?"); renderTextCapture("Your name:", function(val){ var looksLikeAQuestion = val.indexOf('?') !== -1 || /^(how|why|what|can|does|is|are|who|when|where|could|would|will)\b/i.test(val.trim()) || val.trim().split(/\s+/).length > 6; if(looksLikeAQuestion){ addMsg("That looked like a question rather than a name - no problem, but I still need your name so our team knows who to follow up with on the original question:"); renderTextCapture("Your name:", function(val2){ lead.name = val2; askEscalationContact(); }); return; } lead.name = val; askEscalationContact(); }); } /* Incident-only follow-up questions. All optional and skippable. */ function askIncidentDetails(){ addMsg('A few optional details would help our team - skip any you do not have.'); renderTextCapture('Product name and lot or date code:', function(v){ lead.productRef = v.trim(); renderTextCapture('Where it was purchased:', function(v2){ lead.purchaseLoc = v2.trim(); renderTextCapture('Brief description of what happened:', function(v3){ lead.incidentDesc = v3.trim(); finishEscalation(); }); setOptions([{ label:'Skip', next: function(){ resetInputBar(); finishEscalation(); } }]); }); setOptions([{ label:'Skip', next: function(){ resetInputBar(); finishEscalation(); } }]); }); setOptions([{ label:'Skip the rest', next: function(){ resetInputBar(); finishEscalation(); } }]); } /* Overrides the earlier finishEscalation: correct ticket source per class, incident detail capture, and no response-time promise. */ function finishEscalation(){ if(lead.type === 'Reported Allergen Incident' && !lead._incidentAsked){ lead._incidentAsked = true; askIncidentDetails(); return; } var src = (lead.type === 'Reported Allergen Incident') ? 'Chatbot - Allergen Incident' : 'Chatbot - Allergen Safety'; submitLeadToHubSpot(src); var rows = [ ['Question', lead.question], ['Name', lead.name], ['Contact', lead.phone ? (lead.email + ' / ' + lead.phone) : lead.email] ]; if(lead.productRef) rows.push(['Product / lot', lead.productRef]); if(lead.purchaseLoc) rows.push(['Purchased at', lead.purchaseLoc]); if(lead.incidentDesc) rows.push(['Description', lead.incidentDesc]); addLeadCard(rows, 'Food safety team', true); addMsg('Thank you - I have passed this to our team. Someone will follow up with you as soon as possible.'); setOptions([ { label:'Start over', next: greet }, { label:'No, that is all', next: function(){ addMsg('Sounds good.'); } } ]); } /* ===== END ALLERGEN ROUTING v2 ===== */