There's a recurring temptation when building a tool that has to give someone a number: throw a language model at it and ask it to estimate. With Ristrutturazioni Preventivi, a platform giving an instant renovation cost estimate for Rome, we made the opposite choice.
Research before a single line of code
A detail often skipped when telling the story of an AI-built project: before designing the form, we studied the sector, checking every claim against a real source, not with a generic "do me a market analysis" prompt. Rulings from Italy's antitrust authority, administrative court decisions, data-protection authority sanctions, market data from the national construction research body. Ask an unchecked language model "what are the problems with online renovation-quote comparators" and you get a plausible but often generic answer, sometimes wrong in the details. Our path was the opposite: research with verifiable sources first, then AI to organize what we had already found, not to invent it. The knowledge graph in the VibeCoded Orchestrator preserves exactly this: not just the conclusion, but the source behind every claim.
That research surfaced concrete, non-theoretical patterns. More than one competitor in the sector has been sanctioned for unfair commercial practices or non-genuine reviews, with rulings upheld on appeal. Another case, documented by the data-protection authority, involved exactly the single-consent-for-multiple-purposes issue we cover below. Precedents an authority has actually established, which shaped specific choices in the project.
No AI for the numbers
The quote calculator runs on closed parameters: square meters, type of work (full renovation, partial, bathroom, kitchen, windows, roof), number of bathrooms. No free-text field, no open question. The user follows a guided path of predefined answers, and ends up with an estimate calculated on real prices from Rome construction sites, collected with a Rome-based architect who follows work on the ground.
An LLM here would have introduced a specific problem: variance. Ask the same renovation twice to a language model, even with the same prompt, and you can get two different ranges, because it generates plausible text, not a deterministic calculation against a verified price table. For a number the user will carry into a real conversation with a professional, that variance is a defect. The closed-answer path removes the ambiguity at the source: same parameters, same estimate, every time. And a quote built on real prices, collected by people who actually follow the construction sites, is easier to defend when the user asks "where does this number come from" than an estimate with no declared source.
A stack built for a service used once
Behind the form is Next.js 16 on Vercel, with Supabase as the database and Resend for email notifications. There's no app to download, and no account area for whoever fills out the form: the service is meant to be used once, leave your details, and be contacted back by an architect. No account, no password, no state to check: the request goes out, and the conversation continues elsewhere.
The consequence is direct on the architecture: no authentication, no persistent user session, less surface to maintain for a use case that, by definition, doesn't need a history.
Guides that publish themselves, one a week
Beyond the quote calculator, the site publishes price guides (full renovation, bathroom, windows, roof, how to read a quote) on a weekly cadence. Publishing is scheduled: an editorial calendar lives in a TypeScript file in the repository, not in an external panel, and a GitHub cron script checks which guides are "ripe" (meaning their scheduled publish date has arrived) and triggers a deploy hook only for those.
The less obvious detail is the timezone. A GitHub Actions cron runs in UTC by default, and a guide scheduled for "Monday morning" in UTC can go live at midnight or 1am Italian time, depending on daylight saving. The fix is converting explicitly to Europe/Rome before comparing the date against the guide's, instead of comparing raw timestamps: a bug you won't notice in development, because locally you test during the day, and it only surfaces when a guide ships at 2am instead of 9am.
GDPR: two consents, not one
The form collects personal data for two distinct purposes: being contacted back by an architect, and potentially being put in touch with a contractor. These are two different processing activities, and we keep them separate: two distinct consent checkboxes, each timestamped at submission, instead of one consent covering both purposes.
The reason isn't theoretical, as seen above: a consent that asks "do you agree to everything" for different purposes is exactly the kind of practice an authority has already sanctioned a player in this sector for. Separating them costs two extra checkboxes, and removes the ambiguity over what the user actually agreed to.
Cookie-free analytics
No Google Analytics, no cookie banner for tracking. The events that matter (which step of the form a user drops off at, whether they reach the end) are Vercel Analytics events, with no profiling cookies and no consent required. You lose the depth of a properly configured GA4, but for understanding where the funnel loses people, it's enough.
If a similar approach interests you, the updated price guide is at ristrutturazionipreventivi.it/quanto-costa. A different angle on the same theme, SEO for a local craftsman, is in the case study on a carpentry site.