| name | taux-immo-fr |
| description | Research French mortgage rates → offline weekly HTML market report: bank averages, scenario matrix, leading indicators, sourced forecasts. No personal data. Don't use for a personal capacity calc (use capacite-emprunt-fr) or non-France loans. |
| license | MIT |
| metadata | {"version":"1.3.0","author":"francais-skills"} |
| effort | high |
taux-immo-fr — Weekly French mortgage-rate market report
Produce a single self-contained HTML weekly briefing on the French home-loan
market: where rates are, who offers what, what the leading indicators say about
next week, and what named analysts predict. It is a market panorama, independent
of any personal situation — the user supplies nothing about themselves.
When this skill triggers
- "Quel est l'état du marché des taux immobiliers en France ?"
- "Fais-moi le rapport hebdo des taux de crédit immobilier."
- "Quels taux proposent les banques en ce moment / cette semaine ?"
- "Compare les taux entre banques et courtiers."
- "Quelles sont les prévisions de taux immobilier ?"
- "Génère le rapport HTML taux immobilier" / user invokes
/taux-immo-fr.
Do not trigger for — route elsewhere:
- "Combien je peux emprunter ?" / capacité d'emprunt / "avec mes revenus…" →
that is capacite-emprunt-fr (personal, HCSF calc). This skill never asks for
the user's income, apport, or charges.
- Crédit à la consommation, rachat/regroupement de crédits, prêt pro.
- Taux hors France (Belgique, Suisse, Luxembourg).
- Assurance emprunteur deep-dives, or a specific loan offer review.
Output: one self-contained offline HTML file
The skill writes a single .html to the user's current working directory:
./taux-immo-fr-<week>.html e.g. ./taux-immo-fr-2026-S24.html
That file:
- Renders with vendored, inlined TailwindCSS (compiled, shadcn/ui design
tokens) and vendored Chart.js — zero external requests, opens fully
offline. No CDN, no build, no server.
- Shows: a fail-loud provenance banner, hero KPI + week-over-week delta, a
leading-indicators strip (OAT 10Y / TEC10 / ECB), a 12-month trend chart, a
scenario matrix (borrower profile × duration), a per-network comparison
chart, editorial cards from lesser-known institutional sources, named-and-dated
forecast cards, and a méthodologie/sources section.
- Embeds the full structured data as JSON in
<script id="report-data"> — the
chart source AND the audit trail (see references/data-schema.md).
There is no separate markdown summary; the HTML is the deliverable.
The integrity contract (read first — this is the whole point)
This skill reports current numbers and attributed predictions. A polished
report makes a fabricated rate look authoritative. So:
- Every rate carries a source + fetch date in the JSON block. No number
without provenance.
- No forecast without a real fetched quote. Never paraphrase "a BNP economist
expects 3% by Q4" from memory. No quote → the forecast card is left in its
dashed empty state with "pas de citation vérifiable cette semaine".
- Fail loud. When a source 403s or times out, the report SAYS so in the banner
and the méthodologie list — it never silently fills the gap with a guess. A
visibly stale-but-honest report beats a fresh-looking fabricated one.
- Institutional insight cards shrink when sources fail — an absent card beats
an invented "durée moyenne 248 mois".
references/sources.md documents which French sources actually fetch (Empruntis,
ECB, Trading Economics) and which 403 behind Cloudflare (banque-france.fr,
aft.gouv.fr, meilleurtaux.com sometimes), with per-source extraction prompts and
flagged-stale fallback values.
Prerequisites
python3 on PATH (for scripts/build_report.py — stdlib only, no pip installs).
- WebFetch access. Several sources 403; the skill degrades gracefully per
references/sources.md.
- The vendored assets must exist:
assets/report.css, assets/chart.umd.min.js,
assets/report.boot.js. They ship with the skill. Only re-run
scripts/build_assets.sh (network + Tailwind CLI) if you change the template.
Workflow
Five phases, in order. End each with a one-line status before moving on.
Phase 1 — Research the market (fetch, in parallel)
Fetch the four source clusters from references/sources.md in parallel.
Record fetch status (OK / 403 / fallback) and as_of for each — this populates
the provenance banner. The four clusters:
- Mainstream barèmes (Empruntis ✅, Pretto, Meilleurtaux⚠) — monthly averages
for the matrix + comparison.
- Leading indicators (OAT 10Y via Trading Economics ✅, ECB key rates ✅) —
the weekly-moving story; always fetch these, they're what make a weekly
report non-redundant.
- Institutional / lesser-known (Crédit Logement/CSA, Banque de France
production) — the editorial insight cards.
- Forecasts (named courtier economists, bank notes, press) — sourced quotes
only.
Optional fan-out: for a thorough weekly sweep you may spawn one research
subagent per cluster (Agent tool) so the main context stays clean — each returns
structured findings you assemble in Phase 2. Default is inline parallel WebFetch.
Either way, the integrity contract holds: a subagent that couldn't fetch a source
reports that, and you record it as unavailable — you do not let it improvise.
Phase 2 — Assemble the data object (with provenance)
Build the JSON object matching references/data-schema.md. Copy
references/sample-data.json as your starting template and replace its values
with what you fetched — it has the exact shape and the right units already. For
every field, attach the source + as_of. Compute the derived
spread_oat_bareme_pt. Set provenance.sources_ok / sources_total to the
honest counts and list every failed source in provenance.unavailable +
methodology_sources. Forecasts and insights arrays contain only what you
actually fetched.
Units: put every rate in as a percent number (3.45 = 3.45 %), scalars and
chart arrays alike — see the unit rule in the schema. Deltas are points
(avg_20y_delta_pt) / basis points (oat_10y_delta_bps), signed.
Write the object to a temp file, e.g. /tmp/taux-immo-data.json.
Phase 3 — Build the self-contained file (the JSON is the only thing you author)
You do not hand-edit HTML. scripts/build_report.py renders both the
charts and every text section (hero, indicator tiles, matrix rows, insight
cards, forecast cards, banner counts, méthodologie list) from your JSON, then
inlines the vendored CSS + Chart.js + boot script into one offline HTML. This is
deliberate: it makes "the number in the prose == the number in the JSON" a
mechanical guarantee instead of a hope, and lets the script fail loud rather
than silently ship prototype/empty data.
python3 scripts/build_report.py \
--data /tmp/taux-immo-data.json \
--out ./taux-immo-fr-<week>.html
The script refuses to write (non-zero exit) if:
- a required section (
headline, indicators, matrix, provenance,
methodology_sources) is missing — so an incomplete fetch can't produce a
half-empty report;
- any
{{placeholder}} would survive unfilled — so a forgotten field is a hard
error, not a fabricated-looking page;
- a vendored asset is missing.
Empty insights / forecasts arrays are allowed and render as explicit
honest empty-state cards ("aucune citation vérifiable cette semaine") — never as
invented content. FR formatting (decimal comma "3,42 %", arrows on deltas) is
handled by the renderers; you only supply correct numbers in the JSON.
Phase 4 — Verify offline + report
Confirm the output is genuinely self-contained before handing it over:
grep -niE '<(script|link|img|source)[^>]*(src|href)=["'"'"']https?://' ./taux-immo-fr-<week>.html \
&& echo "FAIL: external load found" || echo "PASS: fully offline"
Tell the user the file path, the headline rate + week-over-week move, how many
sources were verified vs. unavailable, and that the file opens offline. Then emit
the Step Completion Report below.
Acceptance Criteria
The run is done when all hold (verify each before reporting PASS):
- A single
./taux-immo-fr-<week>.html is written; build_report.py exited 0.
- The offline grep in Phase 4 prints
PASS: fully offline (0 external loads).
- Every rate in
<script id="report-data"> has a source + as_of; provenance.sources_ok/sources_total match the honest fetch counts.
- No
{{placeholder}} survives in the output (the build asserts this).
forecasts/insights contain only fetched, attributed items — or render the explicit honest empty state, never invented content.
Expected output
A self-contained HTML report plus the terminal Step Completion Report shown below — e.g. Sources fetched: √ 6/8, Self-contained offline: √ grep clean, Result: PASS. The HTML file opens in a browser with charts rendered and zero network requests. See the Step Completion Report block at the end for the exact shape.
Edge Cases
Inputs the skill rejects or handles specially:
- WebFetch 403 / timeout — retry once with the secondary URL in
sources.md.
Still failing → use the flagged-stale fallback, set source_fallback: true, and
surface it in the banner. Never present a fallback as a fresh fetch.
- No forecast quotes found — ship empty forecast cards, do not invent. This is
correct behavior, not a failure.
build_report.py non-zero exit — read stderr; it names the missing asset or
placeholder. Fix that input; never hand-edit the output to paper over it.
- External-ref warning from the script — an asset was linked instead of
inlined. Inline it; the offline guarantee is non-negotiable.
- Charts blank in browser — almost always a unit mismatch in
trend/banks
(decimal vs percent). Make both percent. See the schema unit rule.
- "rate field outside the sane percent band" exit — you passed a decimal
(
0.0345) or basis points (345) where a percent number (3.45) was required.
Fix the unit in the JSON; the guard exists so a 100×-wrong rate never ships.
Step Completion Report
◆ Weekly Taux-Immo Report (FR market panorama)
··································································
Sources fetched: √ N/M (list any 403/fallback)
Provenance complete: √ every rate has source + as_of
Forecasts sourced: √ all named+dated (or empty, none invented)
Self-contained offline: √ grep clean — 0 external loads
Report written: √ ./taux-immo-fr-<week>.html
____________________________
Result: PASS | PARTIAL (stale sources) | FAIL
Reference files
references/sources.md — the four source clusters, working vs 403 URLs,
extraction prompts, flagged-stale fallbacks, the integrity contract.
references/data-schema.md — the auditable JSON block; unit rule; provenance.
references/sample-data.json — a complete, correctly-shaped example to copy and
adapt (right keys, right units). Start here in Phase 2.
references/html-template.html — the static report shell. Asset markers
(/*__REPORT_CSS__*/, /*__CHART_JS__*/, /*__REPORT_BOOT__*/,
<!--__REPORT_DATA__-->) + {{TOKEN}} text placeholders the script fills from JSON.
scripts/build_report.py — renders all text + charts from JSON and inlines
vendored assets → offline HTML (runtime). Fails loud on missing data / unfilled tokens.
scripts/build_assets.sh — re-vendors assets (build-time only; network + Tailwind CLI).