Privacy Policy
Last updated: 7 July 2026
This is the privacy policy for matteospinelli.com — a personal portfolio site. It explains, in plain language, what personal data the site processes, why, on what legal basis, who helps process it, and what rights you have. I have tried to keep it honest and specific rather than generic: the site collects very little, stores almost nothing itself, and uses no tracking cookies.
Who we are
The data controller for this site is Matteo Spinelli, based in Bonn, Germany. For any question about this policy or your personal data, write to me@matteospinelli.com. There is no separate Data Protection Officer; I handle data protection matters personally.
What data we collect and why
The site has four surfaces that can involve personal data: web analytics, the contact form, the chatbot, and the booking form. Note that the booking form is currently not enabled on the live site — the code exists but the interface is hidden — so in normal use web analytics, the contact form, and the chatbot are active. Booking is documented here for completeness.
1. Web analytics
- What we collect: page path/title, referrer, browser/OS/device type, screen size and language, and an approximate country derived on the server from your IP — after which the raw IP is discarded and never stored. Visits are grouped with a daily-rotating hash, not a cookie, so there is no identifier that follows you across days or sites.
- Purpose: to understand, in aggregate, which pages are visited and how the site performs.
- Lawful basis: Art. 6(1)(f) GDPR (legitimate interest). The analytics are cookieless and write nothing to your device, so no consent banner is required; the script also honours your browser's 'Do Not Track' signal.
- Processor: a self-hosted Umami instance I operate (umami.phalanthus.com). This is first-party infrastructure under my control — not a third-party service like Google Analytics, and no adtech or cross-site tracking is involved.
- Retention: only aggregate metrics, kept in the self-hosted Umami database for as long as they remain useful. No raw IP, no cross-site profile, no personal identifier.
2. Contact form
- What we collect: your name, email address, the area(s) of interest you tick (AI, strategy, or green), your message, and the interface language. Your IP address is read only to apply rate-limiting and is not included in the email. A hidden anti-spam field (honeypot) is discarded immediately.
- Purpose: to let you send me a message. The server renders it into an email and sends it only to my own inbox, with your name and email on 'reply-to' so I can write back. Your message is not sent to any address you supply.
- Lawful basis: Art. 6(1)(b) (steps at your request before any contract) and/or Art. 6(1)(f) (legitimate interest in responding).
- Processor: Resend (a transactional email service) delivers the message; my mailbox provider then receives and stores it. In local development, emails are printed to a console log and no third party is involved.
- Retention: the website itself stores nothing — there is no database write. Your message lives in my mailbox until I delete it, and in Resend's delivery logs per Resend's retention. The only short-lived technical record is a rate-limit counter that auto-expires within 120 seconds.
3. Booking (currently disabled on the live site)
- What we collect: your name, email, optional company, optional notes, the time slot you choose, your time zone, and interface language. Your IP is used only for rate-limiting; the hidden anti-spam field is discarded.
- Purpose: to let you book a call. The request is forwarded to Cal.com, which creates the booking, writes it to my connected calendar, and sends its own confirmation email. Looking up available slots involves no personal data.
- Lawful basis: Art. 6(1)(b) and/or Art. 6(1)(f).
- Processor: Cal.com (scheduling) and the calendar connected to my Cal.com account.
- Retention: the website stores nothing. The booking record is retained by Cal.com and in my calendar, per their retention. Only the 120-second rate-limit counter is transient state.
4. Chatbot
- What we collect: the messages you type and a language hint. Whatever you choose to put in those messages is processed — please don't paste sensitive personal data. Your IP is used only for rate-limiting and is not sent to the language-model provider.
- Purpose: a small assistant that answers questions about my CV and career. The server combines your messages with a fixed, static copy of my CV and asks a language model for a reply, streamed back to you. There are no external lookups or agentic tools.
- Lawful basis: Art. 6(1)(f) (legitimate interest in answering questions about my background).
- Processor: Scaleway Generative APIs (serverless LLM inference). Scaleway is based in the EU (France), so this processing does not leave the EU.
- Retention: conversations are not stored — there is no database or log of your message content anywhere. The only thing recorded per interaction is a small, aggregate, non-personal telemetry data point (call status, language hint, model name, token counts and estimated cost) used to monitor usage and cost. It contains no message content and no personal data.
Cookies
This site does not use cookies — none for tracking, advertising, or analytics, and there is no cookie consent banner because there is nothing to consent to under the ePrivacy/cookie rules. The analytics (Umami) are cookieless, write nothing to your device, identify visits only via a daily-rotating server-side hash, and honour 'Do Not Track'. The only browser storage the site uses is a single localStorage flag that enforces a short (60-second) cooldown on the contact form to deter spam — strictly necessary for that anti-spam function, holding no personal data and used for no tracking.
Third-party processors & international transfers
I rely on a small number of service providers to run the site. Some are based in the United States; I am honest about that here. Where personal data leaves the EU/EEA to a US provider, that transfer is covered by appropriate safeguards under Chapter V GDPR — in practice, Standard Contractual Clauses (Art. 46) and the providers' own data-processing terms.
| Processor | Purpose | Location | Transfer safeguard |
|---|---|---|---|
| Self-hosted Umami | Web analytics (first-party, aggregate, cookieless) | EU-hosted, operator-controlled | First-party — no third-party transfer |
| Resend, Inc. | Sends the contact-form email | United States | Standard Contractual Clauses (Art. 46) |
| Cal.com, Inc. | Booking (currently disabled) | United States | Standard Contractual Clauses (Art. 46) |
| Scaleway | Chatbot inference | EU (France) | Stays in the EU — none needed |
| Cloudflare | Hosting, CDN/edge, abuse-prevention, aggregate telemetry | Global edge (US-HQ) | Standard Contractual Clauses (Art. 46), as applicable |
My mailbox provider (where my email is hosted) also stores contact-form messages once delivered. No advertising networks, data brokers, or cross-site trackers are used.
Data retention
The application itself does not run a database and does not persist your content. In summary:
- Contact messages: kept in my inbox until I delete them, and in Resend's delivery logs per Resend's retention.
- Bookings (disabled): kept by Cal.com and in my connected calendar, per their retention.
- Chatbot conversations: not stored at all; only aggregate, non-personal usage telemetry is recorded.
- Analytics: aggregate metrics only, in the self-hosted Umami database.
- Rate-limit records: your IP is held very briefly (a counter that auto-expires within 120 seconds) to prevent abuse, then discarded.
Your rights
Under the GDPR you have the right to:
- Access the personal data I hold about you (Art. 15);
- Rectify inaccurate or incomplete data (Art. 16);
- Erasure — ask me to delete your data (Art. 17);
- Restrict processing in certain circumstances (Art. 18);
- Object to processing based on legitimate interest (Art. 21);
- Data portability — receive your data in a structured, machine-readable format (Art. 20);
- Withdraw consent at any time, where processing is based on consent (it generally is not here).
To exercise any of these, just email me@matteospinelli.com. I will respond within the time limits the GDPR requires. Because I store so little, the fastest route is often simply to ask me to delete the email you sent.
You also have the right to lodge a complaint with a data protection supervisory authority. As the controller is based in Bonn, the competent German authority is the one for North Rhine-Westphalia (Landesbeauftragte für Datenschutz und Informationsfreiheit Nordrhein-Westfalen, LDI NRW). You may also complain to the authority where you live — for example, the Italian Garante per la protezione dei dati personali.
Security
- Encryption in transit via HTTPS, with HTTP Strict Transport Security (HSTS).
- Hardened response headers: X-Frame-Options DENY, X-Content-Type-Options nosniff, a strict Referrer-Policy, a restrictive Permissions-Policy (camera, microphone, geolocation and browsing-topics disabled), and Cross-Origin-Opener-Policy same-origin. A Content-Security-Policy is in place (currently report-only and being moved to fully enforcing).
- Strict server-side validation of every form field, with length limits, header-injection guards, and HTML escaping of anything that ends up in an email.
- Abuse protection: per-IP rate-limiting on all API routes, hidden anti-spam fields, and an origin allow-list (CORS) restricting API calls to this site's own domains.
- Minimal footprint: no application database, so there is no large store of personal data to breach.
No system can be guaranteed perfectly secure, but the design goal here is to collect and retain as little as possible in the first place.
Changes to this policy
I may update this policy from time to time — for example, if I enable the booking or chatbot features, or change a service provider. When I do, I will revise the 'Last updated' date. Material changes will be reflected on this page.