nogales.health is a bilingual, AI-powered health directory connecting cross-border patients with trusted doctors, dentists, and specialists in Nogales, Sonora, Mexico.
Nogales, Sonora sits just minutes from the Arizona border. Thousands of Americans visit each year for dental work, surgery, and specialist care — at a fraction of US costs.
This directory is a project of Nogales.Digital Studio, a local digital marketing agency serving health professionals in Nogales, Sonora.
nogales.health does not require account creation or personal information to browse. Anonymous usage data is collected via Umami Analytics — a privacy-first, cookieless tool that does not track individuals.
Conversations are sent to Google's Gemini API. We do not store these on our servers. See Google's privacy policy.
No tracking cookies. Your API key is stored only in your browser's session storage and never transmitted to our servers.
nogales.health is an informational directory only. We do not provide medical advice, diagnoses, or treatment recommendations. Always consult a qualified healthcare professional.
We make reasonable efforts to ensure accuracy but cannot guarantee all information is current. Contact providers directly to verify details before visiting.
The AI assistant is for general guidance only and is not a substitute for professional medical advice. We are not liable for decisions made based on AI-generated content.
Operated by Nogales.Digital Studio, Nogales, Sonora, Mexico. Use governed by applicable Mexican law.
${r.bio}
`:''} ${r.review_snippet?`"${r.review_snippet}"
`:''} ${r.services?.length?`${l.services}: ${r.services.join(' \xB7 ')}
`:''} ${r.address?`${l.address}: ${r.address}
`:''} ${r.phone?`${l.phone}: ${r.phone}
`:''} ${isPrem&&r.booking_link?``:''}${data.context_message}
`; else if(isMore)bbl.innerHTML=`${l.moreOptions}
`; const grid=document.createElement('div');grid.className='results-wrap'; grid.innerHTML=final.map(r=>renderCard(r)).join(''); bbl.appendChild(grid); const smw=document.createElement('div');smw.className='show-more-wrap'; const smb=document.createElement('button');smb.className='show-more'; smb.innerHTML=`${l.showMore}`; smb.onclick=()=>loadMore(smb); smw.appendChild(smb);bbl.appendChild(smw); w.appendChild(av);w.appendChild(bbl);msgs.appendChild(w);msgs.scrollTop=msgs.scrollHeight; } /* ===== LOAD MORE ===== */ async function loadMore(btn){ btn.disabled=true;btn.textContent=L[lang].searching; const exclude=lastResults.map(r=>r.name).join(', '); const prompt=lang==='es'? `Muestra 3 proveedores DIFERENTES para: ${lastSpecialty} en Nogales, Sonora. No repitas: ${exclude}. Mismo formato JSON exacto.`: `Show 3 DIFFERENT providers for: ${lastSpecialty} in Nogales, Sonora. Do NOT repeat: ${exclude}. Same exact JSON format.`; history.push({role:'user',parts:[{text:prompt}]}); try{ const raw=await callGemini(); const parsed=parseResp(raw); if(parsed?.action==='show_results'&&parsed.results?.length){ history.push({role:'model',parts:[{text:raw}]}); renderResults(parsed,true); } }catch(e){} btn.parentElement?.remove(); } /* ===== MARKDOWN ===== */ function md(t){ return t.replace(/&/g,'&').replace(//g,'>') .replace(/\*\*(.+?)\*\*/g,'$1') .replace(/\[([^\]]+)\]\(([^)]+)\)/g,'$1') .replace(/^\- (.+)$/gm,'').replace(/\n/g,'
')
.replace(/^([^<\n].+)$/gm,m=>m.startsWith('<')?m:`
${m}
`); } /* ===== PARSE RESPONSE ===== */ function parseResp(text){ try{ const m=text.match(/```(?:json)?\s*([\s\S]*?)```/); if(m)return JSON.parse(m[1].trim()); const m2=text.match(/(\{[\s\S]*?"action"\s*:\s*"show_results"[\s\S]*?\})/); if(m2)return JSON.parse(m2[1]); }catch(e){} return null; } /* ===== CALL GEMINI ===== */ async function callGemini(){ // Try Netlify function (GitHub-connected deploys) try{ const r=await fetch('/.netlify/functions/chat',{ method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({messages:history.slice(-12),lang:lang}) }); if(r.ok){const d=await r.json();return d.text;} }catch(e){} // Direct OpenRouter fallback (works on any deploy) const key=window.OR_KEY||''; if(!key)throw new Error('API not configured'); const resp=await fetch('https://openrouter.ai/api/v1/chat/completions',{ method:'POST', headers:{ 'Content-Type':'application/json', 'Authorization':'Bearer '+key, 'HTTP-Referer':'https://nogales.health', 'X-Title':'nogales.health' }, body:JSON.stringify({ model:'nex-agi/nex-n2-pro:free', messages:[{role:'system',content:lang==='es'?SYS_ES:SYS_EN},...history.slice(-12)], temperature:0.35, max_tokens:1400 }) }); if(!resp.ok){const e=await resp.json().catch(()=>({}));throw new Error(e.error?.message||'HTTP '+resp.status);} const d=await resp.json(); return d.choices?.[0]?.message?.content||''; } /* ===== SEND MESSAGE ===== */ async function sendMsg(userText){ addMsg('user',md(userText)); history.push({role:'user',parts:[{text:userText}]}); showTyping();sbtn.disabled=true; try{ const raw=await callGemini();removeTyping(); const parsed=parseResp(raw); if(parsed?.action==='show_results'&&parsed.results?.length){ history.push({role:'model',parts:[{text:raw}]}); renderResults(parsed,false); }else{ history.push({role:'model',parts:[{text:raw}]}); addMsg('assistant',md(raw)); } }catch(err){ removeTyping(); { addMsg('assistant',`Something went wrong: ${err.message}. Please try again.
`); } } sbtn.disabled=inp.value.trim()===''; } /* ===== MODALS ===== */ function openM(id){document.getElementById(id).classList.add('open');} function closeM(id){document.getElementById(id).classList.remove('open');} document.querySelectorAll('.modal-bg').forEach(m=>{m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('open');});}); document.addEventListener('keydown',e=>{if(e.key==='Escape')document.querySelectorAll('.modal-bg.open').forEach(m=>m.classList.remove('open'));}); /* ===== INIT ===== */ if(window.matchMedia('(min-width:768px)').matches)setTimeout(()=>inp.focus(),450); // API key is in Netlify environment variables — never exposed to browser