DOCS · UPDATED 29 SEPTEMBER 2026
Put a Valnivo widget on your site
Financial calculators, each one line on your page. No account, no key, no bill, and nothing your visitor types reaches us. Every one runs live in the library below, beside the line that embeds it.
Nothing to install or sign up for. Your visitor's figures never leave their browser,
and a widget sets no cookie and stores nothing there. Framed from valnivo.eu, the widget
is still a request to our host, which sees it as any server does — an IP address and the usual
request details, as our privacy notice describes — so your own notice may
need to mention it; the standalone package makes no request at all. Parameters are
only ever added, never renamed — see what will not break.
§ One line, and you are done
<script src="https://valnivo.eu/valnivo.js"
data-valnivo="projection" data-currency="EUR" data-locale="fr-LU"></script>
The widget appears where the tag sits. Swap projection for any name in
the library and add that widget's parameters as data- attributes.
The loader builds the frame and keeps it the height of its contents — 7 kB, no dependencies, and
its address never changes.
Or have it written for you: the configurator ticks calculators, sets currency, language and accent, and hands you the finished line.
Not a screenshot: the loader inserted that frame from the tag above, and it sized itself.
§ Several of them, in one frame
Four separate embeds boot four copies of React: measured here, 1,242 KB of JavaScript against 346 KB for the same four in one frame. So one widget holds the others:
<div data-valnivo="page" data-widgets="projection:6,loan:6,emergency:12"></div>
<script src="https://valnivo.eu/valnivo.js"></script>
| Name | What it does | Default |
|---|---|---|
widgets |
Which calculators, in what order, and how wide — name:width, comma separated.
The width is in twelfths and may be 4, 6, 8 or
12; anything else, or a name left bare, is full width. Below about 760px they all
stack. A name we do not have is ignored rather than guessed at, and a calculator named twice
appears once.
A row always fills. Widths decide who sits beside whom — two at 6, or 8 beside 4 — and whatever is left over is shared
out, so mortgage:8,rentvsbuy:8 draws as two full-width rows rather than two
thirds of one each with the last third empty. fit=0 keeps the older behaviour,
where a width was an absolute span and a short row was left short.
|
projection:12 |
Every shared parameter applies to the whole page — one currency, one language, one theme, one accent, one licence. Each calculator's code is fetched only if you placed it, so a page of two ships two.
Opening each calculator on your own figures
Prefix any parameter with the calculator's name and a dot, and it reaches that one and no other:
<div data-valnivo="page"
data-widgets="mortgage:6,rentvsbuy:6,cashvsmortgage:12,projection:12"
data-mortgage.price="600000"
data-mortgage.rate="3.2"
data-rentvsbuy.rent="2200"
data-projection.save="1500"></div>
<script src="https://valnivo.eu/valnivo.js"></script>
Or, as an address:
https://valnivo.eu/embed/page.html?widgets=mortgage:6,rentvsbuy:6,cashvsmortgage:12,projection:12&mortgage.price=600000&projection.save=1500
A bare name reaches nobody on a composed page, deliberately. years
belongs to nine of these calculators, rate to four and amount to three, so
?years=20 would set all of them at once. On a page of a single calculator both
forms work. Ranges and defaults are unchanged by a prefix; a prefix naming a calculator you did not
place says so once in the console. Currency, language, theme, accent and read-only belong to the page:
one frame is one of each.
When not to use it. One frame is one block — you cannot put your own heading between two calculators inside it. For that, give each its own frame.
§ Sending somebody the answer
Every embed carries a Share these figures link in the corner. It hands back the address of the same calculator, or the same arrangement, with the figures the visitor has moved it to:
https://valnivo.eu/embed/mortgage.html?price=620000&rate=3.4&years=25&upkeep=310
Same names as opening on your own figures, so a shared link pastes straight
back into a data- attribute.
It is a link before it is a button. A frame may only write to the clipboard if the page
holding it allowed that, and most of the iframes in the world holding these widgets were written before
this existed — so clicking copies where it can and opens the scenario in a new tab where it cannot. If
you frame the widgets by hand rather than with the loader and want the copy to
work, add allow="clipboard-write" to your iframe; the loader does it for you.
The licence is never in the link, because a link is a thing people forward and a licence
is a credential. Nothing about the visitor is in it either: it carries figures they typed, and it is made
in their browser — we are not told that it was made, and there is nothing on our side that holds it. A
widget posts its height to the page framing it and nothing else, so embedding one never gives a
host a way to read what a visitor types.
The configurator works from the other end: tune its preview, and its link, snippet and frames all carry those figures.
§ Ready-made arrangements
The page widget with its calculators already chosen. Each is one address — copy it, open it, or take it into the configurator. Each carries its own Share these figures link.
An arrangement places calculators; it does not join them up. Each still stands on its own figures, and nothing carries a total from one into the next.
They arrange; they do not advise. Each is the same calculators documented below, in one frame, each still carrying the same line inside it: an illustration built on the figures your visitor typed, not a forecast or advice. An arrangement recommends no course, names no product and ranks no option.
mortgage:6,rentvsbuy:6,cashvsmortgage:12,projection:12
debt:6,loan:6,projection:12
networth:6,retirement:6,sequence:12
crossborder:6,emergency:6,projection:12
breakeven:6,vat:6,roi:12
networth:6,flow:6,projection:12
The first of them, running here as one frame, which is exactly what the snippet under it puts on your page:
Three calculators, one frame, one Valnivo mark — and one copy of React.
<div data-valnivo="page" data-widgets="mortgage:6,rentvsbuy:6,cashvsmortgage:12,projection:12"></div>
<script src="https://valnivo.eu/valnivo.js"></script>
Only the first runs here; the other five are links, and every calculator in them is live further down.
Changing one is editing widgets: drop a name, add one from
the library, or change a width. None includes the inflation table
— it needs countries= to be a sensible size, and a composed page takes no per-calculator
parameters, so give it its own frame.
§ Steering the loader
Three data- attributes are the loader's own; every other one is passed to the widget as a
query parameter, which is why a parameter added later needs no new loader.
| Attribute | What it does | Default |
|---|---|---|
data-valnivo |
Which widget — any name from the library. Required. | — |
data-height |
The height to start at, in pixels, before the widget reports its real one. It only decides whether there is a jump on load. | 420 |
data-title |
The frame's accessible name, read by a screen reader in place of "Valnivo projection". | Valnivo <widget> |
A container instead of the script tag, to place the widget yourself or to take several from one script:
<div data-valnivo="goal" data-currency="CHF" data-target="80000" data-years="15"></div>
<div data-valnivo="inflation" data-countries="LU,BE,FR" data-height="300"></div>
<script src="https://valnivo.eu/valnivo.js"></script>
Every [data-valnivo] is framed once. Two copies of the same widget size independently —
the loader tells frames apart by which one spoke.
If your page renders after the script runs (React, Vue, Angular, htmx), call the loader again; it skips anything already framed:
window.Valnivo.mountAll() // everything not yet framed
window.Valnivo.mount(element) // one element you hold a reference to
window.Valnivo also carries origin, version and
embedUrl(widget, params) if you want the address without the frame. Loading the script
twice is a no-op — the first copy keeps the page.
The loader does three things and no more: it reads your attributes, inserts an
iframe and applies a height. No cookie, no storage, no request of its own — the frame carries
referrerpolicy="no-referrer", so your page's address never reaches us, and everything
that computes lives inside the frame where our CSS cannot touch yours.
§ Or a plain iframe
The loader is a convenience, not a requirement — write the frame yourself if you would rather ship no third-party JavaScript:
<iframe
src="https://valnivo.eu/embed/projection.html?currency=EUR&locale=fr-LU"
title="Valnivo projection"
loading="lazy"
style="width:100%;border:0;height:420px"
></iframe>
That works on its own; it just cannot resize itself until you listen for its height. Every preview below is a plain iframe like this one.
§ Or install it
Two packages, for the two cases where a script tag is awkward: a build that would rather import a component, and a site whose editor should never meet code.
npm, for React, Vue, Angular and anything else
npm install @valnivo_labs/widgets
See it running — every calculator on that page is rendered by the package, in the page, with a counter showing the requests it makes after load.
Two modes, and the difference matters. standalone puts the calculator
itself in your page and makes no request of any kind — no frame, no fetch, no font.
If valnivo.eu stopped answering tomorrow, a page built on it would carry on working.
Without it, the package builds the same iframe the loader does, which is a
kilobyte instead of 54 and takes a correction to a model the day it ships rather than when you
update. Pick standalone when the page must not depend on us; pick framed when you would rather not
think about updates.
// React
import { ValnivoWidget } from '@valnivo_labs/widgets/react'
<ValnivoWidget widget="projection" params={{ currency: 'EUR', have: 40000 }} />
// Vue 3
import { ValnivoWidget } from '@valnivo_labs/widgets/vue'
<ValnivoWidget widget="loan" :params="{ currency: 'EUR', years: 7 }" />
// Angular — a custom element, so no compiler is involved and an AOT build is fine.
// import '@valnivo_labs/widgets/angular' once, then CUSTOM_ELEMENTS_SCHEMA in the component.
<valnivo-widget widget="mortgage" [params]="figures"></valnivo-widget>
// Anything else
import { mount } from '@valnivo_labs/widgets'
const handle = mount(el, { widget: 'projection', params: { currency: 'EUR' } })
handle.update({ have: 50000 }) // re-points the frame; the height follows
handle.destroy()
// Standalone: the calculator itself, no network at all.
import { render } from '@valnivo_labs/widgets/standalone'
const handle = render(el, { widget: 'projection', params: { have: 40000 }, currency: 'EUR', lang: 'fr' })
// Or as a prop, in any of the wrappers above:
<ValnivoWidget standalone widget="projection" params={{ have: 40000 }} />
<valnivo-widget standalone widget="mortgage" currency="EUR"></valnivo-widget>
An npm package live — params takes any name
from the shared parameters or the calculator's own table, and there is one
implementation of every calculation behind both modes, so they cannot disagree about an answer.
Standalone renders into a closed shadow root: our styles cannot reach your page,
yours cannot reach ours, and the Valnivo mark and each calculator's illustration line sit inside it
where nothing on your page can take them out — a white-label licence
is still the one way the mark comes off. The bundle is fetched only if you ask for
standalone, so a page that frames carries none of it — and its translations travel
inside it too, one small chunk per language loaded only when lang asks for it, so a
page has one language and the words need no request either.
Where it runs
| Environment | Framed | Standalone |
|---|---|---|
| React 17, 18, 19 | yes | React-DOM 18+ (createRoot) |
| Vue 3.0 – 3.5 | yes | yes |
Angular 2 – 21, as <valnivo-widget> with CUSTOM_ELEMENTS_SCHEMA | yes | yes |
| Svelte, Solid, Lit, Astro, plain HTML — the same element | yes | yes |
| Next.js, Nuxt, SvelteKit | on the client | on the client |
| Server rendering | Both render on hydration; neither draws HTML on the server. | |
| Browsers | anything with <iframe> | shadow DOM: Chrome/Edge 53+, Firefox 63+, Safari 10+ |
| WordPress, Webflow, Squarespace, Ghost | Use the plugin or the loader; neither needs npm. | |
React, React-DOM and Vue are optional peer dependencies — install only the one your project already has, and the custom element needs none of them.
WordPress
valnivo-calculators.zip · version 0.2.3 · 7.6 kB · SHA-256
235efa894bfe85aee437ee85b0d8de12ae02422d80b5ca3f5313f8ca356f1bf9. Upload it under
Plugins → Add New → Upload Plugin, activate, and a Valnivo calculator block is in the
inserter — which calculator, currency, language, locale, theme, accent, height and a figures field, all as
sidebar fields. For classic editors and page builders there is a shortcode:
[valnivo widget="mortgage" currency="EUR" lang="fr" locale="fr-LU"]
[valnivo widget="loan" years="7" amount="20000"]
It carries no calculator of its own: the plugin emits the placeholder the loader fills, and loads the loader only on a page that shows one — so nothing new reaches us and there is no second implementation of anything. Served from this site rather than wordpress.org; it is four readable files. Webflow, Squarespace and Ghost need no plugin — each has an embed block that takes the one-line loader as it is. Drupal waits for somebody to ask.
§ Parameters every widget takes
| Name | What it does | Default |
|---|---|---|
currency |
Any ISO 4217 code — the currency figures are shown in. It changes the labels, not the arithmetic: nothing is converted except where a widget says so. | EUR |
locale |
A BCP 47 tag (fr-LU, de-CH, en-GB…) deciding how numbers are grouped and where the currency symbol sits. An unusable tag falls back rather than failing. |
en-GB |
lang |
The language of the widget's words: en, fr, de, es, it, pt, nl or pl. Separate from locale, which only formats numbers — so locale=fr-LU alone stays in English, and lang=fr is what changes the words. An unknown value falls back to English. On the loader it is data-lang; in the npm package, lang. |
en |
theme |
dark, light, or auto to follow your reader's own prefers-color-scheme and keep following it if they change it mid-visit. |
dark |
accent |
Your own accent, as six hex digits — leave the # off, since everything after a # in a URL is a fragment the browser never sends. Three digits work too. It colours the controls and the interaction states; see fitting your design for what it does not colour, and for when it is refused. |
Valnivo's violet |
readonly |
Shows the figures and switches every control off — sliders, selects, preset
buttons. For a worked example on a page that is not meant to be played with, or for handing
somebody a layout to look at without their first slider drag making them think those are the
figures. It is a real disabled, so the keyboard cannot reach the controls either and
a screen reader announces them as disabled rather than as adjustable. Anything but
0, false, no or off switches it on. The
configurator offers it as a mode beside the link.
|
off — every embed is adjustable unless you say otherwise |
share |
A quiet Share these figures link in the frame's own corner, beside the mark. It
copies an address that reopens the calculator on the figures now on screen — so a visitor
who has moved the sliders can send somebody what they are looking at rather than a blank
calculator. Set share=0 to take it off. It is not drawn on a
white-label page: a licensed embed shows no Valnivo mark, so it
shows no link back to us either.
|
on |
Unknown parameters are ignored, and a number outside a widget's range is clamped into it rather than breaking the page. A name added here later cannot break an embed that does not use it.
§ The widget library
Grouped by the question they answer. They share the loader, the parameters, the resize message and the conditions of use, so once one is on your page, adding another means changing one word.
Seeing where money leads
projectionWhat you have today, what you put aside each month, and the total after 10, 20 and 30 years.
What if one thing changed? livescenarioTwo futures from one starting point: the one you are on, and the one where a single habit changes.
What could this grow into? livecompoundHow much of the result was put in against how much was earned, with charges as a knob of their own.
Which assumption matters most? livesensitivityEach of the five things a projection rests on moved alone, a stated amount either way, ranked by how much it moves the answer.
What did this grow at? livecagrTwo values and the years between them, as one rate a year.
What would it take? livegoalA goal read backwards: the monthly figure that gets there.
How long would your savings last? liveemergencyCash on one side, a month’s spending on the other, and how many months the first covers.
What paying the minimum really costs livecardminimumA card balance at its minimum against the same balance with a little more paid each month.
When does a fee for a lower rate pay for itself? livebuydownA fee paid up front against a rate lower for the whole term, and the month it pays for itself.
Where does your month go? liveflowWhat comes in and where it went, drawn as a flow. Money put aside is not spending.
What you own, less what you owe livenetworthA photograph, not a projection: nothing grows, nothing is discounted.
What could you retire on? liveretirementA pot grown to an age the visitor picks, and what it might pay out a month.
Does it matter when you retire? livesequenceWalks what the US stock market really did, once for every year somebody could have started.
Across borders
Borrowing
loanThe monthly payment, the interest, and what paying a little extra each month would change.
What would this home cost a month? livemortgageA price and a deposit, with upkeep, property tax and insurance added.
When would this be paid off? livedebtMonths to clear a balance, and a plain answer when the payment does not cover the interest.
Deciding between two courses
For a business
roiA firm’s own costs against its own estimate of time saved, and the month it breaks even.
How many do you have to sell? livebreakevenFixed costs against what a sale leaves behind, and the number of sales where the two meet.
VAT, both ways livevatAdd VAT to a net price or take it back out of a gross one.
SEEING WHERE MONEY LEADS
Projection live
Two sliders — what you have today, what you put aside each month — and the total after 10, 20 and 30 years in both future and today's prices, with the return and inflation assumptions on screen and adjustable.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/projection.html?currency=EUR&locale=fr-LU
| Name | What it does | Range | Default |
|---|---|---|---|
have | What the first slider opens on — money already put by. | 0–1 000 000 | 20 000 |
save | What the second slider opens on — put aside each month. | 0–10 000 | 500 |
rate | The return assumed each year after fees, as a percent. The visitor can still move it. | 0–15 | 5 |
inflation | The inflation assumed each year, as a percent, which is what today's-prices column divides by. | 0–15 | 2 |
Message name: projection. These four set where the sliders start and nothing
else: a visitor can move every one of them, which is the point of the widget. Added 13 September 2026
— before that this widget opened on its own figures and no others, so an embed that passes none
behaves exactly as it always has.
What if one thing changed? live
Two futures from one starting point: the one you are on, and the one where a single habit changes — put aside more, put aside less, or stop altogether. The difference is stated in both nominal and today's prices, over 10, 20 or 30 years.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/scenario.html?currency=EUR&locale=fr-LU&have=20000&monthly=500&change=200&years=20
| Name | What it does | Range | Default |
|---|---|---|---|
have | Starting pot, in whole units. | 0–200 000 | 20 000 |
monthly | What goes aside each month to begin with. | 0–3 000 | 500 |
change | The size of the change being tried, per month. | 0–1 000 | 200 |
years | Which of the three horizons opens selected. | 10, 20 or 30 | 20 |
knob | Which what-if it opens on: more, less or stop. Anything else opens on the first. | those three | more |
Message name: scenario.
What could this grow into? live
A starting sum, an amount each month, and — the reason to show this rather than a plain total — how much of the result was put in against how much was earned. Charges are a knob of their own, because a percent a year is the largest drag on a long horizon that anybody actually controls.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/compound.html?currency=EUR&locale=fr-LU&have=10000&monthly=300&years=20
| Name | What it does | Range | Default |
|---|---|---|---|
have | What the visitor starts with. | 0–250 000 | 10 000 |
monthly | Added each month. | 0–3 000 | 300 |
years | For how long. | 1–40 | 20 |
rate | The return assumed each year before fees, as a percent. The visitor can still move it. | 0–15 | 6 |
fee | The yearly charge taken off that return, as a percent. | 0–5 | 0.5 |
inflation | The inflation assumed each year, as a percent, for the today’s-prices figure. | 0–15 | 2 |
Message name: compound. Return, charges and inflation are sliders inside the widget, so a
reader can see what each one costs; the result is shown in both money of the day and today's prices.
Which assumption matters most? live
A starting sum and a monthly amount grown for some years, and then each of the five things the answer rests on — the return, inflation, the monthly amount, the years and the starting sum — moved alone, a stated amount either way, ranked by how much each moves the result. Every row names what it moved, because the order is a statement about those amounts and a reader who cannot see them is being handed a choice as a finding. Measured in today’s prices, since a nominal ranking puts inflation last with a swing of nothing. It says what the answer depends on — never which assumption is right.
Over a long horizon the return usually moves it most — which is the one nobody knows.
https://valnivo.eu/embed/sensitivity.html?currency=EUR&locale=fr-LU&have=20000&monthly=400&years=25&rate=6&inflation=2
| Name | What it does | Range | Default |
|---|---|---|---|
have | What there is to start with, in whole units. | 0–250 000 | 20 000 |
monthly | Added each month. | 0–3 000 | 400 |
years | How many years it grows for. | 4–40 | 25 |
rate | The return, as a percent a year. | 0–12 | 6 |
inflation | Inflation, as a percent a year, used to read the result in today’s prices. | 0–8 | 2 |
Message name: sensitivity. The moves are fixed and printed on every row: the return ±2 points,
inflation ±1 point, the monthly amount ±20%, the years ±3 and the starting sum ±10%. One
steady return, no charges and no tax; two assumptions moving together can be worse than either alone, which
one-at-a-time does not show and the frame says so.
What did this grow at? live
Two values and the years between them, as one rate a year — the only widget here that looks backwards, and it stops there: there is no button to carry the rate forward, because a past rate extended into the future is a forecast wearing a fact's clothes. Money put in or taken out along the way is part of the change, so this is the growth of a figure rather than a return earned, and it says so on its face.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/cagr.html?currency=EUR&locale=fr-LU&start=10000&end=18000&years=8
| Name | What it does | Range | Default |
|---|---|---|---|
start | What it was worth at the start, in whole units. | 0–500 000 | 10 000 |
end | What it is worth now. | 0–2 000 000 | 18 000 |
years | Years between the two figures. | 1–50 | 8 |
Message name: cagr.
What would it take? live
A goal read backwards: an amount, a number of years, what you have towards it, and the monthly figure that gets there — plus how much of the total is what you put in and how much is growth. It says "nothing" when the pot already grows past the target on its own, which is the honest answer.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/goal.html?currency=EUR&locale=fr-LU&target=50000&have=5000&years=10
| Name | What it does | Range | Default |
|---|---|---|---|
target | The figure being aimed at, in whole units. | 1 000–500 000 | 50 000 |
have | What is already there. | 0–200 000 | 5 000 |
years | How long there is. | 1–40 | 10 |
rate | The return assumed each year, as a percent. | 0–15 | 5 |
Message name: goal.
How long would your savings last? live
Cash on one side, a month's spending on the other, and how many months the first covers — plus the gap to whatever number of months the reader picks. No growth is assumed: this is money that has to be there on the day it is needed. It sets no target — "three to six months" is named as the convention it is, never as a recommendation.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/emergency.html?currency=EUR&locale=fr-LU&spend=2000&cash=4000&months=3
| Name | What it does | Range | Default |
|---|---|---|---|
spend | What a month costs, in whole units. | 200–10 000 | 2 000 |
cash | Cash that could be reached this week. | 0–100 000 | 4 000 |
months | How many months the reader wants covered. | 1–24 | 3 |
Message name: emergency.
What paying the minimum really costs live
A balance, its rate and the card’s own minimum — a percentage with a floor, both read off a statement — against the same balance with a little more paid each month. At an ordinary rate the minimum takes decades and costs more in interest than the balance, which is the figure it exists for. Where the minimum does not cover the interest it says the balance never falls rather than printing a very large number. It ranks nothing: no order to pay debts in, no consolidation, no rate called high or low.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/cardminimum.html?currency=EUR&locale=fr-LU&balance=2000&rate=19.9&percent=2&floor=25&extra=50
| Name | What it does | Range | Default |
|---|---|---|---|
balance | What is owed, in whole units. | 100–20 000 | 2 000 |
rate | The rate the card charges, per cent a year. | 0–40 | 19.9 |
percent | The card’s minimum, per cent of the balance. | 0.5–10 | 2 |
floor | The smallest minimum it will take. | 0–100 | 25 |
extra | Paid on top of the minimum each month. | 0–500 | 50 |
Message name: cardminimum.
When does a fee for a lower rate pay for itself? live
A fee paid up front against a rate lower for the whole term — points in the United States, an arrangement fee most other places. It answers the month it pays for itself rather than giving a verdict, because whether that is worth it turns on how long the loan is kept, which is the reader's fact. Where both rates give the same payment it says the fee does not repay. It names no lender, quotes no rate, and calls none good or bad.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/buydown.html?currency=EUR&locale=fr-LU&amount=250000&years=25&rate=3.9&lower=3.5&fee=2500
| Name | What it does | Range | Default |
|---|---|---|---|
amount | What is borrowed, in whole units. | 10 000–1 000 000 | 250 000 |
years | The term. | 1–40 | 25 |
rate | The rate without the fee, per cent a year. | 0–15 | 3.9 |
lower | The rate the fee buys. | 0–15 | 3.5 |
fee | What the lower rate costs up front. | 0–20 000 | 2 500 |
Message name: buydown.
Where does your month go? live
What comes in on one side and where it went on the other, drawn as a flow so the shape of a month is visible at a glance. The distinction it insists on: money put aside is not spending — a standing order to savings is drawn apart from the groceries, because it is still the reader's money. It always balances; outgoings above income appear as a source, "from what you already had", rather than as a negative bar.
It reads no file and asks for no statement. The figures are typed on the widget's own controls. A box on a page inviting somebody to drop a bank statement into it is a pattern we will not put on other people's sites, however honest the code behind it — see what it does with your visitor's data. The version inside Valnivo draws the same diagram from a ledger the person already keeps.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/flow.html?currency=EUR&locale=fr-LU&income=3200&home=1100&food=480&transport=220&other=360&aside=300
| Name | What it does | Range | Default |
|---|---|---|---|
income | What comes in over the month, in whole units. | 0–20 000 | 3 200 |
home | Rent, a mortgage payment, and what comes with the roof. | 0–10 000 | 1 100 |
food | Food and everyday spending. | 0–10 000 | 480 |
transport | Getting around. | 0–10 000 | 220 |
other | Everything else. | 0–10 000 | 360 |
aside | Money moved to savings or an investment — not counted as spending. | 0–10 000 | 300 |
Message name: flow. The categories are fixed: a host-defined list would be a form to
maintain for every host, and a visitor who has to name six categories before seeing anything is a
visitor who has already left.
What you own, less what you owe live
Cash, investments and property on one side, everything owed on the other, with the part reachable without selling a home shown separately. It is a photograph, not a projection: nothing grows, nothing is discounted, no year is named. The borrowed share is stated because it is arithmetic; no level of it is called healthy, high or safe, because that would be a judgement about a person rather than a sum.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/networth.html?currency=EUR&locale=fr-LU&cash=15000&investments=40000&property=250000&owed=180000
| Name | What it does | Range | Default |
|---|---|---|---|
cash | Money in accounts, in whole units. | 0–200 000 | 15 000 |
investments | Investments and pensions. | 0–1 000 000 | 40 000 |
property | Property, at what it would fetch. Selling costs and tax are not counted. | 0–2 000 000 | 250 000 |
owed | Everything owed, mortgage included. | 0–1 500 000 | 180 000 |
Message name: networth.
What could you retire on? live
A pot grown to an age the visitor picks, and what it might pay out a month at a withdrawal rate they also pick. The rate is deliberately theirs: no figure here is presented as a safe one to live on.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/retirement.html?currency=EUR&locale=fr-LU&age=40&retireAt=65&have=60000&monthly=500
| Name | What it does | Range | Default |
|---|---|---|---|
age | The visitor's age now. | 18–75 | 40 |
retireAt | The age they stop. Never accepted below age. | 40–85 | 65 |
have | Saved towards it already. | 0–1 000 000 | 60 000 |
monthly | Put aside each month. | 0–3 000 | 500 |
rate | The return assumed each year while saving, as a percent. | 0–15 | 5 |
inflation | The inflation assumed each year, as a percent. | 0–15 | 2 |
withdrawal | The share of the pot drawn each year once it is being spent, as a percent. No level of it is called safe — it is the visitor’s to set. | 1–10 | 4 |
Message name: retirement. An age is typed into the frame and goes nowhere — it is not
stored, not sent and not part of any record, which is what lets a widget ask for one at all. No state
or occupational pension is counted, and nothing is taxed.
Does it matter when you retire? live
A pot nobody draws on cares only about the average: the same returns in any order finish in the same place. Start taking money out and the order becomes the story — a bad first decade sells units at the bottom that are then not there for the recovery, and no run of good years afterwards puts them back. An ordinary retirement calculator cannot show this.
So this one does not use an average. It walks what the US stock market really did, once for every year somebody could have started, and reports how many of those starts the money outlasted. On the defaults, retiring in 1966 and retiring in 1982 are the same pot, the same withdrawal and the same market — and only one of them still has money.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/sequence.html?currency=EUR&locale=fr-LU&pot=500000&withdraw=20000&years=30
| Name | What it does | Range | Default |
|---|---|---|---|
pot | What there is at the start. | 50 000–3 000 000 | 500 000 |
withdraw | Taken each year, held constant in today’s money — which is what makes inflation-adjusted returns the right series to walk. | 0–200 000 | 20 000 |
years | How long it has to last. Longer than the record can answer for and it says so rather than guessing. | 5–50 | 30 |
stocks | Share of the pot in the market, as a percent. The rest earns steady. | 0–100 | 100 |
steady | What the part not in the market earns each year after inflation, as a percent. Negative is allowed, because cash has spent most of this century losing to it. | −2–4 | 0 |
Message name: sequence. Real total returns — dividends reinvested,
inflation removed — for the US stock market from 1871 to 2022, derived from
Robert
Shiller’s public dataset, January to January. One country, one asset class, and the
past: the United States has the longest clean record and is also the market that won that
century, so a European or Japanese pot did not do this — the frame says so where a visitor
reads it. The pot is rebalanced once a year and the withdrawal comes out before the year’s
return, which is the convention every published study uses and the conservative one. No tax, fee or
state pension is modelled, nothing here forecasts any market, and no rate of withdrawal is
called safe — that figure is the visitor’s to set.
ACROSS BORDERS
Pay across a border live
A monthly salary in one country, in another country's money, and what each country's own inflation does to it over time. Thirty-seven countries, from Valnivo's bundled reference table.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/crossborder.html?locale=fr-LU&from=LU&to=PT&amount=4000&years=10
| Name | What it does | Range | Default |
|---|---|---|---|
from | Where the salary is paid — ISO 3166-1 alpha-2. | Any curated country | LU |
to | Where it is being lived on. | Any curated country | PT |
amount | Monthly pay, in the origin country's currency. | 500–20 000 | 4 000 |
years | How far ahead to show the inflation effect. | 1–30 | 10 |
Message name: crossborder. currency is ignored here — each side is shown in
its own money.
What this one is not. It does not compare the cost of living, and it says so on screen. Rent, tax, childcare and groceries differ between two countries far more than the conversion does, and Valnivo holds no price-level or purchasing-power data to put a number on that. Please do not present it as a "should I move?" calculator.
Inflation by country live
The inflation figures Valnivo actually projects with — the current rate and the long-run rate it glides to — for all thirty-seven curated countries, searchable, with what they do to a fixed sum over time.
Six countries here, so the preview stays short; leave countries off and you get all
thirty-seven. Try the search.
https://valnivo.eu/embed/inflation.html?currency=EUR&locale=fr-LU&countries=LU,BE,FR,DE&sum=1000&years=10
| Name | What it does | Range | Default |
|---|---|---|---|
countries | A comma-separated list of alpha-2 codes, in your order. Omit it for all of them. | Any curated codes | all |
sum | The sum whose purchasing power is shown. | 1–1 000 000 | 1 000 |
years | Over how many years. | 1–30 | 10 |
Message name: inflation. The figures are the bundled reference table with its date shown; a
widget never fetches a live figure, so a table on your page cannot change under you. All thirty-seven
rows come to roughly 2 000px, so pass countries= unless you want the full list.
BORROWING
What would this loan cost? live
The monthly payment, the interest over the life of the loan, where each year's payments go — and what paying a little extra each month would change, which is the part a bank's own calculator rarely shows.
Move the extra-payment slider — the years and the interest saved follow.
https://valnivo.eu/embed/loan.html?currency=EUR&locale=fr-LU&amount=25000&rate=4.5&years=7&extra=100
| Name | What it does | Range | Default |
|---|---|---|---|
amount | How much is borrowed. | 1 000–500 000 | 25 000 |
rate | The annual interest rate, as a percent. Decimals are kept, so 4.5 means 4.5%. | 0–25 | 4.5 |
years | The term. | 1–35 | 7 |
extra | The overpayment the comparison opens on. | 0–1 000 | 100 |
Message name: loan. The rate is treated the way lenders quote it — nominal, divided by
twelve — so the payment matches a published amortisation table to the cent. It assumes a fixed rate, no
arrangement fee, no insurance and no early-repayment charge, and says so inside the frame.
What would this home cost a month? live
The same arithmetic against a price and a deposit, with upkeep, property tax and insurance added, since those are what turn a payment people can quote into a cost they had not planned for.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/mortgage.html?currency=EUR&locale=fr-LU&price=500000&deposit=100000&rate=3.5&years=25
| Name | What it does | Range | Default |
|---|---|---|---|
price | Price of the home. | 50 000–2 000 000 | 500 000 |
deposit | What is put down. Capped at the price. | 0–1 000 000 | 100 000 |
rate | The annual rate, as a percent. | 0–12 | 3.5 |
years | The term. | 5–35 | 25 |
upkeep | Upkeep, tax and insurance a month — the costs that come with owning and are not the loan. | 0–5 000 | 250 |
There is deliberately no affordability widget, and there will not be one without a lawyer's opinion. "How much home can I afford" states what somebody may borrow from their income and debts — a creditworthiness judgement, which is the lender's own regulated duty and close to advice on a regulated mortgage contract. This widget answers what a home would cost, never what you may have.
When would this be paid off? live
Months to clear a balance, the interest along the way, and what paying more each month changes. It also answers the case a calculator usually fudges: when the payment does not cover the interest, it says the debt never clears rather than printing a very large number of months.
Drag the payment below the interest — the answer changes in kind, not in degree.
https://valnivo.eu/embed/debt.html?currency=EUR&locale=fr-LU&balance=15000&rate=18&monthly=400&extra=100
| Name | What it does | Range | Default |
|---|---|---|---|
balance | What is owed. | 100–100 000 | 15 000 |
rate | The annual rate, as a percent. | 0–40 | 18 |
monthly | Paid each month. | 0–3 000 | 400 |
extra | The overpayment the comparison opens on. | 0–1 000 | 100 |
Message name: debt. It will never rank several debts, propose an order to clear them in, or
suggest consolidating: debt counselling is a licensed activity in Luxembourg and most of its
neighbours, and that is the step from arithmetic into advice. The widget points at approved services
instead.
DECIDING BETWEEN TWO COURSES
Rent or buy? live
The comparison Valnivo ought to own, because it is a scenario rather than a calculation. Both sides start with the same cash — the deposit plus the costs of buying — and whoever pays less each month invests the difference. Without that last rule the answer flatters whichever side happens to cost more, which is how this sum is usually rigged.
The last two sliders decide the answer, and nobody knows either of them.
https://valnivo.eu/embed/rentvsbuy.html?currency=EUR&locale=fr-LU&price=500000&deposit=100000&rent=1500&years=10
| Name | What it does | Range | Default |
|---|---|---|---|
price | Price of the home. | 50 000–2 000 000 | 500 000 |
deposit | What could be put down. | 0–1 000 000 | 100 000 |
rent | Rent a month instead. | 200–6 000 | 1 500 |
years | Compared over how long. | 1–30 | 10 |
mortgagerate | The mortgage rate, as a percent a year. | 0–12 | 3.5 |
appreciation | What the home is assumed to gain each year, as a percent. Negative is allowed, because homes do fall. | −5–12 | 2 |
growth | What the renter’s invested difference is assumed to return each year, as a percent. | 0–15 | 5 |
Message name: rentvsbuy. Buying assumes a 25-year mortgage at a fixed rate, 7% of the price
in costs to buy, 1% of the price a year in upkeep and tax, and that the home is not sold. Renting
assumes rent rises 2% a year. Neither side is taxed, and deductible mortgage interest — real in
Luxembourg — is not modelled. All of that is stated inside the frame too.
Pay cash or take a mortgage? live
Buying outright with cash the reader already has, against borrowing and keeping that cash invested. Both paths start with the same cash and spend the same each month: whatever the borrower pays the lender, the cash buyer invests instead. The home is the same in both and is left out of both figures, so what is compared is investments less what is still owed. It says which path ends higher under the figures set — never which to take — and names no lender and no investment.
The return against the mortgage rate decides most of it, and nobody knows the return.
https://valnivo.eu/embed/cashvsmortgage.html?currency=EUR&locale=fr-LU&price=400000&cash=450000&deposit=20&rate=3.5&years=25&growth=5
| Name | What it does | Range | Default |
|---|---|---|---|
price | Price of the home, in whole units. | 50 000–2 000 000 | 400 000 |
cash | The cash there is to start with, in both paths. Below the price there is nothing to compare, and the frame says so. | 0–3 000 000 | 450 000 |
deposit | What is put down if borrowing, as a percent of the price. | 0–100 | 20 |
rate | The mortgage rate, as a percent a year. | 0–12 | 3.5 |
years | The mortgage term. | 5–35 | 25 |
growth | What invested cash is assumed to return each year before charges, as a percent. | 0–12 | 5 |
fee | The ongoing charge on the investments, as a percent a year. | 0–2.5 | 0.3 |
inflation | Used only to restate the difference in today’s prices, as a percent a year. | 0–8 | 2 |
horizon | How many years the two paths are compared over; shorter than the term counts what is still owed. | 1–40 | 25 |
Message name: cashvsmortgage. One steady return every year, a fixed mortgage rate, and no tax
on either side — relief on mortgage interest and tax on returns differ by country. Buying costs, lender
fees and insurance are not included, and the frame says that invested cash can be reached while a paid-off
home cannot, which no figure carries. All of that is stated inside the frame too.
FOR A BUSINESS
Would this pay for itself? live
A firm's own costs against its own estimate of time saved, and the month it breaks even. Not consumer finance at all, which makes it the one widget that fits a B2B page where a projection would not.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/roi.html?currency=EUR&locale=en-GB&nowCost=500&newCost=300&setup=1500&hours=10&hourly=40
| Name | What it does | Range | Default |
|---|---|---|---|
nowCost | What is spent today, a month. | 0–20 000 | 500 |
newCost | What the change would cost, a month. | 0–20 000 | 300 |
setup | One-off cost of switching. | 0–100 000 | 1 500 |
hours | Hours a month saved. | 0–200 | 10 |
hourly | What an hour is worth. | 0–500 | 40 |
Message name: roi. When the change costs more than it saves, break-even reads
never rather than a negative number of months. Nothing is discounted and nothing is taxed.
How many do you have to sell? live
Fixed costs against what a sale leaves behind, and the number of sales where the two meet — with a profit target on top if you want one. The case it exists for is the one with no answer: where the price does not cover what a unit costs to make, no quantity gets there, so it says so in words and names the figure that caused it. It assumes every sale is the same and that costs split cleanly into fixed and per-unit, and says so in the frame.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/breakeven.html?currency=EUR&locale=fr-LU&fixed=12000&price=25&unit=10
| Name | What it does | Range | Default |
|---|---|---|---|
fixed | Costs a month that do not move with sales, in whole units. | 0–200 000 | 12 000 |
price | What one is sold for. | 0–5 000 | 25 |
unit | What one costs to make or deliver. | 0–5 000 | 10 |
profit | Profit wanted a month on top of covering the fixed costs. | 0–100 000 | 0 |
Message name: breakeven.
VAT, both ways live
Add VAT to a net price or take it back out of a gross one, with the standard rates of Luxembourg, Germany, France and Belgium as presets. The smallest widget here and the one an ecommerce or accounting page is most likely to want.
Move the controls — it is the real widget, not a picture.
https://valnivo.eu/embed/vat.html?currency=EUR&locale=fr-LU&amount=1000&rate=17&mode=add
| Name | What it does | Range | Default |
|---|---|---|---|
amount | The price to start from. | 0–100 000 | 1 000 |
rate | The rate, as a percent. Decimals are kept. | 0–30 | 17 |
mode | add treats the amount as net; remove treats it as gross. | add / remove | add |
Message name: vat. Taking VAT out divides by 1 + the rate rather than taking the rate off
the gross price, which is the usual mistake and always understates the tax. The presets are standard
rates as a convenience: which rate applies to a sale is a question about the sale.
§ In Excel, without writing anything
An Office Add-in is a hosted page plus a manifest, so the widgets go into Excel as they are. Install valnivo-excel.xml and a Valnivo button appears on the Home tab, opening a pane beside the sheet.
https://valnivo.eu/valnivo-excel.xml
- Excel on the web — Insert → Office Add-ins → Upload My Add-in → pick the XML.
- Excel on Windows — share a folder holding the XML, add it under File → Options → Trust Center → Trusted Add-in Catalogs, restart, then Insert → My Add-ins → Shared Folder.
- Excel on macOS — drop the XML in
~/Library/Containers/com.microsoft.Excel/Data/Documents/wef/and restart. - A whole organisation — your Microsoft 365 admin can deploy the same file from Settings → Integrated apps, with nothing to publish.
It reads only the cells you select, only when you ask, and never writes. The
manifest declares ReadDocument (it was Restricted until 21 September 2026):
select figures in your sheet, press Use the selected cells in the pane, and they become the
widget's inputs — nothing is read on load, nothing is watched, and no cell is ever written. The
pane makes no request of its own — the same as any embed on this page — and loads Microsoft's
Office library only inside Excel itself.
The pane carries three of them, not the whole library, and the reason is on its own face:
Excel already has PMT, FV, PV, NPER and
RATE, so a loan or a savings pot needs three cells and no add-in. What is in the
pane is what a spreadsheet cannot do on its own — the projection as a range, rent against buying, and
the dated inflation figures behind both.
Not built: custom functions, the =VALNIVO... kind that put a figure in a
cell. A cell holds a number and cannot hold "an illustration built on assumptions, not advice", which
is the one thing that travels with every widget here. It is a decision waiting on wording rather than
on code — say so if it is what you need, and it moves up the list.
§ Letting a widget size itself
Skip this if you use the loader — it does this for you. Each widget posts its height whenever it changes; apply it and the frame follows:
<iframe id="valnivo" src="https://valnivo.eu/embed/scenario.html?currency=EUR&locale=fr-LU"
title="Valnivo what-if" loading="lazy" style="width:100%;border:0;height:420px"></iframe>
<script>
addEventListener('message', function (e) {
if (e.origin !== 'https://valnivo.eu') return
if (!e.data || e.data.source !== 'valnivo' || e.data.widget !== 'scenario') return
document.getElementById('valnivo').style.height = e.data.height + 'px'
})
</script>
The message is { source: 'valnivo', widget: '<name>', height: <pixels> } and
carries nothing else — no figures, no identifiers.
Check e.origin. Any page in any frame can post a message to yours; that
line is what stops you resizing on a stranger's word.
Two of the same widget? The message names the widget, not which copy — compare
e.source with the frame's contentWindow, which is what the loader does.
A frame with no width gets no message
A widget's height is not a property of the widget. It is a function of the width it is laid out at, and the curve is steep. The same page, measured at four widths:
| Laid out at | Reports |
|---|---|
| 1,076px | 415px |
| 296px | 892px |
| 96px | 1,905px |
| 36px | 2,696px |
So a height measured before your frame has a width is not a smaller truth — it is a different number,
several times too large. A frame laid out at zero width sends nothing
(display:none, a closed tab, an unopened accordion): yours keeps the height you gave it,
and the real one arrives when the frame has a width. Zero is the only width that cannot have been
meant, so there is no threshold to trip a genuinely narrow column.
You never have to ask for a fresh measurement. The widget watches its own box and the frame's, so revealing a hidden frame or changing its column produces a new height by itself.
§ Fitting your design
- A widget paints its own ground — dark or light, your choice — and never a transparent one: the type inside is a real colour on a real ground, so borrowing what is behind the frame would make it unreadable on about half the pages it lands on.
-
theme=light|dark|auto. The default isdarkand stays dark — repainting published embeds because our own default moved is the surprise the promise below rules out. -
accent=six hex digits,#left off. It colours the sliders and interaction states. An accent that cannot be seen is refused — it must reach 3:1 against its ground, and underautoagainst both — so a reader switching to dark is never left with an invisible slider. A refused colour keeps ours and says so once in the console. - What you cannot set, and it is not an omission. Money coming in is green, money going out is red, and a figure the model produced rather than one your visitor typed is brass. Those three carry meaning rather than branding, and a widget that let them be repainted would let a projected figure be dressed as a fact. Nor can the line saying a figure is an illustration and not advice be removed, at any tier, by any parameter — it is what the widget is.
- Responsive from about 320px wide — give one the width you have.
- Set an initial
heightnear 420px so there is no jump before the first message; it need not be right.
§ What it does with your visitor's data
Nothing at all, and that is a design rule rather than a coincidence. A widget:
- keeps no account and asks for nothing;
- writes no cookie and no
localStorage, so it needs no consent banner from you on our behalf; - makes no request of its own once loaded — the numbers are computed in the browser;
- runs no analytics and no advertising, ever.
The browser does fetch the widget from valnivo.eu, so our host sees an IP address and the
usual request details, as any server would; our privacy notice covers
those. If a widget ever stores or sends something about a visitor, this page will say so and there
will be an agreement to sign first — it will not change quietly under an existing embed.
§ Showing somebody their own figures
The commonest question here. A widget computes from what your visitor types into it: there is no parameter, token or API that hands a widget somebody's Valnivo data — not an unbuilt feature but the property everything else rests on, since a component that could fetch a person's figures could not be embedded anywhere without an agreement about their data.
Never ask a visitor for a Valnivo recovery code. That code is the master key to a whole ledger — it derives the encryption key for everything, for ever, and cannot be scoped to one view or given an expiry. Our own database rules refuse to serve a ledger to anyone who is not signed in as its owner or a member of its space, so a page collecting one could not use it even if it wanted to.
Which means: a page asking for a Valnivo recovery code is either broken or phishing, and it is not ours. Please do not build one, and tell us if you see one.
What exists instead is the person doing it themselves: in the app they make a share link — one dated snapshot of a projection, with no entries, accounts, categories or name, sealed with a key that exists only inside the link and dead within 48 hours at most. They can revoke it sooner.
https://valnivo.eu/shared/#<id>.<key>
-
Link it; you cannot frame it. The page sends
Content-Security-Policy: frame-ancestors 'none'andX-Frame-Options: DENY, so an iframe pointing at it stays blank — a page somebody is linked to must not be dressable as another service's own screen. -
Nothing reaches us about who opened it. The id and the key sit after the
#, which browsers never send to a server. - It is not an integration point. There is no way to create one programmatically, and there will not be.
If what you actually need is to show figures for people your organisation manages — clients, members, employees — that is a different product with a different contract: Valnivo Professional, where the organisation is the controller, we are the processor, and a case carries a reference of yours rather than anybody's name. It is in early access: open to firms at no charge, and an account is created by invitation rather than by signing up.
§ The little Valnivo mark
A 17 pixel icon and the word, on a quiet chip in the top corner. It is positioned
absolutely and takes no width from the widget, so your own heading never wraps around it.
Clicking it opens valnivo.eu in a new tab — it never navigates the frame —
and the link carries rel="noreferrer noopener".
On the free tier it does not come off. There is no parameter to hide it, for the same reason the disclaimer travels inside the frame. If it clashes with your design, write to us rather than covering it.
A white-label licence removes it and lets you present the calculation as your own. It is free today — today, and only while Valnivo is running, rather than a right a licence gives you — and issued by hand. What a licence cannot touch is the line inside the frame saying a figure is an illustration and not advice: our name may go; that may not.
§ Conditions of use
A projection is an illustration built on assumptions, and every widget says so inside the frame. Please leave that visible — do not overlay it, clip it out, or place a widget so that the line reads as your own recommendation. Two things follow from the same rule:
- No product beside it as if it were the answer. A widget shows a visitor's own figures under their own assumptions. It never names, ranks or compares a fund, account, policy or provider, and it must not be framed as advice, a recommendation or a suitability assessment — yours or ours. Valnivo is a planning tool, not a regulated financial service; see the terms of use.
- Do not present it as your own calculation. Say it comes from Valnivo if the context could suggest otherwise. You are welcome to link to valnivo.eu. This is the one condition a white-label licence lifts; the one above it is not liftable by any licence, and neither is the illustration line inside the frame.
§ Changes, and what will not break
- Parameters and messages are additive. New ones may appear; the ones documented here keep working with the same meaning.
- A breaking change gets a new address (
/embed/v2/projection.html), and the old one keeps working. Your page will not be changed underneath you. - Widgets are served from our origin, so improvements and fixes reach every embed without you doing anything. That is the trade for not shipping you a file to host.
- Embedding is free today, as the app is. That is how things stand rather than a right it gives you, and if it ever changes, this page says so first.
§ Still to come
Not built. Tell us which is worth doing first.
- More calculators, on request planned — say what would earn its place on your page. Tax is not a widget. Luxembourg and French income tax exist on the calculators page, each checked against an official reference, and are deliberately not embeddable: presenting a computed tax position can fall inside a reserved advisory activity in some member states, so we keep it on pages where we control how it is framed. Hourly against annual pay stays refused as a widget: the figure people read off it is take-home pay in whatever country they are in, and take-home pay is worked out and checked for Luxembourg alone, on its own page.
- Per-site keys with an allowed-origins list later — only once a widget needs one.
§ If something is wrong
Write to support@valnivo.eu with the page you embedded it on and what you saw, or open an issue in the public feedback repository — that one is public, so keep anything private for the email.