Every order rides a caravan

Pick your town.
Pick a caravan. Eat.

We stopped pretending small-town delivery works like city delivery. Every run is scheduled. Every neighbor joining your caravan drops your fee by a buck-fifty. First ride out: $2 off automatically.

How are we delivering?
Step 1

Which town?

Tell us what you want.
Loading restaurants…
The driver will read this aloud to the cashier. Be specific.
The driver will use this for turn-by-turn navigation.
📷
Tap to take or upload
Stand at your porch, point at the road. Show the driveway or sidewalk.
Complexity goes 100% to the driver as a tip. We never take a cut of it.

You're aboard.

Drop your fee more

Every neighbor who joins your caravan saves everyone $1.50. Share this link — if two friends book, you all pay less.

We'll text you when your driver is heading out, and again when they pull up.
Already in Amarillo?
Order Domino's with ink — skip the caravan.
Metro carryout/delivery via Domino's API. Small-town runs still use caravans below.
🍕 Domino's × Ink
+((book.total_fee_cents||0)/100).toFixed(2)+' →'}else{payBtn.style.display='none'}} document.getElementById('success-panel').classList.add('active'); document.getElementById('success-panel').scrollIntoView({behavior:'smooth',block:'start'}); } function shareInvite(){ const url=`${window.location.origin}/aeats?caravan=${window.inviteCaravanId}`; const text=`Joining a ${state.zone} food caravan from Amarillo. If you hop in too, we both save $1.50. Grab a seat:`; if(navigator.share){navigator.share({title:'Aeats caravan',text,url})} else{navigator.clipboard.writeText(`${text} ${url}`).then(()=>alert('Invite link copied!'))} } window.toggleFlexMode=function(){ const form=document.getElementById("flex-form-section"); const board=document.getElementById("caravan-section"); const flexOpt=document.getElementById("flex-option-section"); const showFlex=form.style.display==="none"; form.style.display=showFlex?"block":"none"; board.style.display=showFlex?"none":"block"; flexOpt.style.display=showFlex?"none":"block"; document.getElementById("flex-zone-name").textContent=state.zone||""; if(showFlex){renderFlexMerchants();setDefaultFlexTimes();form.scrollIntoView({behavior:"smooth"})} }; function renderFlexMerchants(){ document.getElementById("flex-merchant-grid").innerHTML=state.merchants.map(m=> `
${m.icon_emoji||"🍽️"}
${m.name}
${m.cuisine_type||""}
` ).join(""); } window.pickFlexMerchant=function(id){ state.flexMerchant=state.merchants.find(m=>m.id===id); document.querySelectorAll("#flex-merchant-grid .mcard").forEach(c=>c.classList.toggle("active",c.dataset.id===id)); validateFlex(); }; function setDefaultFlexTimes(){ const now=new Date();const pad=n=>String(n).padStart(2,"0"); const start=new Date(now.getTime()+2*3600*1000); const end=new Date(now.getTime()+6*3600*1000); const fmt=d=>`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; document.getElementById("ff-start").value=fmt(start); document.getElementById("ff-end").value=fmt(end); } function validateFlex(){ const ready=state.flexMerchant&& document.getElementById("ff-name").value.trim().length>1&& document.getElementById("ff-phone").value.replace(/\\D/g,"").length>=10&& document.getElementById("ff-address").value.trim().length>5&& document.getElementById("ff-order").value.trim().length>3; document.getElementById("flex-btn").disabled=!ready; } document.addEventListener("input",e=>{if(e.target.id&&e.target.id.startsWith("ff-"))validateFlex()}); window.submitFlex=async function(){ const btn=document.getElementById("flex-btn"); btn.disabled=true;btn.textContent="Submitting…"; const r=await rpc("book_flex_order",{ p_requester_name:document.getElementById("ff-name").value, p_requester_phone:document.getElementById("ff-phone").value, p_requester_email:document.getElementById("ff-email").value, p_delivery_address:document.getElementById("ff-address").value, p_zone:state.zone, p_merchant_id:state.flexMerchant.id, p_merchant_name:state.flexMerchant.name, p_order_description:document.getElementById("ff-order").value, p_window_start:new Date(document.getElementById("ff-start").value).toISOString(), p_window_end:new Date(document.getElementById("ff-end").value).toISOString() }); if(!r.ok){alert("Booking failed: "+(r.error||"try again"));btn.disabled=false;btn.textContent="Submit flex order";return} document.getElementById("flex-form-section").style.display="none"; document.getElementById("caravan-section").style.display="none"; document.getElementById("flex-option-section").style.display="none"; document.getElementById("success-panel").classList.add("active"); if(book&&book.run_id&&typeof attachPhotoEvalToRun==="function")await attachPhotoEvalToRun(book.run_id); if(book&&book.run_id&&typeof redirectToStripeCheckout==="function"){const went=await redirectToStripeCheckout(book.run_id);if(went)return} document.getElementById("success-summary").innerHTML=`Flex order placed for ${state.zone}. Starting fee: $${(r.starting_fee_cents/100).toFixed(2)} — auto-drops as neighbors book in your window.`; document.getElementById("success-stats").innerHTML=`
Starting fee$${(r.starting_fee_cents/100).toFixed(2)}
Already saving vs solo−$${((r.solo_fee_would_be-r.starting_fee_cents)/100).toFixed(2)}
We will text you the final fee once your caravan seals.
`; document.getElementById("success-panel").scrollIntoView({behavior:"smooth"}); }; const _origPickZone=pickZone; window.pickZone=async function(zone){await _origPickZone(zone);document.getElementById("flex-option-section").style.display="block"}; // ========= STRIPE CHECKOUT (uses existing checkout edge function) ========= async function redirectToStripeCheckout(runId){ try{ // First: check if this customer's phone is on a jobsite tab const phoneInput=document.getElementById("f-phone")||document.querySelector("input[name=phone]")||document.querySelector("#phone")||document.querySelector("input[type=tel]"); const phone=phoneInput?phoneInput.value:""; if(phone&&phone.replace(/\D/g,"").length>=10){ const access=await rpc("check_jobsite_access",{p_phone:phone}); if(access&&access.eligible&&access.within_caps){ const p=await rpc("build_caravan_checkout_params",{p_run_id:runId}); const amt=p.amount_cents||0; if(amt<=access.remaining_today_cents&&(access.billing_mode==="company_tab"||access.prepaid_balance_cents>=amt)){ const ch=await rpc("charge_jobsite_for_run",{ p_run_id:runId,p_jobsite_id:access.jobsite_id, p_worker_id:access.worker_id,p_amount_cents:amt }); if(ch&&ch.ok){ alert("Billed to "+access.company+" jobsite tab ("+access.jobsite_name+"). $"+(amt/100).toFixed(2)+" charged."); window.location.href="/paid?run="+runId+"&jobsite=1"; return true; } }else{ alert("Daily cap exceeded ($"+(access.remaining_today_cents/100).toFixed(0)+" remaining today). You can pay this one yourself."); } } } const p=await rpc("build_caravan_checkout_params",{p_run_id:runId}); if(!p.ok||!p.amount_cents){return false} const r=await fetch(`${SB}/functions/v1/checkout`,{ method:"POST", headers:{"apikey":KEY,"Authorization":"Bearer "+KEY,"Content-Type":"application/json"}, body:JSON.stringify(p) }); const d=await r.json(); if(d&&(d.url||d.checkout_url)){window.location.href=d.url||d.checkout_url;return true} if(d&&d.session_id){window.location.href=`https://checkout.stripe.com/c/pay/${d.session_id}`;return true} }catch(e){console.warn("stripe checkout failed",e)} return false; } window.redirectToStripeCheckout=redirectToStripeCheckout; // ========= PHOTO AI EVAL (scrap reuse, eval every upload) ========= window.lookupLastPhoto=async function(){/* reuse scrapped — every delivery gets fresh photo + eval */}; window.useExistingPhoto=function(){}; async function evaluatePhotoAI(photoUrl){ const notes=document.getElementById("f-notes")?.value||""; try{ const r=await fetch(`${SB}/functions/v1/daisy-vision/evaluate-reference`,{ method:"POST", headers:{"apikey":KEY,"Authorization":"Bearer "+KEY,"Content-Type":"application/json"}, body:JSON.stringify({photo_url:photoUrl,notes}) }); return await r.json(); }catch(e){console.warn("eval failed",e);return{ok:false,error:String(e)}} } function renderPhotoEval(ev){ if(!ev||!ev.ok){return} const e=ev.eval||{}; const surcharge=ev.surcharge_cents||0; const tier=ev.tier||"unknown"; const msg=ev.message||""; const haz=(e.hazards||[]); const color=(tier==="excellent"||tier==="good")?"#10b981":(tier==="fair")?"#e4a547":"#d86a5f"; let slot=document.getElementById("photo-eval-slot"); if(!slot){ slot=document.createElement("div");slot.id="photo-eval-slot";slot.style.cssText="margin-top:12px"; const photoBox=document.getElementById("photo-box"); if(photoBox&&photoBox.parentElement)photoBox.parentElement.appendChild(slot); } slot.innerHTML=`
${tier} photo
${surcharge>0?`+$${(surcharge/100).toFixed(2)} hazard fee`:"no surcharge"}
${msg?`
${msg}
`:""} ${haz.length?`
Hazards spotted${haz.map(h=>`• ${h.type.replace(/_/g," ")} (${h.severity}) — ${h.desc}`).join("
")}
`:""} ${e.recommended_action?`
→ ${e.recommended_action}
`:""} ${surcharge>100?``:""}
`; state.photoEval=ev; if(typeof updateFees==="function")updateFees(); } window.retakePhoto=function(){ state.photoFile=null;state.photoUrl=null;state.photoEval=null; const slot=document.getElementById("photo-eval-slot");if(slot)slot.remove(); const box=document.getElementById("photo-box"); if(box){box.innerHTML=`
📷
Tap to take or upload
Daylight. Step back. Show the full porch and any obstacles.
`;box.classList.remove("has-photo")} const actions=document.getElementById("photo-actions");if(actions)actions.style.display="none"; const input=document.getElementById("f-photo");if(input){input.value="";input.click()} }; // Wrap uploadPhoto to auto-eval const _origUploadPhotoForAI=window.uploadPhoto; if(_origUploadPhotoForAI){ window.uploadPhoto=async function(){ const up=await _origUploadPhotoForAI(); if(up&&up.url){ state.photoUrl=up.url; // persist so attach can read // Show evaluating message let slot=document.getElementById("photo-eval-slot"); if(!slot){slot=document.createElement("div");slot.id="photo-eval-slot";slot.style.cssText="margin-top:12px";document.getElementById("photo-box")?.parentElement?.appendChild(slot)} slot.innerHTML=`
🔍 Evaluating photo quality…
`; const ev=await evaluatePhotoAI(up.url); renderPhotoEval(ev); } return up; }; } // Hook after any successful booking to attach photo eval to the run async function attachPhotoEvalToRun(runId){ if(!runId||!state.photoEval||!state.photoEval.eval)return; const e=state.photoEval.eval; try{ await rpc("attach_photo_eval_to_run",{ p_run_id:runId, p_photo_url:state.photoUrl||(state.photoFile?null:null), p_photo_notes:document.getElementById("f-notes")?.value||null, p_quality:e.quality_score,p_safety:e.safety_score, p_lighting:e.lighting,p_clarity:e.clarity,p_coverage:e.coverage, p_hazards:e.hazards||[],p_description:e.description, p_recommended_action:e.recommended_action, p_model:state.photoEval.model||"claude-opus-4-7" }); }catch(err){console.warn("attach eval failed",err)} } window.attachPhotoEvalToRun=attachPhotoEvalToRun; // ========= MODE HANDLING: crew / pin / zone ========= window._mode=null;window._pinLat=null;window._pinLng=null;window._pinZoneInfo=null;window._crewJobsite=null; window.modeZone=function(){document.getElementById("mode-picker").style.display="none";window._mode="zone";document.getElementById("zones")?.closest("section")?.scrollIntoView({behavior:"smooth"})}; window.modePin=function(){document.getElementById("mode-picker").style.display="none";document.getElementById("pin-picker-screen").style.display="block";window._mode="pin";setTimeout(initPinMap,100);document.getElementById("pin-picker-screen").scrollIntoView({behavior:"smooth"})}; window.modeCrewPrompt=function(){ const code=prompt("Enter your 6-letter crew code:"); if(!code)return; const clean=code.trim().toUpperCase(); rpc("get_jobsite_by_code",{p_code:clean}).then(r=>{ if(!r.ok){alert(r.error||"invalid code");return} window._crewJobsite=r;window._mode="crew"; document.getElementById("mode-picker").style.display="none"; document.getElementById("mode-banner").style.display="block"; document.getElementById("mode-title").innerHTML=`Ordering to ${r.name}`; document.getElementById("mode-sub").textContent=`${r.nearest_zone} · crew code ${clean} · ${r.total_orders||0} orders all-time`; // Set zone to jobsite's nearest zone and auto-trigger zone pick if(typeof pickZone==="function"){state.zone=r.nearest_zone;pickZone(r.nearest_zone)} }); }; window.exitMode=function(){ window._mode=null;window._crewJobsite=null;window._pinLat=null;window._pinLng=null; document.getElementById("mode-banner").style.display="none"; document.getElementById("pin-picker-screen").style.display="none"; document.getElementById("mode-picker").style.display="block"; document.getElementById("caravan-section")&&(document.getElementById("caravan-section").style.display="none"); window.scrollTo({top:0,behavior:"smooth"}); }; // GPS PIN MAP let _pinMap,_pinMarker; function initPinMap(){ if(_pinMap){_pinMap.invalidateSize();return} _pinMap=L.map("pin-picker-map",{zoomControl:true,scrollWheelZoom:false}).setView([35.16,-101.45],8); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{attribution:"© OSM",maxZoom:18}).addTo(_pinMap); _pinMap.on("click",(e)=>setPin(e.latlng.lat,e.latlng.lng)); // Show Amarillo hub L.circleMarker([35.22,-101.83],{radius:8,fillColor:"#6da4e4",color:"#f4efe4",weight:2,fillOpacity:0.7}).addTo(_pinMap).bindTooltip("Amarillo pickup"); } window.usePinLocation=function(){ if(!navigator.geolocation){alert("Geolocation not available");return} navigator.geolocation.getCurrentPosition( (pos)=>setPin(pos.coords.latitude,pos.coords.longitude), (err)=>alert("Could not get location: "+err.message), {enableHighAccuracy:true,timeout:15000} ); }; function setPin(lat,lng){ window._pinLat=lat;window._pinLng=lng; if(_pinMarker)_pinMarker.remove(); const icon=L.divIcon({className:"",html:`
📍
`,iconSize:[36,36],iconAnchor:[18,36]}); _pinMarker=L.marker([lat,lng],{icon}).addTo(_pinMap); _pinMap.setView([lat,lng],13); rpc("nearest_zone",{p_lat:lat,p_lng:lng}).then(r=>{ const s=document.getElementById("pin-status"); s.style.display="block"; if(r.ok){ s.style.background="rgba(16,185,129,0.08)";s.style.border="1px solid rgba(16,185,129,0.3)";s.style.color="var(--green)"; s.innerHTML=`✓ In service · nearest zone ${r.zone} · ${r.miles_from_zone} mi · starting fee $${(r.computed_fee_cents/100).toFixed(0)}`; window._pinZoneInfo=r; const btn=document.getElementById("pin-continue");btn.disabled=false;btn.style.opacity="1"; }else{ s.style.background="rgba(216,106,95,0.08)";s.style.border="1px solid rgba(216,106,95,0.3)";s.style.color="var(--rose)"; s.innerHTML=`✕ ${r.error}`; window._pinZoneInfo=null; document.getElementById("pin-continue").disabled=true;document.getElementById("pin-continue").style.opacity="0.4"; } }); } window.confirmPin=function(){ if(!window._pinZoneInfo)return; document.getElementById("pin-picker-screen").style.display="none"; document.getElementById("mode-banner").style.display="block"; const lbl=document.getElementById("pin-label-in").value||"GPS pin"; document.getElementById("mode-title").innerHTML=`Delivering to ${lbl}`; document.getElementById("mode-sub").textContent=`${window._pinZoneInfo.zone} zone · ${window._pinZoneInfo.miles_from_zone} mi · fee $${(window._pinZoneInfo.computed_fee_cents/100).toFixed(0)}`; state.zone=window._pinZoneInfo.zone; if(typeof pickZone==="function")pickZone(window._pinZoneInfo.zone); }; // Hijack the booking call based on mode if(typeof window._origBookCaravanSeat==="undefined"&&typeof anon_book==="function"){ // safety: we cannot always find the exact booking point; mode routing happens via flex form hooks below } // Hook flex submit to route through book_to_pin / book_to_jobsite based on mode const _origSubmitFlex=window.submitFlex; window.submitFlex=async function(){ if(window._mode==="pin"&&window._pinLat){ const btn=document.getElementById("flex-btn");btn.disabled=true;btn.textContent="Submitting…"; const r=await rpc("book_to_pin",{ p_requester_name:document.getElementById("ff-name").value, p_requester_phone:document.getElementById("ff-phone").value, p_requester_email:document.getElementById("ff-email").value, p_lat:window._pinLat,p_lng:window._pinLng, p_pin_label:document.getElementById("pin-label-in")?.value||"GPS pin", p_merchant_id:state.flexMerchant.id, p_merchant_name:state.flexMerchant.name, p_order_description:document.getElementById("ff-order").value, p_window_start:new Date(document.getElementById("ff-start").value).toISOString(), p_window_end:new Date(document.getElementById("ff-end").value).toISOString() }); handleBookingResult(r,btn);return; } if(window._mode==="crew"&&window._crewJobsite){ const btn=document.getElementById("flex-btn");btn.disabled=true;btn.textContent="Submitting…"; const r=await rpc("book_to_jobsite",{ p_code:window._crewJobsite.invite_code||prompt("Re-enter crew code"), p_requester_name:document.getElementById("ff-name").value, p_requester_phone:document.getElementById("ff-phone").value, p_requester_email:document.getElementById("ff-email").value, p_merchant_id:state.flexMerchant.id, p_merchant_name:state.flexMerchant.name, p_order_description:document.getElementById("ff-order").value, p_window_start:new Date(document.getElementById("ff-start").value).toISOString(), p_window_end:new Date(document.getElementById("ff-end").value).toISOString() }); handleBookingResult(r,btn);return; } if(_origSubmitFlex)return _origSubmitFlex(); }; function handleBookingResult(r,btn){ if(!r.ok){alert("Booking failed: "+(r.error||"try again"));btn.disabled=false;btn.textContent="Submit order";return} document.getElementById("flex-form-section")&&(document.getElementById("flex-form-section").style.display="none"); document.getElementById("caravan-section")&&(document.getElementById("caravan-section").style.display="none"); document.getElementById("flex-option-section")&&(document.getElementById("flex-option-section").style.display="none"); document.getElementById("success-panel").classList.add("active"); if(book&&book.run_id&&typeof attachPhotoEvalToRun==="function")await attachPhotoEvalToRun(book.run_id); if(book&&book.run_id&&typeof redirectToStripeCheckout==="function"){const went=await redirectToStripeCheckout(book.run_id);if(went)return} const savedCents=r.you_saved_cents||(r.solo_fee_would_be?r.solo_fee_would_be-r.starting_fee_cents:0); const feeCents=r.seat_fee_cents||r.starting_fee_cents||0; document.getElementById("success-summary").innerHTML=r.jobsite_name?`Crew order placed for ${r.jobsite_name}. Seat fee $${(feeCents/100).toFixed(2)} — ${r.crew_size_aboard||1} riders aboard.`:`Order placed! ${r.matched_caravan_id?"Slotted into an existing caravan.":"Fee drops as neighbors book in your window."}`; document.getElementById("success-stats").innerHTML=`
Your seat fee$${(feeCents/100).toFixed(2)}
${savedCents>0?`
Saved vs solo−$${(savedCents/100).toFixed(2)}
`:""}
We will text you when the driver is on the way.
`; document.getElementById("success-panel").scrollIntoView({behavior:"smooth"}); if(r.run_id&&typeof attachPhotoEvalToRun==="function")await attachPhotoEvalToRun(r.run_id); if(r.run_id&&typeof redirectToStripeCheckout==="function"){const went=await redirectToStripeCheckout(r.run_id);if(went)return} } // URL auto-detect: ?crew=XYZ or ?pin=lat,lng (function(){ const params=new URLSearchParams(window.location.search); const crew=params.get("crew"); if(crew){ rpc("get_jobsite_by_code",{p_code:crew}).then(r=>{ if(r.ok){ window._crewJobsite=r;window._mode="crew"; document.getElementById("mode-picker").style.display="none"; document.getElementById("mode-banner").style.display="block"; document.getElementById("mode-title").innerHTML=`Ordering to ${r.name}`; document.getElementById("mode-sub").textContent=`${r.nearest_zone} · crew code ${crew.toUpperCase()} · ${r.total_orders||0} orders all-time`; state.zone=r.nearest_zone; if(typeof pickZone==="function")pickZone(r.nearest_zone); } }); } })(); init();