Legal
Privacy notice
This notice explains what Shoppingo collects, why, where it is stored and what you can do with it. It applies to shoppingo.imapps.uk (the landing site) and the hosted app that lives under the same domain.
Last updated: 2026-10-18.
Who runs Shoppingo
Shoppingo is an open-source project. The hosted version at shoppingo-app.imapps.uk is operated by the project maintainer as a small personal service. It is not a commercial product.
- Controller
- The maintainer of the Shoppingo repository.
- Contact
- igorsiergiej@gmail.com
- Supervisory authority
- Information Commissioner’s Office (ico.org.uk) for UK residents; the equivalent authority in your country if you live elsewhere.
What we collect
The table below lists every category of personal data the hosted stack handles. It is rebuilt from the same inventory used by shoppingo-gdpr-sweep; the wording is deliberately close to that document so the two stay in sync.
| Category | Source | What is stored | Why |
|---|---|---|---|
| Account credentials | kivo (the auth service) | Username and argon2id password hash; refresh token held in an httpOnly cookie. | To run the service for the account holder. |
| Session telemetry | kivo | Username on failed logins (no password). Sessions have a TTL. | Abuse detection and session management. |
| User data in MongoDB | shoppingo-api | Lists, recipes, todos, labels, meal plans, push subscriptions, friendships, pairing codes, Discover publications and reports, item categories. | To provide the app’s features to the account holder. |
| Uploaded photos | MinIO (object store) | Recipe and item photos uploaded by users. | To attach images to recipes and list items. |
| Front-end logs | Loki | userId, userAgent, URL and server-observed clientIp. No list-item text, recipe text or transcripts. | Operational debugging and abuse response. |
| Voice transcripts and AI requests | fal.ai | Speech-to-text transcripts from voice input, recipe-import text, substitution/categorisation requests and image prompts. | To convert voice and links into structured items and recipes. |
| Push notifications | FCM (Android) / Mozilla autopush (Firefox) | Push endpoint and the notification payload. | To deliver reminders and shared-list updates to opted-in devices. |
| Network traffic | Cloudflare (tunnel and proxy) | Every request that reaches the hosted stack. | Routing, DDoS protection and caching. |
| Aggregate analytics | Self-hosted Umami | Page views and referrers on shoppingo.imapps.uk and the hosted app. No personal identifiers. | To measure which parts of the product are used. |
| Public Discover publications | shoppingo-api | The username is shown only if the user ticks “show name”; the cover photo is copied to a public key. | To make shared recipes findable in Discover. |
| Display fonts | Bundled (Bricolage Grotesque and Montserrat Variable via @fontsource) | Font files served from the site’s own origin. No third-party font CDN is contacted. | Typography without sending visitor IP to a font provider. |
Why we collect it (lawful basis)
Each purpose has a lawful basis under the UK GDPR. Where processing rests on consent, that consent is collected in-app before any data is sent to the third party.
| Purpose | Lawful basis | Notes |
|---|---|---|
| Running the service (lists, recipes, meal plans, sharing, push notifications) | Contract | Processing is required to deliver what the account holder signed up for. |
| Authentication telemetry and operational logs | Legitimate interests | Needed to keep the service secure and operable. No special-category data. |
| Aggregate analytics on the hosted sites | Statistical exception (UK GDPR §4(2)), with opt-out | Self-hosted Umami produces aggregate reports. The opt-out switch lives in app Settings (owned by shoppingo-gdpr-sweep). |
| Session replay and any identified analytics | Consent | Off by default. shoppingo-gdpr-sweep prompts once and stores the choice. |
| Voice transcripts sent to fal.ai | Consent (explicit, one-time prompt at first microphone use) | The microphone is not opened until the user accepts. |
Processors and where data goes
The hosted stack uses a small number of processors. Each is listed with what they do, where they sit, the transfer mechanism used for any cross-border data flow, and the data they see.
| Processor | Role | Location | Transfer mechanism | Data seen |
|---|---|---|---|---|
| fal.ai | Speech-to-text and generative models for voice input, recipe import, substitution, categorisation and image generation. | United States | EU Standard Contractual Clauses and an executed DPA. | Voice transcripts, recipe-import text, prompts derived from user content. No account credentials. |
| Cloudflare | Tunnel, proxy, caching and DDoS protection in front of the hosted stack. | United States / global edge | EU SCCs and ongoing adequacy decisions where applicable. | Every request reaching shoppingo.imapps.uk and the hosted app. |
| Google Firebase Cloud Messaging (FCM) | Delivery of push notifications on Android. | United States | EU SCCs (Google Cloud DPA). | Push token and notification payload. |
| Mozilla autopush | Delivery of push notifications on Firefox. | United States | EU SCCs (Mozilla DPA). | Push token and notification payload. |
| Self-hosted Umami | Aggregate, cookie-less analytics on shoppingo.imapps.uk and the hosted app. | Server in the EU (imapps.uk) | No transfer — self-hosted. | Page path, referrer, country (derived from IP), browser family. No personal identifiers. |
| Self-hosted Loki | Front-end log retention and search. | Server in the EU (imapps.uk) | No transfer — self-hosted. | userId, userAgent, URL, server-observed clientIp. |
| Self-hosted MinIO | Object storage for user-uploaded photos. | Server in the EU (imapps.uk) | No transfer — self-hosted. | Recipe and item photos uploaded by users. |
Google Fonts is no longer used. The bundled @fontsource-variable/bricolage-grotesque and@fontsource-variable/montserrat packages ship font files from the site’s own origin.
How long we keep it
Retention is the shortest the purpose allows. The values below mirror the operational configuration of the hosted stack.
| Item | Retention | Where it is set |
|---|---|---|
| Front-end logs (Loki) | 30 days | foundry/monitoring/config/loki/loki.yml retention_period: 30d |
| MongoDB backups (mongodump) | Until pruned at RETENTION_DAYS | foundry/docs/homelab.md — nightly mongodump; MinIO is not backed up. |
| Account data and content | Until the user closes their account | shoppingo-gdpr-sweep will add account deletion (typed confirmation) and data export. |
| Umami aggregate analytics | As configured on the Umami instance | Self-hosted Umami retention setting. |
| Session replays | 30 days | shoppingo-gdpr-sweep — replay storage TBD by that task. |
| Fal.ai inputs | Per fal.ai’s published retention | fal.ai DPA — confirmed before activation. |
Your rights and how to use them
The UK GDPR gives you the rights below. Exercising them is free and we reply within one calendar month. Where the request is complex, we may write to extend that by up to two further months and explain why.
| Right | What it means |
|---|---|
| Access | A copy of the personal data we hold about you. |
| Rectification | Correction of inaccurate or incomplete data. |
| Erasure | Deletion of your account and associated content (lists, recipes, photos, friendships, publications). Account deletion will require a typed confirmation and is being added by shoppingo-gdpr-sweep. |
| Restriction | Pausing processing while a complaint or query is resolved. |
| Portability | A JSON download of your lists, items, recipes, meal plans, todos and friends. Provided by shoppingo-gdpr-sweep. |
| Objection | Right to object to processing based on legitimate interests, including aggregate analytics. |
| Withdraw consent | Where processing rests on consent (session replays, microphone access), you can withdraw it at any time. |
| Complain | Right to lodge a complaint with the Information Commissioner’s Office (ico.org.uk) if you believe your data has been handled incorrectly. |
To exercise any of these rights, email igorsiergiej@gmail.comfrom the address on your account. For deletion and data export, the in-app controls underSettings → Account are the fastest path once shoppingo-gdpr-sweep ships.
Cookies and local storage
Cookies are kept to the minimum: one strictly necessary for authentication, and one that sends returning users from this landing page straight to the app. Everything else is local storage on the user’s device, which the user can clear at any time.
| Name | Kind | Purpose | Lifetime |
|---|---|---|---|
| kivo refresh-token cookie | Strictly necessary cookie | Holds the signed refresh token used to mint access tokens. httpOnly, Secure, SameSite=Strict. | Rolling; expires when the session ends or is revoked. |
| shoppingo_app | Functional cookie | Set by the app after you sign in, on imapps.uk (the parent domain of the app and this site), so visiting shoppingo.imapps.uk takes you straight to the app instead of this landing page. Holds no identifier, only the value 1. | 1 year. |
| shoppingo:config | localStorage | Persisted UI preferences (e.g. tutorial completion flags). | Until cleared by the user. |
| theme | localStorage | User-chosen colour theme (light / dark / system). | Until cleared by the user. |
| unitSystem | localStorage | Metric or imperial units shown across the app. | Until cleared by the user. |
| shoppingo.voiceKeepListening | localStorage | Whether voice input stays open after a successful transcript. | Until cleared by the user. |
| release-notes-seen | localStorage | Records which in-app release notes have already been shown. | Until cleared by the user. |
| Umami session | Cookie-less | Aggregate analytics visit grouping. Held only on the self-hosted Umami instance. | Session. |
Changes to this notice
Material changes are listed at the top with the date they take effect, and the in-app release notes link here when something you can act on changes. Earlier versions are kept in thesite repository.