Psychotherapist website in Italy: Next.js build, blog migration and AI search visibility
A bilingual website for a psychotherapist in Milan: 468 posts moved off WordPress with every URL intact, a CMS that checks texts against the profession's code, pages already cited by ChatGPT.
Client
Industry
Services
Website

Problem
Giuseppe is a psychologist and psychotherapist. He sees people in Milan, Monza and Cernusco sul Naviglio, and works online with Italians living abroad. His focus is anxiety and panic attacks. He found me through ChatGPT, which set the tone for the whole project: the new site had to be built so that he, too, would be found in AI answers, not only in Google.
The old site ran on WordPress and its blog held 468 posts. Those URLs had been indexed for years, so losing them was not an option. After launch Giuseppe intended to run the site himself, without a developer. And advertising by psychologists in Italy is restricted by article 40 of the professional code of conduct: no promised outcomes, no patient testimonials, no discounts, no "free consultation". A single careless phrase in a text can become a licensing problem.
There was also a question of how the site should feel. Many people arrive at a psychotherapist's website while anxious. They need a calm place to read and think, not counters, pop-ups and "book now" buttons.
Goal
- Rebuild the site from scratch, moving from WordPress to Next.js and Sanity
- Ship two languages: Italian as the primary one, English under /en
- Migrate all 468 blog posts so that every old URL keeps working
- Make the site legible to Google and to AI assistants: ChatGPT, Perplexity, Google AI Overviews
- Give the psychotherapist a CMS that is hard to break and hard to breach the code with
- Design a calm, custom site rather than adapt a template
- Hand the site over with documentation the owner can actually use
Results
- New pages already appear in ChatGPT answers
- All 468 blog posts migrated, 468 of 468, with 301 redirects from every old URL
- The site is open to crawlers and indexed; no page is left noindexed by accident
- 7 pillar pages by area of therapy, 21 Italian subtopic pages, plus pages for Milan, Monza and online therapy for Italians abroad
- 150 Italian FAQ entries, reused across topic pages and the FAQ page
- The CMS warns the editor when a text contains wording the professional code forbids
- Owner's manual in English (69 pages) and Italian (71 pages), plus video walkthroughs
- 44 working days from the first line of code to handover
- A five-star Google review from Giuseppe
Completed Work
- Custom design: dark theme, light sections, a serif with a true italic, all on open-licensed resources
- Block-by-block sign-off: every home page block was reviewed by the client before the next one started
- Development on Next.js 16 and Sanity, with the CMS embedded in the site itself
- Italian and English versions with translated page addresses and a link between the two
- Migration of 468 WordPress posts, their images and captions, with 301 redirects from all old URLs
- A deontology check for article 40 built into the CMS
- Guard rails in the CMS: key pages cannot be deleted, published slugs are locked, no page can exist without a language
- Draft preview on the page itself and publishing without a developer
- Structured data for Google and AI: the practitioner, the practices, conditions, therapies, services, questions and answers
- Explicit rules for AI crawlers in robots.txt
- A map of the consulting rooms in Milan, Monza and Cernusco sul Naviglio
- A contact form on the client's own domain mail, with SPF, DKIM and DMARC in place
- Analytics that only starts after the visitor consents
- Owner's manual in two languages and video walkthroughs
- After handover: a Search Console review and the removal of duplicate URLs
Project Highlights
Project Description
What a psychotherapist in Italy needs from a website: search, trust and professional rules
A private psychotherapist's website has three jobs. People looking for help with anxiety or panic attacks have to find it. It has to earn the trust of someone who is already having a hard time. And it must not breach the rules of the profession, which in Italy are stricter than in most industries.
The old WordPress site did the first two poorly, but it carried something valuable: 468 blog posts Google had known for years. So the brief was not "make it look good" — it was "rebuild everything and lose nothing".
How the psychotherapist's website was prepared for ChatGPT, Perplexity and Google
Giuseppe found me through ChatGPT. That made visibility in AI answers a first-day requirement rather than a later addition.
In practice that means a few things. Every public page is rendered ahead of time, so a crawler or an AI assistant sees the full text without running any scripts. Each page carries its own title, description and canonical URL, and the Italian and English versions point at each other, so search engines serve people the page in their language.
The robots file spells out what AI crawlers may do. The search crawlers behind ChatGPT, Perplexity and Claude are allowed in explicitly, so they can find a page and quote it in an answer. Whether to allow the crawlers that collect text for model training is the client's decision. The CMS and the internal endpoints are closed to everyone.
Preview builds, which Vercel publishes on every change, are always kept out of the index — in the response header and in the page itself. The rule lives in the code, so a draft copy cannot leak into Google because someone forgot about it.
The effect is already visible: new pages from the site turn up in ChatGPT answers.
Schema.org markup for a therapy website: practitioner, practices, conditions
Structured data tells search engines and AI assistants who stands behind the site. It describes the practitioner, the practice with its addresses and opening hours, the medical pages, the conditions he works with, the therapies, the services and their prices, the questions and answers, the blog posts and the path to every page.
A visitor never sees any of it. A machine reads a clear statement: this practitioner in Milan and Monza works with anxiety and panic attacks, here is his approach, here are the answers to the common questions.
Site structure built around what patients actually search for
The structure follows what people bring to a psychotherapist. Seven pillar pages cover the areas of therapy: anxiety disorders, panic attacks and agoraphobia, relationship difficulties, sexual dysfunctions, stress and burnout, couples therapy, trauma. Each area has its own subtopics — 21 of them in Italian — and the pillar pages exist in English too.
Separate pages answer the "where" question: psychologist in Milan, psychologist in Monza, and online therapy for Italians living abroad. All of them in both languages.
Questions and answers are stored on their own, 150 of them in Italian. The same answer can be attached to a pillar page, to a subtopic and to the FAQ page, so correcting it once corrects it everywhere.
Page addresses are translated: /metodo becomes /en/method, /psicologo-milano becomes /en/psychologist-milan.
Migrating 468 blog posts from WordPress to Sanity without losing a single URL
All 468 posts came across, 468 of 468. Four of them failed on the first run because of errors on the old WordPress side; a second run picked them up without a line of code changing.
Every post was converted from HTML into Sanity's format, images came with it, and images that had no alt text were given one. A migration report was kept for each post.
The old addresses did not disappear. A snapshot of all 468 slugs was frozen, and from it the site generates permanent 301 redirects to the new blog URLs. The WordPress tail was closed off separately: date archives, old checkout pages, the previous contact page.
One more safeguard: the addresses the redirects come from are reserved. If anyone tries to create a page at one of them, the CMS refuses. Otherwise the page would look published while every visitor got redirected away from it.
During the migration two nearly identical posts turned up, 94% the same text. I did not quietly delete one of them — which to keep was the client's call.
A CMS that checks texts against article 40 of the professional code
Article 40 of the Italian psychologists' code of conduct restricts advertising. A psychotherapist may not promise outcomes, publish patient testimonials, offer discounts or a "free consultation", or push urgency.
When the owner writes the texts himself, that line is easy to cross by accident. So the check sits inside the CMS. If a text contains wording such as "gratuito", "guarire", "garantito", "sconto", "recensioni", a percentage sign or "offerta limitata", the CMS raises an error and explains why. It does not replace professional judgement, but it does insure against a careless sentence.
Guard rails in the CMS: what the owner cannot break
Giuseppe is not a technical person, and the CMS is built accordingly.
Key pages cannot be deleted or duplicated. The address of a published page is locked, so a stray edit cannot break existing links. A page cannot exist without a language. Required fields are validated before publishing. The CMS menu is grouped by meaning — pages, blog, reference data, settings — and subtopics sit inside their pillar pages.
The Italian and English versions of a page are paired. The menu shows one entry per page, and the English version opens from inside the document.
Edits are visible before they go live: the owner opens the draft on the page itself and clicks a piece of text to jump to the field behind it. Header, footer and navigation are editable too. After publishing, changes appear within seconds without a developer, and the sitemap updates with them.
Designing for an anxious visitor: calm instead of calls to action
Templates were off the table from the start: the design is fully custom, built on open-licensed fonts and resources. The home page was signed off block by block — Giuseppe reviewed each one and only then did the next begin. The palette was his own suggestion and became the basis of the theme.
The site is dark by default: a deep green-black background, ivory text, champagne and bronze accents. Individual sections are light and let the eye rest. Headlines are set in EB Garamond with a true italic, body text in Source Sans 3, both served from the site itself rather than an external service.
There are no counters, promo bars or aggressive buttons. Instead there are blocks that answer questions before a person decides to write. "Ti riconosci?" ("Do you recognise yourself?") lists the sentences Giuseppe hears in his consulting room. "Il percorso" lays out four steps of therapy, from the first message to independence, behind large translucent numerals. The video about a first session only plays on click. Entrance animations switch off for visitors whose system asks for reduced motion.
Text contrast measured against WCAG AA, not judged by eye
Contrast was calculated. The client's original accent colour gave 3.95:1 on the light background, where body text needs at least 4.5:1. For text the colour was darkened slightly, to 4.58:1. Champagne gold reaches only 2.35:1 on light, so it is used there for decorative rules and never for text.
Map of the consulting rooms in Milan, Monza and Cernusco sul Naviglio
Four consulting rooms — two in Milan, one each in Monza and Cernusco sul Naviglio — sit on a single map. Clicking a marker opens a card styled like the rest of the site; clicking an address in the list flies the map to it. The base map is light and minimal, in keeping with the design.
Speed and hosting: Next.js, Vercel and images from the Sanity CDN
The site runs on Next.js 16, hosted on Vercel, with texts and images in Sanity. Images are served straight from the Sanity CDN at the size each screen needs and load as the visitor scrolls. An image is never upscaled beyond the size of the original file.
That choice had a concrete cause: Vercel's image transformation quota ran out and the blog illustrations disappeared. Moving to the Sanity CDN brought them back immediately, without waiting for the quota to reset.
Enquiries from the site: mail that stays out of spam and consent-first analytics
The contact form sends mail through the client's own domain. SPF, DKIM and DMARC are configured, so messages from the site do not look suspicious and do not land in spam.
Analytics only starts once the visitor consents to cookies; before that, nothing is sent. On a psychotherapist's website, where people arrive with private questions, that is not a formality.
Handing the site over: a manual in two languages and video walkthroughs
The owner's manual runs to 69 pages in English and 71 in Italian, with 23 screenshots, set in the site's own colours and typefaces, in DOCX and PDF. The Italian edition is written in the formal register and includes a chapter on deontology that cites article 40.
Alongside the manual I recorded short videos covering the edits he makes most often.
The CMS and the data belong to the client's own account. The content is entirely in his hands and does not depend on the developer.
Support after handover: a Search Console review and 16 redirects for duplicates
After delivery and payment I went through the Search Console reports at no charge: 571 URLs in the coverage reports.
The cause of the duplicates turned out to be structural — every permanent page answered on four addresses instead of two, an Italian slug under /en and the other way round. I added 16 permanent redirects. They are generated automatically from the site's route map and covered by a test with 27 assertions, so a new page cannot recreate the problem.
The old WordPress tail was cleaned up at the same time, the blog images were restored, and an obsolete section was removed from the CMS because editing it changed nothing on the site.
What the psychotherapist said about the project
Giuseppe left a five-star review on my Google profile. Quoted in full:
I found Aliaksandr through ChatGPT, and working with him was a very good decision. He rebuilt my website from scratch in Italian and English with a custom design that reflects my approach and my practice. We worked block by block: he proposed solutions, listened to my feedback and adjusted everything until it felt right. He moved all the articles from my old blog to the new site without losing the existing links, and set up an admin panel where I can edit texts myself. He also recorded short videos showing me how. Beyond development, he knows SEO and AI search: my new pages already appear in ChatGPT answers. Reliable, precise and always available. I recommend him.









