[{"data":1,"prerenderedAt":814},["ShallowReactive",2],{"meta-profile":3,"command-palette-about":18,"meta-contacts":403,"project-wp-auth-ai-gate":421},{"id":4,"extension":5,"logo_name":6,"meta":7,"name":8,"roles":9,"stem":16,"__hash__":17},"profile/meta/profile.yml","yml","giovanni-manara",{},"Giovanni Manara",[10,11,12,13,14,15],"Full Stack Developer","WordPress Developer","Frontend Developer","GSAP Enthusiast","Tennis Lover","Gamer Appassionato","meta/profile","3BmX-xwCGwakpBF7rjsHDYIpXj8I89zWKoP32P9_MxE",[19,44,63,81,100,122,144,187,220,247,300,326,378],{"id":20,"title":21,"body":22,"description":28,"extension":36,"meta":37,"navigation":38,"order":39,"path":40,"seo":41,"stem":42,"__hash__":43},"about/competencies/ai-nel-workflow.md","ai-nel-workflow",{"type":23,"value":24,"toc":32},"minimark",[25,29],[26,27,28],"p",{},"Uso quotidianamente strumenti come Claude Code e Cursor, ma con regole precise: la spec e il piano vengono prima del codice, ogni modifica passa da una review, e ogni repository ha le sue convenzioni scritte che anche gli agenti devono rispettare. L'AI accelera l'esecuzione; le decisioni — architettura, priorità, cosa entra in produzione — restano mie.",[26,30,31],{},"Quando ho voluto imparare React sul serio, ho ribaltato i ruoli: sul mio progetto personale l'AI poteva solo fare da reviewer, mai scrivere. Ogni riga l'ho scritta io. Saper usare bene questi strumenti significa anche sapere quando spegnerli.",{"title":33,"searchDepth":34,"depth":34,"links":35},"",2,[],"md",{},true,4,"/competencies/ai-nel-workflow",{"title":21,"description":28},"competencies/ai-nel-workflow","TX_bURb05LSO0o517DTADGBpxuILgJN3MNd2uxE6qZw",{"id":45,"title":46,"body":47,"description":51,"extension":36,"meta":57,"navigation":38,"order":58,"path":59,"seo":60,"stem":61,"__hash__":62},"about/competencies/code-quality.md","code-quality",{"type":23,"value":48,"toc":55},[49,52],[26,50,51],{},"Mi piace scrivere codice pulito e mantenere codebase leggibili e facili da manutenere — sia su personalizzazioni WordPress (temi/plugin) sia su progetti custom.",[26,53,54],{},"La qualità, per me, non è un dettaglio estetico: è logica, ordine e attenzione ai dettagli, così che un progetto prenda forma passo dopo passo e regga in produzione.",{"title":33,"searchDepth":34,"depth":34,"links":56},[],{},3,"/competencies/code-quality",{"title":46,"description":51},"competencies/code-quality","WVyPz6M7BXq1MiXLLc4nXEwS_MEpymEmdCSifEoF1Ms",{"id":64,"title":65,"body":66,"description":70,"extension":36,"meta":76,"navigation":38,"order":34,"path":77,"seo":78,"stem":79,"__hash__":80},"about/competencies/collaboration.md","collaboration",{"type":23,"value":67,"toc":74},[68,71],[26,69,70],{},"Ho fatto sport a diversi livelli fin da giovane, e questo mi ha lasciato una cosa utilissima nel lavoro: saper stare in squadra, comunicare in modo chiaro e contribuire senza \"rumore\".",[26,72,73],{},"Su progetti reali e codebase già in produzione, collaborare significa allinearsi sul problema, condividere contesto e consegnare in modo affidabile — non solo scrivere codice in isolamento.",{"title":33,"searchDepth":34,"depth":34,"links":75},[],{},"/competencies/collaboration",{"title":65,"description":70},"competencies/collaboration","CiCBh3JZXfzxe54qjCmGI8FdUVPskd571f84dOpak3U",{"id":82,"title":83,"body":84,"description":88,"extension":36,"meta":94,"navigation":38,"order":95,"path":96,"seo":97,"stem":98,"__hash__":99},"about/competencies/problem-solving.md","problem-solving",{"type":23,"value":85,"toc":92},[86,89],[26,87,88],{},"Quando qualcosa non torna, vado a fondo: studio, provo, documento e arrivo alla soluzione con costanza.",[26,90,91],{},"Nel lavoro quotidiano applico lo stesso approccio: capire il problema, scomporlo in parti gestibili, e farlo funzionare davvero — senza scorciatoie che poi costano in produzione.",{"title":33,"searchDepth":34,"depth":34,"links":93},[],{},1,"/competencies/problem-solving",{"title":83,"description":88},"competencies/problem-solving","_y34cpLrt3OqbL7_xHC_feokuoDThzESXsqrDOfmULo",{"id":101,"title":102,"body":103,"description":107,"extension":36,"meta":117,"navigation":38,"order":95,"path":118,"seo":119,"stem":120,"__hash__":121},"about/experiences/megiston.md","megiston",{"type":23,"value":104,"toc":115},[105,108],[26,106,107],{},"Dal 2022 lavoro come sviluppatore web, con un focus pratico su progetti reali e codebase già in produzione.",[26,109,110,114],{},[111,112,113],"strong",{},"2025 - oggi | Megiston S.r.l."," — Full stack web developer in un team piccolo, dove si tocca un po' di tutto. Mi sono occupato del frontend di una piattaforma di biglietteria online (Nuxt su API REST, interfacce costruite da Figma con Tailwind, carrello e pagamenti online), di personalizzazioni WordPress profonde — plugin custom per preventivi multi-step, dati strutturati JSON-LD, integrazioni con booking engine, ecc. — e attualmente del backend del nuovo sito aziendale con Payload CMS.",{"title":33,"searchDepth":34,"depth":34,"links":116},[],{},"/experiences/megiston",{"title":102,"description":107},"experiences/megiston","30UBT7QbA9xQo9Vrb9OritBBGpQLwd_4g3epIiFz3LQ",{"id":123,"title":124,"body":125,"description":138,"extension":36,"meta":139,"navigation":38,"order":34,"path":140,"seo":141,"stem":142,"__hash__":143},"about/experiences/websonica.md","websonica",{"type":23,"value":126,"toc":136},[127,133],[26,128,129,132],{},[111,130,131],{},"2022 - 2025 | Websonica S.r.l."," — Prima come stage web developer (2022-2023), poi come junior web developer (2023-2025). Ho lavorato su gestione e personalizzazione di siti WordPress e Magento2, su software custom in Laravel e Next.js, e su CRM come vTiger.",[26,134,135],{},"Mi piace tenere un approccio ordinato: capire il problema, scomporlo, e farlo funzionare davvero (senza magia nera… o almeno provandoci).",{"title":33,"searchDepth":34,"depth":34,"links":137},[],"2022 - 2025 | Websonica S.r.l. — Prima come stage web developer (2022-2023), poi come junior web developer (2023-2025). Ho lavorato su gestione e personalizzazione di siti WordPress e Magento2, su software custom in Laravel e Next.js, e su CRM come vTiger.",{},"/experiences/websonica",{"title":124,"description":138},"experiences/websonica","dVGZo1BJjKJRXpZU7gBpp2M0iuKv_52-qjEPKsA1GnA",{"id":145,"title":146,"body":147,"description":181,"extension":36,"meta":182,"navigation":38,"order":95,"path":183,"seo":184,"stem":185,"__hash__":186},"about/hobbies/favorite-games.md","favorite-games",{"type":23,"value":148,"toc":179},[149,156],[26,150,151,152,155],{},"Nei videogiochi mi sento a casa nei ",[111,153,154],{},"GDR",", soprattutto quelli story-driven: mi piace immergermi nelle storie, nei personaggi e nelle scelte (quelle che poi ti fanno pensare \"ok, questa me la porto dietro\").",[26,157,158,159,162,163,166,167,170,171,174,175,178],{},"Il mio primo \"innesco\" è stato ",[111,160,161],{},"Final Fantasy X",", e da lì ho continuato a cercare esperienze simili. Tra i miei preferiti ci sono la trilogia di ",[111,164,165],{},"Mass Effect"," (su Andromeda sorvoliamo), ",[111,168,169],{},"Baldur's Gate 3",", la saga di ",[111,172,173],{},"Persona"," (3, 4 e 5) e ",[111,176,177],{},"Clair Obscur 33",", probabilmente il mio preferito degli ultimi anni.",{"title":33,"searchDepth":34,"depth":34,"links":180},[],"Nei videogiochi mi sento a casa nei GDR, soprattutto quelli story-driven: mi piace immergermi nelle storie, nei personaggi e nelle scelte (quelle che poi ti fanno pensare \"ok, questa me la porto dietro\").",{},"/hobbies/favorite-games",{"title":146,"description":181},"hobbies/favorite-games","RjYRAf75mnYJgFIdt-pf1Wf3zXT7Y7Sum_s4AIaBdck",{"id":188,"title":189,"body":190,"description":194,"extension":36,"meta":215,"navigation":38,"order":34,"path":216,"seo":217,"stem":218,"__hash__":219},"about/hobbies/sports.md","sports",{"type":23,"value":191,"toc":213},[192,195,206],[26,193,194],{},"Ho praticato diversi sport (con una breve parentesi tra calcio e basket), ma i due che mi hanno formato di più sono stati scherma e tennis.",[26,196,197,198,201,202,205],{},"Per ",[111,199,200],{},"sei anni"," ho fatto agonismo nella ",[111,203,204],{},"scherma",", ottenendo buoni risultati a livello regionale e nazionale. Più che i piazzamenti, mi porto dietro ciò che conta davvero: fiducia costruita nel tempo, disciplina, ambizione e la capacità di lavorare in squadra anche quando la pressione sale.",[26,207,208,209,212],{},"Oggi il mio sport è il ",[111,210,211],{},"tennis",": è l'unico che pratico con continuità e che seguo davvero, anche in TV e streaming. Federer è stato il mio riferimento, e adesso mi godo con entusiasmo Alcaraz e (inevitabilmente) Sinner.",{"title":33,"searchDepth":34,"depth":34,"links":214},[],{},"/hobbies/sports",{"title":189,"description":194},"hobbies/sports","OjIveNcZF2yHP6pEJ4krecf72toMAa6nhMecOCA20Io",{"id":221,"title":222,"body":223,"description":33,"extension":36,"meta":242,"navigation":38,"order":95,"path":243,"seo":244,"stem":245,"__hash__":246},"about/personal-life/bio.md","bio",{"type":23,"value":224,"toc":239},[225,230,233,236],[226,227,229],"h2",{"id":228},"about-me","About me",[26,231,232],{},"Mi chiamo Giovanni Manara e lavoro come sviluppatore web dal 2022: prima uno stage, poi un percorso da junior, oggi full stack con propensione al frontend in una piccola web agency vicino Padova.",[26,234,235],{},"Mi muovo soprattutto su due binari: applicazioni web in Vue/Nuxt, dove mi sono occupato a lungo del frontend di una piattaforma di vendita online in produzione, e WordPress fatto sul serio — temi custom e plugin scritti da zero quando i builder non bastano. Ultimamente sto costruendo il backend del nuovo sito aziendale con Payload CMS.",[26,237,238],{},"Il filo conduttore: partire dal design, tenere la logica separata dalla UI, e quando un flusso mi serve più di una volta trasformarlo in uno strumento riusabile.",{"title":33,"searchDepth":34,"depth":34,"links":240},[241],{"id":228,"depth":34,"text":229},{},"/personal-life/bio",{"title":222,"description":33},"personal-life/bio","PXadkOSxGExPpohcY-s6KWcyBI_LvG_4DFW3s-eBhdg",{"id":248,"title":249,"body":250,"description":33,"extension":36,"meta":295,"navigation":38,"order":58,"path":296,"seo":297,"stem":298,"__hash__":299},"about/personal-life/education.md","education",{"type":23,"value":251,"toc":292},[252,256,259],[226,253,255],{"id":254},"educazione","Educazione",[26,257,258],{},"Un percorso non lineare: dalle biotecnologie allo sviluppo web, passando per la bioinformatica.",[260,261,262,269,275,286],"ul",{},[263,264,265,268],"li",{},[111,266,267],{},"2010-2015"," — Diploma al Liceo Scientifico Enrico Fermi (Padova).",[263,270,271,274],{},[111,272,273],{},"2015-2019"," — Laurea Triennale in Biotecnologie, Università del Piemonte Orientale (Novara).",[263,276,277,280,281,285],{},[111,278,279],{},"2019-2021"," — Laurea Magistrale in Bioinformatica, Università Tor Vergata (Roma). Qui mi sono avvicinato allo sviluppo web grazie a un corso di ",[282,283,284],"em",{},"Applicazioni web per la Bioinformatica",": con il contesto del COVID e una passione crescente, ho scelto di mettere in pausa l'università per concentrarmi sulla programmazione.",[263,287,288,291],{},[111,289,290],{},"2022"," — Corso professionalizzante in Full Stack Web Development (600 ore, riconosciuto MIUR), Accademia delle Professioni (Noventa Padovana), concluso con ottimi risultati.",{"title":33,"searchDepth":34,"depth":34,"links":293},[294],{"id":254,"depth":34,"text":255},{},"/personal-life/education",{"title":249,"description":33},"personal-life/education","zKz_U6qhxDUbh3tCI3bf5XcUlJLHsE-Ea0mDOJhN4ro",{"id":301,"title":302,"body":303,"description":33,"extension":36,"meta":321,"navigation":38,"order":34,"path":322,"seo":323,"stem":324,"__hash__":325},"about/personal-life/interests.md","interests",{"type":23,"value":304,"toc":318},[305,309,312,315],[226,306,308],{"id":307},"interessi","Interessi",[26,310,311],{},"Mi piace la tecnologia in senso ampio: dal web alle soluzioni \"ben costruite\", fino a tutto ciò che migliora processi e prodotti.",[26,313,314],{},"Amo il tennis (lo seguo e lo pratico da anni) e quando posso mi piace vivere i tornei dal vivo.",[26,316,317],{},"Mi piace anche viaggiare e cucinare: scoprire posti nuovi e provare sapori diversi è un ottimo modo per tenere la curiosità allenata.",{"title":33,"searchDepth":34,"depth":34,"links":319},[320],{"id":307,"depth":34,"text":308},{},"/personal-life/interests",{"title":302,"description":33},"personal-life/interests","E7rdK_OqdaU42uR_g8l-MRvUfHXlF0Mkjw6fiZzEkkw",{"id":327,"title":328,"body":329,"description":333,"extension":36,"meta":373,"navigation":38,"order":95,"path":374,"seo":375,"stem":376,"__hash__":377},"about/skills/hard-skills.md","hard-skills",{"type":23,"value":330,"toc":371},[331,334],[26,332,333],{},"Mi muovo tra front-end e back-end, con il frontend come casa.",[26,335,336,339,340,343,346,347,349,352,353,355,358,359,361,364,365,367,370],{},[111,337,338],{},"Fondamentali:"," HTML, CSS, JavaScript, TypeScript.",[341,342],"br",{},[111,344,345],{},"Frontend:"," Vue 3 / Nuxt, React / Next.js, Pinia.",[341,348],{},[111,350,351],{},"Stili:"," Tailwind, Sass, DaisyUI, design token da Figma.",[341,354],{},[111,356,357],{},"WordPress:"," temi child e plugin custom OO, ACF, WooCommerce, WPML.",[341,360],{},[111,362,363],{},"Backend:"," PHP, Payload CMS, MySQL, PostgreSQL.",[341,366],{},[111,368,369],{},"Strumenti:"," Git, GSAP, Stripe, i18n, sviluppo AI-assisted (Claude Code, Cursor) con workflow spec-first.",{"title":33,"searchDepth":34,"depth":34,"links":372},[],{},"/skills/hard-skills",{"title":328,"description":333},"skills/hard-skills","eFu6VaeKB7pA6op62PTPLV3PIMfwNP9blrWwzkBQMq8",{"id":379,"title":380,"body":381,"description":397,"extension":36,"meta":398,"navigation":38,"order":34,"path":399,"seo":400,"stem":401,"__hash__":402},"about/skills/soft-skills.md","soft-skills",{"type":23,"value":382,"toc":395},[383,389],[26,384,385,388],{},[111,386,387],{},"Teamwork:"," ho fatto sport a diversi livelli fin da giovane, e questo mi ha lasciato una cosa utilissima nel lavoro: saper stare in squadra, comunicare in modo chiaro e contribuire senza \"rumore\".",[26,390,391,394],{},[111,392,393],{},"Tenacia e affidabilità:"," le sfide mi stimolano. Quando qualcosa non torna, vado a fondo: studio, provo, documento e arrivo alla soluzione con costanza. Mi piace prendermi responsabilità su quello che consegno, perché il codice in produzione non perdona (ma insegna parecchio).",{"title":33,"searchDepth":34,"depth":34,"links":396},[],"Teamwork: ho fatto sport a diversi livelli fin da giovane, e questo mi ha lasciato una cosa utilissima nel lavoro: saper stare in squadra, comunicare in modo chiaro e contribuire senza \"rumore\".",{},"/skills/soft-skills",{"title":380,"description":397},"skills/soft-skills","QyBwnFi9-ZYJc-xGJ0-L1syIeASIp61uVcI2WBJ_HZo",{"id":404,"direct":405,"extension":5,"meta":410,"social":411,"stem":419,"__hash__":420},"contacts/meta/contacts.yml",{"title":406,"sources":407},"contacts",{"email":408,"phone":409},"giovanni@megiston.com","+39 375 890 5337",{},{"github":412,"linkedin":416},{"title":413,"url":414,"user":415},"Github profile","https://github.com/GioManara96","GioManara96",{"title":417,"url":418,"user":8},"Linkedin account","https://www.linkedin.com/in/giovanni-manara-80b3b324a/","meta/contacts","i0Q8Qe7rb0Tu8tqyz-9qGrPI7w8qOijxquLhi5vFgUU",{"id":422,"title":423,"body":424,"description":790,"extension":36,"img":791,"liveUrl":792,"meta":793,"navigation":38,"path":794,"projectId":39,"seo":795,"slug":796,"stack":797,"stem":810,"tech":811,"url":792,"__hash__":813},"projects/projects/wp-auth-ai-gate.md","Auth Gate per AI",{"type":23,"value":425,"toc":783},[426,432,436,448,452,459,463,519,523,533,726,736,754,764,768,779],[427,428,429],"blockquote",{},[26,430,431],{},"Progetto che ho sviluppato in agenzia, partendo da spec e piano scritti prima del codice. Niente nomi e niente codice reale: gli snippet sono riscritti e semplificati per illustrare l'approccio.",[226,433,435],{"id":434},"cosè","Cos'è",[26,437,438,439,443,444,447],{},"Un cliente voleva offrire un assistente AI (Voiceflow) solo ai propri clienti registrati. WordPress però non ha un flusso di registrazione frontend decente: ",[440,441,442],"code",{},"wp-login.php"," è brutto, non fa double opt-in e non c'entra nulla col brand. Questo plugin costruisce l'intera esperienza — registrazione, verifica email, login, recupero password — e usa lo stato di autenticazione come ",[111,445,446],{},"interruttore dell'assistente",": loggato e verificato → widget di chat che ti saluta per nome; anonimo → un badge che ti invita a registrarti.",[226,449,451],{"id":450},"il-problema","Il problema",[26,453,454,455,458],{},"Tre vincoli: gli account dovevano essere utenti WordPress veri (per non inventare un secondo concetto di sessione), la verifica email doveva essere obbligatoria prima del primo accesso, e nulla di tutto questo doveva avvicinarsi a ",[440,456,457],{},"wp-admin"," — un cliente registrato non deve mai vedere la dashboard.",[226,460,462],{"id":461},"come-funziona","Come funziona",[260,464,465,478,492,502,508],{},[263,466,467,470,471,474,475,477],{},[111,468,469],{},"Ruolo dedicato"," con la sola capability ",[440,472,473],{},"read","; ",[440,476,457],{}," viene bloccato a priorità 1 con redirect, e l'admin bar nascosta — con via di fuga per gli account promossi a editor in seguito",[263,479,480,483,484,487,488,491],{},[111,481,482],{},"Double opt-in",": il token di verifica (40 caratteri) è salvato ",[111,485,486],{},"hashato"," con TTL di 24 ore e confrontato con ",[440,489,490],{},"hash_equals()","; al click l'utente viene attivato e loggato in automatico",[263,493,494,497,498,501],{},[111,495,496],{},"Una pagina, cinque viste",": registrazione, login, recupero, reset e \"conferma la tua email\" sono sibling nello stesso template; un JS vanilla da ~100 righe mostra la vista che ",[111,499,500],{},"il server"," indica nella risposta — anche negli errori",[263,503,504,507],{},[111,505,506],{},"Igiene automatica",": un cron mensile elimina gli account mai verificati dopo 30 giorni",[263,509,510,511,514,515,518],{},"Recupero password su primitive core (",[440,512,513],{},"get_password_reset_key"," / ",[440,516,517],{},"reset_password","), sessioni invalidate dopo ogni reset, copy admin-editabile e registrato in WPML",[226,520,522],{"id":521},"dettagli-di-cui-vado-fiero","Dettagli di cui vado fiero",[26,524,525,528,529,532],{},[111,526,527],{},"La difesa dall'enumeration, fatta nell'ordine giusto."," Il flusso di login verifica la password ",[282,530,531],{},"prima"," di rivelare che un account esiste ma non è verificato — nell'ordine inverso, chiunque potrebbe scoprire quali email sono registrate. Stessa filosofia su recupero e reinvio: risposta generica identica sia che l'email esista sia che no, con un rate limit che resta invisibile proprio grazie alla risposta uniforme.",[534,535,539],"pre",{"className":536,"code":537,"language":538,"meta":33,"style":33},"language-php shiki shiki-themes one-dark-pro","// Prima la password, poi lo stato: l'ordine inverso rivelerebbe\n// a chiunque quali email hanno un account.\nif ( ! $user || ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {\n  return $this->fail( __( 'Credenziali non valide.' ), 'login' );\n}\nif ( get_user_meta( $user->ID, 'account_status', true ) === 'pending' ) {\n  return $this->ok( __( 'Conferma la tua email per accedere.' ), 'pending' );\n}\n","php",[440,540,541,549,554,611,646,652,693,721],{"__ignoreMap":33},[542,543,545],"span",{"class":544,"line":95},"line",[542,546,548],{"class":547},"sV9Aq","// Prima la password, poi lo stato: l'ordine inverso rivelerebbe\n",[542,550,551],{"class":544,"line":34},[542,552,553],{"class":547},"// a chiunque quali email hanno un account.\n",[542,555,556,560,564,568,572,575,578,582,585,588,591,593,596,599,601,603,605,608],{"class":544,"line":58},[542,557,559],{"class":558},"seHd6","if",[542,561,563],{"class":562},"sn6KH"," ( ",[542,565,567],{"class":566},"sjrmR","!",[542,569,571],{"class":570},"sVyAn"," $user",[542,573,574],{"class":566}," ||",[542,576,577],{"class":566}," !",[542,579,581],{"class":580},"sVbv2"," wp_check_password",[542,583,584],{"class":562},"(",[542,586,587],{"class":570}," $password",[542,589,590],{"class":562},",",[542,592,571],{"class":570},[542,594,595],{"class":562},"->",[542,597,598],{"class":570},"user_pass",[542,600,590],{"class":562},[542,602,571],{"class":570},[542,604,595],{"class":562},[542,606,607],{"class":570},"ID",[542,609,610],{"class":562}," ) ) {\n",[542,612,613,616,620,622,625,628,631,633,637,640,643],{"class":544,"line":39},[542,614,615],{"class":558},"  return",[542,617,619],{"class":618},"sU0A5"," $this",[542,621,595],{"class":562},[542,623,624],{"class":580},"fail",[542,626,627],{"class":562},"( ",[542,629,630],{"class":580},"__",[542,632,584],{"class":562},[542,634,636],{"class":635},"subq3"," 'Credenziali non valide.'",[542,638,639],{"class":562}," ), ",[542,641,642],{"class":635},"'login'",[542,644,645],{"class":562}," );\n",[542,647,649],{"class":544,"line":648},5,[542,650,651],{"class":562},"}\n",[542,653,655,657,659,662,664,666,668,670,672,675,677,681,684,687,690],{"class":544,"line":654},6,[542,656,559],{"class":558},[542,658,563],{"class":562},[542,660,661],{"class":580},"get_user_meta",[542,663,584],{"class":562},[542,665,571],{"class":570},[542,667,595],{"class":562},[542,669,607],{"class":570},[542,671,590],{"class":562},[542,673,674],{"class":635}," 'account_status'",[542,676,590],{"class":562},[542,678,680],{"class":679},"sVC51"," true",[542,682,683],{"class":562}," ) ",[542,685,686],{"class":566},"===",[542,688,689],{"class":635}," 'pending'",[542,691,692],{"class":562}," ) {\n",[542,694,696,698,700,702,705,707,709,711,714,716,719],{"class":544,"line":695},7,[542,697,615],{"class":558},[542,699,619],{"class":618},[542,701,595],{"class":562},[542,703,704],{"class":580},"ok",[542,706,627],{"class":562},[542,708,630],{"class":580},[542,710,584],{"class":562},[542,712,713],{"class":635}," 'Conferma la tua email per accedere.'",[542,715,639],{"class":562},[542,717,718],{"class":635},"'pending'",[542,720,645],{"class":562},[542,722,724],{"class":544,"line":723},8,[542,725,651],{"class":562},[26,727,728,731,732,735],{},[111,729,730],{},"Il contesto utente arriva all'AI senza backend in mezzo."," Quando un utente verificato apre una pagina, il plugin scrive un cookie first-party di un'ora con id, email e nome; il widget lo legge client-side e personalizza il saluto. Niente API custom, niente sincronizzazione di stato: il cookie ",[282,733,734],{},"è"," il contratto.",[26,737,738,741,742,745,746,749,750,753],{},[111,739,740],{},"Hardening contro lo script-breakout."," L'ID del progetto Voiceflow configurato dall'admin finisce dentro un tag ",[440,743,744],{},"\u003Cscript>",": viene serializzato con ",[440,747,748],{},"wp_json_encode(..., JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT)",", così un eventuale ",[440,751,752],{},"\u003C/script>"," nel valore resta inerte anche se la sanitizzazione a monte dovesse regredire un domani.",[26,755,756,759,760,763],{},[111,757,758],{},"Il server guida la UI."," Ogni risposta JSON — successo o errore — può indicare la prossima vista da mostrare. \"Credenziali giuste ma email non confermata\" porta alla vista ",[440,761,762],{},"pending"," senza reload e senza che il client debba conoscere la logica: il frontend è stupido apposta.",[226,765,767],{"id":766},"cosa-ho-imparato","Cosa ho imparato",[260,769,770,773,776],{},[263,771,772],{},"L'autenticazione è fatta di ordinamenti: cosa verifichi prima di cosa riveli, cosa hashi prima di cosa salvi",[263,774,775],{},"Riusare le primitive core di WordPress (auth cookie, reset key, ruoli) batte reinventarle: meno codice mio da difendere",[263,777,778],{},"Una state machine guidata dal server rende il client banale e i flussi testabili",[780,781,782],"style",{},"html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":33,"searchDepth":34,"depth":34,"links":784},[785,786,787,788,789],{"id":434,"depth":34,"text":435},{"id":450,"depth":34,"text":451},{"id":461,"depth":34,"text":462},{"id":521,"depth":34,"text":522},{"id":766,"depth":34,"text":767},"Registrazione e login frontend su WordPress con double opt-in, usati come cancello per un assistente AI (Voiceflow) - solo gli utenti verificati parlano col bot, che li accoglie per nome.","/icons/projects/auth-ai-gate-wide.webp",null,{},"/projects/wp-auth-ai-gate",{"title":423,"description":790},"wp-auth-ai-gate",[798,801,804,806,808],{"icon":799,"label":800},"cib:wordpress","WordPress",{"icon":802,"label":803},"cib:php","PHP",{"label":805},"Voiceflow",{"label":807},"reCAPTCHA v3",{"label":809},"WPML","projects/wp-auth-ai-gate",[812],"wordpress","HqRqUVwt5D1V8yRf7xR6lBNXGIVkx-YPwa_aCx9fyLo",1786039355214]