feat(content): refonte conseils (kits par phénomène), à-propos, mentions, sitemap
All checks were successful
Deploy info-canicule / deploy (push) Successful in 1m28s

- /conseils : cards par phénomène (couleur d'impact + glyphe), bloc registre canicule mis en avant, numéros d'urgence
- /conseils/[slug] : nouvelle route SSR par phénomène — kit imprimable, share natif, cross-link, advice.ts réutilisé
- /conseils/registre-canicule : reskin nouveau design, contenu existant conservé + TL;DR coloré
- /a-propos : reskin + sections "engagement accessibilité" et "à venir"
- /mentions-legales : reskin en cards (contenu inchangé)
- Sitemap : custom serialize avec priority/changefreq par type d'URL, customPages pour les 102 départements + 7 kits (117 URLs au total). Suppression du custom sitemap-departements.xml redondant

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian 2026-05-27 19:02:38 +02:00
parent 72b3785499
commit 0723ee10e3
7 changed files with 719 additions and 359 deletions

View file

@ -3,9 +3,17 @@ import node from '@astrojs/node';
import tailwind from '@astrojs/tailwind'; import tailwind from '@astrojs/tailwind';
import sitemap from '@astrojs/sitemap'; import sitemap from '@astrojs/sitemap';
import sentry from '@sentry/astro'; import sentry from '@sentry/astro';
import { DEPARTEMENTS } from './src/lib/departements.ts';
import { PHENOMENA } from './src/lib/phenomena.ts';
const sentryDsn = process.env.SENTRY_DSN; const sentryDsn = process.env.SENTRY_DSN;
const release = process.env.GIT_COMMIT_SHA || 'dev'; const release = process.env.GIT_COMMIT_SHA || 'dev';
const SITE = 'https://info-canicule.nocleus.com';
// URLs dynamiques (SSR) listées explicitement pour le sitemap — sinon @astrojs/sitemap
// ne les voit pas (il n'énumère que les routes statiques au build).
const deptUrls = DEPARTEMENTS.map((d) => `${SITE}/departement/${d.code}`);
const kitUrls = Object.values(PHENOMENA).map((p) => `${SITE}/conseils/${p.slug}`);
export default defineConfig({ export default defineConfig({
output: 'server', output: 'server',
@ -13,12 +21,36 @@ export default defineConfig({
integrations: [ integrations: [
tailwind({ applyBaseStyles: false }), tailwind({ applyBaseStyles: false }),
sitemap({ sitemap({
filter: (page) => filter: (page) => !page.includes('/api/'),
!page.includes('/api/') && customPages: [...deptUrls, ...kitUrls],
!page.includes('/departement/'), // Priorités SEO selon le type d'URL.
// /departement/* est dynamique pour les 96 dépts — généré dans /sitemap-departements.xml.ts à part. // Home > carte dept > conseils par phénomène > conseils index > pages info.
serialize(item) {
const url = item.url;
// Home — priorité max, change toutes les ~15 min côté contenu mais l'URL ne bouge pas.
if (url === `${SITE}/` || url === SITE) {
return { ...item, priority: 1.0, changefreq: 'hourly' };
}
// Pages département (96) — coeur du SEO long-tail, contenu live.
if (url.includes('/departement/')) {
return { ...item, priority: 0.9, changefreq: 'hourly' };
}
// Kits par phénomène — contenu durable, fort potentiel SEO.
if (url.includes('/conseils/') && url !== `${SITE}/conseils/` && !url.includes('registre-canicule')) {
return { ...item, priority: 0.8, changefreq: 'monthly' };
}
// Index conseils + registre canicule — repères durables.
if (url.includes('/conseils')) {
return { ...item, priority: 0.8, changefreq: 'monthly' };
}
// Embed — utile pour intégrations tierces.
if (url.includes('/embed')) {
return { ...item, priority: 0.5, changefreq: 'monthly' };
}
// Pages info (à-propos, mentions, etc.)
return { ...item, priority: 0.4, changefreq: 'yearly' };
},
}), }),
// Sentry / GlitchTip — opt-in via env. Si SENTRY_DSN absent, intégration omise (no-op).
...(sentryDsn ...(sentryDsn
? [ ? [
sentry({ sentry({
@ -26,14 +58,13 @@ export default defineConfig({
environment: process.env.NODE_ENV ?? 'production', environment: process.env.NODE_ENV ?? 'production',
release, release,
tracesSampleRate: 0.1, tracesSampleRate: 0.1,
// GlitchTip est OK avec source maps mais on les omet pour éviter le upload.
sourceMapsUploadOptions: { enabled: false }, sourceMapsUploadOptions: { enabled: false },
}), }),
] ]
: []), : []),
], ],
server: { host: '0.0.0.0', port: 4321 }, server: { host: '0.0.0.0', port: 4321 },
site: 'https://info-canicule.nocleus.com', site: SITE,
vite: { vite: {
ssr: { ssr: {
noExternal: ['ioredis'], noExternal: ['ioredis'],

View file

@ -2,92 +2,170 @@
import Base from '../layouts/Base.astro'; import Base from '../layouts/Base.astro';
export const prerender = false; export const prerender = false;
const why = [
{ title: 'Lisible par tous', text: "Couleur + glyphe + label pour chaque niveau. Lecteurs d'écran, contraste AAA, focus visibles." },
{ title: "Centré sur l'action", text: "On affiche d'abord ce qu'il faut faire, pas seulement les données brutes." },
{ title: 'Partager facilement', text: "Un kit imprimable par phénomène, partageable en deux clics à un proche fragile." },
{ title: 'Sans publicité', text: "Pas de tracker commercial, pas de pub. Financé sur fonds propres + dons." },
];
const a11y = [
"Couleur jamais seule : glyphe (●▲◆■) + label pour chaque niveau vigilance",
"Navigation clavier complète + skip-link + focus visibles",
"Contraste AAA (WCAG 2.2) sur les textes principaux",
"Zoom 200% sans perte de contenu ni de fonction",
"Mode sombre, préférence système respectée",
"Compatible lecteurs d'écran (NVDA, JAWS, VoiceOver)",
"Respect de prefers-reduced-motion",
"Pages prose lisibles sur mobile (mesure de ligne contrôlée)",
];
const roadmap: Array<[string, string]> = [
['Alertes par e-mail', "Recevoir un message à chaque franchissement de seuil sur son département."],
['Notifications push', "Alertes navigateur sans dépendre de l'e-mail."],
['Mode FALC global', "Bascule complète en Facile À Lire et à Comprendre."],
['Widget intégrable', "Code à coller pour mairies, associations, médiathèques."],
];
--- ---
<Base <Base
title="À propos — Info Canicule" title="À propos — Info Canicule"
description="Info Canicule est un site d'information publique gratuit, non lucratif, qui agrège les alertes Vigilance Météo France et les conseils officiels." description="Pourquoi ce site existe, comment il fonctionne, ses sources de données et ses engagements d'accessibilité."
> >
<section class="bg-gradient-to-b from-canicule-50 to-white"> <section class="container-tight" style="padding-block: clamp(28px, 5vw, 56px) 32px;">
<div class="container-tight py-10"> <div class="flex flex-col gap-3" style="margin-bottom: 40px; max-width: 720px;">
<h1 class="text-3xl font-bold sm:text-4xl">À propos d'Info Canicule</h1> <div class="kicker">Le projet</div>
<p class="mt-2 text-slate-600"> <h1>Info Canicule, en clair.</h1>
Pourquoi ce site existe, comment il fonctionne, ce qu'il ne fait pas. <p style="font-size: clamp(1rem, 0.9rem + 0.4vw, 1.18rem); color: var(--ink-2); line-height: 1.55; margin-top: 8px;">
Un service indépendant qui rend l'information météo Météo France <strong>directement actionnable</strong>&nbsp;:
voir si vous êtes concerné, savoir quoi faire, prévenir un proche fragile. Gratuit, sans publicité,
sans collecte de données personnelles.
</p> </p>
</div> </div>
</section>
<section class="container-tight py-8"> {/* Pourquoi */}
<div class="prose prose-slate max-w-none"> <section style="margin-bottom: 56px;">
<h2>Pourquoi ce site ?</h2> <h2 style="margin-bottom: 20px;">Pourquoi&nbsp;?</h2>
<p> <div class="grid gap-4" style="grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));">
Les épisodes de canicule, d'orages violents ou de fortes pluies tuent des dizaines de personnes {why.map((b) => (
chaque année en France. Les informations existent — Météo France publie des bulletins Vigilance <div class="ic-card-soft">
détaillés, le gouvernement diffuse des conseils — mais elles sont éparpillées, parfois difficiles <h3>{b.title}</h3>
à trouver, souvent enfouies sous des bannières publicitaires sur les sites grand public. <p style="margin-top: 8px; line-height: 1.5; color: var(--ink-soft);">{b.text}</p>
</p> </div>
<p> ))}
<strong>Info Canicule</strong> est un site d'utilité publique qui ne fait qu'une chose : </div>
afficher clairement, gratuitement, sans publicité ni traceurs commerciaux, la Vigilance Météo </section>
France en temps réel et les conseils officiels à appliquer.
</p>
<h2>Comment ça marche</h2> {/* Comment ça marche */}
<ul> <section style="margin-bottom: 56px;">
<li> <h2 style="margin-bottom: 16px;">Comment ça marche</h2>
<strong>Données Vigilance</strong> : récupérées toutes les 15 minutes depuis le portail <div class="ic-card">
Opendatasoft qui rediffuse les bulletins Météo France. Bulletin officiel mis à jour deux fois <ul style="padding-left: 20px; line-height: 1.75;">
par jour (matin et après-midi). <li>
</li> <strong>Vigilance</strong> · API officielle Météo France (et Opendatasoft en filet de secours).
<li> Bulletin officiel publié deux fois par jour (~6h et ~16h), avec cache court côté serveur pour amortir les pics de trafic.
<strong>Données climatologiques</strong> : températures journalières des 30 derniers jours, </li>
récupérées depuis <a href="https://meteo.data.gouv.fr/" rel="noopener">meteo.data.gouv.fr</a> <li>
(jeu de données <em>Données climatologiques de base — quotidiennes</em>), agrégées en moyenne <strong>Températures observées</strong> · réseau SYNOP, station ouverte la plus proche du département. Données horaires.
sur toutes les stations du département. </li>
</li> <li>
<li> <strong>Climatologie quotidienne</strong> · 365 derniers jours via
<strong>Conseils officiels</strong> : repris des publications de <a href="https://meteo.data.gouv.fr/" rel="noopener" style="color: var(--brand-deep);">meteo.data.gouv.fr</a>
<a href="https://www.meteofrance.fr/" rel="noopener">Météo France</a>, (jeu de données <em>Données climatologiques de base — quotidiennes</em>).
<a href="https://sante.gouv.fr/" rel="noopener">santé.gouv.fr</a> et </li>
<a href="https://www.gouvernement.fr/" rel="noopener">gouvernement.fr</a>. <li>
</li> <strong>Normales climatologiques</strong> · WMO 19912020, indexées par département × jour de l'année.
</ul> </li>
<li>
<strong>Conseils officiels</strong> · publications de
<a href="https://www.meteofrance.fr/" rel="noopener" style="color: var(--brand-deep);">Météo France</a>,
<a href="https://sante.gouv.fr/" rel="noopener" style="color: var(--brand-deep);">santé.gouv.fr</a> et
<a href="https://www.gouvernement.fr/" rel="noopener" style="color: var(--brand-deep);">gouvernement.fr</a>.
</li>
</ul>
</div>
</section>
<h2>Ce que ce site n'est pas</h2> {/* Engagement accessibilité */}
<ul> <section style="margin-bottom: 56px;">
<li><strong>Pas un service officiel</strong>. En cas d'urgence, suivre les consignes de la Préfecture ( <h2 style="margin-bottom: 16px;">Notre engagement accessibilité</h2>
<a href="tel:112">112</a>).</li> <div class="grid gap-3" style="grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));">
<li><strong>Pas un site commercial</strong>. Aucune publicité, aucune monétisation, aucun affiliation, {a11y.map((claim) => (
aucune vente de données.</li> <div class="ic-card flex items-start gap-3" style="padding: 16px;">
<li><strong>Pas un outil de prévision</strong>. Les prévisions affichées sont celles de Météo France, <span style="color: var(--v-vert); flex-shrink: 0; font-weight: 700;" aria-hidden="true">✓</span>
pas un modèle indépendant.</li> <span style="font-size: 0.95rem; line-height: 1.45;">{claim}</span>
</ul> </div>
))}
</div>
</section>
<h2>Statut juridique</h2> {/* Ce que ce site n'est pas */}
<p> <section style="margin-bottom: 56px;">
Info Canicule est édité <strong>à titre personnel, sans but lucratif</strong>, sur fonds propres <h2 style="margin-bottom: 16px;">Ce que ce site n'est pas</h2>
par un développeur indépendant. Le site n'est pas une association loi 1901, pas une entreprise, <div class="ic-card">
pas un service public. Les données affichées sont publiques et réutilisables sous <ul style="padding-left: 20px; line-height: 1.75;">
<a href="https://www.etalab.gouv.fr/licence-ouverte-open-licence/" rel="noopener">Licence Ouverte 2.0</a>. <li><strong>Pas un service officiel.</strong> En cas d'urgence, suivre les consignes de la Préfecture et appeler les services d'urgence (<a href="tel:112" style="color: var(--brand-deep); font-weight: 600;">112</a>).</li>
</p> <li><strong>Pas un site commercial.</strong> Aucune publicité, aucune monétisation, aucune affiliation, aucune vente de données.</li>
<p> <li><strong>Pas un outil de prévision.</strong> Les prévisions affichées sont celles de Météo France, pas un modèle indépendant.</li>
Voir aussi : <a href="/mentions-legales">mentions légales</a>, </ul>
<a href="/dependances">dépendances logicielles</a>, </div>
<a href="/soutenir">soutenir le projet</a>. </section>
</p>
<h2>Code source</h2> {/* Statut juridique */}
<p> <section style="margin-bottom: 56px;">
Le code est disponible sur demande à <h2 style="margin-bottom: 16px;">Statut juridique</h2>
<a href="mailto:florian@nocleus.com">florian@nocleus.com</a> (contributions, signalements de <div class="ic-card">
bugs et améliorations bienvenus). <p>
</p> Info Canicule est édité <strong>à titre personnel, sans but lucratif</strong>, sur fonds propres, par un développeur
indépendant. Le site n'est pas une association loi 1901, pas une entreprise, pas un service public.
</p>
<p style="margin-top: 12px;">
Les données affichées sont publiques et réutilisables sous
<a href="https://www.etalab.gouv.fr/licence-ouverte-open-licence/" rel="noopener" style="color: var(--brand-deep);">Licence Ouverte 2.0</a>.
</p>
<p style="margin-top: 12px; color: var(--ink-soft); font-size: 0.95rem;">
Voir aussi&nbsp;: <a href="/mentions-legales" style="color: var(--brand-deep);">mentions légales</a> ·
<a href="/dependances" style="color: var(--brand-deep);">dépendances logicielles</a> ·
<a href="/soutenir" style="color: var(--brand-deep);">soutenir le projet</a>.
</p>
</div>
</section>
<h2>Contact</h2> {/* À venir */}
<p> <section style="margin-bottom: 56px;">
Mail : <a href="mailto:florian@nocleus.com">florian@nocleus.com</a> — pour toute question, <div class="kicker">À venir</div>
remarque ou correction (typo, erreur dans un conseil, donnée incohérente). <h2 style="margin-top: 8px; margin-bottom: 16px;">Prochaines étapes</h2>
</p> <p style="color: var(--ink-soft); max-width: 640px; margin-bottom: 20px;">
</div> Ces fonctionnalités sont prévues mais ne sont pas encore intégrées. La structure d'interface est en place pour les accueillir le moment venu.
</p>
<div class="grid gap-3" style="grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));">
{roadmap.map(([title, desc]) => (
<div class="ic-card" style="padding: 16px;">
<div class="flex items-center justify-between gap-2">
<strong>{title}</strong>
<span class="kicker" style="font-size: 0.7rem; padding: 3px 8px; border-radius: 999px; background: var(--paper-warm); color: var(--ink-soft);">à venir</span>
</div>
<p style="margin-top: 8px; font-size: 0.9rem; line-height: 1.45; color: var(--ink-soft);">{desc}</p>
</div>
))}
</div>
</section>
{/* Code source + Contact */}
<section style="margin-bottom: 24px;">
<h2 style="margin-bottom: 16px;">Code source &amp; contact</h2>
<div class="ic-card">
<p>
Le code est disponible sur demande à
<a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>
— contributions, signalements de bug et améliorations bienvenus.
</p>
<p style="margin-top: 12px;">
Pour toute question, remarque ou correction (typo, erreur dans un conseil, donnée incohérente)&nbsp;:
<a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>.
</p>
</div>
</section>
</section> </section>
</Base> </Base>

View file

@ -0,0 +1,191 @@
---
import Base from '../../layouts/Base.astro';
import { PHENOMENA, phenomenonBySlug } from '../../lib/phenomena';
import { ADVICE } from '../../lib/advice';
export const prerender = false;
const slug = Astro.params.slug as string;
const phenomenon = phenomenonBySlug(slug);
if (!phenomenon) {
return new Response('Phénomène inconnu', { status: 404 });
}
const advice = ADVICE[phenomenon.id];
if (!advice) {
return new Response('Conseils indisponibles', { status: 404 });
}
const PHENOM_COLOR: Record<number, 'vert' | 'jaune' | 'orange' | 'rouge'> = {
6: 'orange', 3: 'jaune', 1: 'jaune', 2: 'jaune', 5: 'vert', 8: 'vert', 9: 'jaune',
};
const color = PHENOM_COLOR[phenomenon.id];
const PHENOM_INTRO_LONG: Record<number, string> = {
6: "Une vague de chaleur dure plusieurs jours et nuits. Le corps a du mal à se rafraîchir, surtout chez les personnes âgées, les nourrissons et les malades chroniques.",
3: "Foudre, vent fort, grêle et fortes pluies localisées peuvent provoquer dégâts matériels, blessures et interruptions de services.",
1: "Des rafales fortes peuvent emporter des objets, briser des branches, et rendre la conduite dangereuse — notamment pour les véhicules hauts.",
2: "Des cumuls de précipitations importants peuvent provoquer débordements, coulées de boue et coupures de routes.",
5: "La neige et le verglas rendent les routes glissantes et peuvent isoler certains lieux.",
8: "Le manteau neigeux peut devenir instable, en particulier après des chutes récentes ou un redoux.",
9: "Vagues fortes et submersion marine présentent un risque élevé sur le littoral.",
};
const intro = PHENOM_INTRO_LONG[phenomenon.id] ?? advice.intro;
const title = `Que faire en cas de ${phenomenon.label.toLowerCase()} — Info Canicule`;
const description = `Kit imprimable et partageable : bons gestes officiels en cas de ${phenomenon.label.toLowerCase()}. Source Météo France, santé.gouv.fr, gouvernement.fr.`;
---
<Base title={title} description={description}>
<section class="container-tight" style="padding-block: clamp(24px, 4vw, 48px);">
<a href="/conseils" class="ic-btn ic-btn-ghost ic-btn-sm no-print" style="text-decoration: none; margin-bottom: 16px;">
← Tous les conseils
</a>
{/* Hero coloré */}
<div class={`v-block v-${color}`} style="margin-bottom: 24px; padding: 28px;">
<div class="kicker" style={`color: var(--v-${color}-ink); opacity: 0.85;`}>
Kit phénomène · imprimable &amp; partageable
</div>
<div class="flex items-center gap-4" style="margin-top: 12px;">
<div
style={`width: 56px; height: 56px; border-radius: 50%; background: rgba(255,255,255,0.55); display: flex; align-items: center; justify-content: center; font-size: 1.8rem; color: var(--v-${color}-ink);`}
aria-hidden="true"
>
{phenomenon.emoji}
</div>
<h1 style={`color: var(--v-${color}-ink);`}>{phenomenon.label}</h1>
</div>
<p style={`margin-top: 16px; font-size: 1.05rem; color: var(--v-${color}-ink); line-height: 1.55; max-width: 720px;`}>
{intro}
</p>
</div>
{/* Blocs de conseils */}
<div class="grid gap-4 kit-grid" style="grid-template-columns: 1fr 1fr;">
{
advice.blocks.map((b) => (
<div class="ic-card">
<h3 style="display: flex; align-items: center; gap: 10px; color: var(--v-vert);">
<span aria-hidden="true">✓</span>
{b.title}
</h3>
<ul style="margin-top: 14px; padding-left: 0; list-style: none;">
{b.items.map((t, i) => (
<li
style={`display: flex; gap: 10px; padding: 10px 0; ${i < b.items.length - 1 ? 'border-bottom: 1px dashed var(--line);' : ''}`}
>
<span style="color: var(--v-vert); flex-shrink: 0; margin-top: 2px;" aria-hidden="true">✓</span>
<span>{t}</span>
</li>
))}
</ul>
</div>
))
}
</div>
{/* Urgence */}
{advice.emergency.length > 0 && (
<div class="v-block v-rouge" style="margin-top: 24px; display: flex; align-items: flex-start; gap: 14px;">
<span aria-hidden="true" style="font-size: 1.4rem; line-height: 1; flex-shrink: 0;">⚠</span>
<div>
<strong style="font-size: 1.05rem;">En urgence</strong>
<ul style="margin-top: 8px; padding-left: 0; list-style: none;">
{advice.emergency.map((e, i) => (
<li style={`padding: 6px 0; ${i < advice.emergency.length - 1 ? 'border-bottom: 1px dashed currentColor;' : ''}`}>
{e}
</li>
))}
</ul>
</div>
</div>
)}
{/* Bonus pour la canicule : pointer vers le registre */}
{phenomenon.id === 6 && (
<a
href="/conseils/registre-canicule"
class="ic-card ic-card-interactive flex flex-wrap items-center justify-between gap-4 no-print"
style="padding: 22px; margin-top: 24px; text-decoration: none; color: inherit; background: var(--brand-tint); border-color: var(--line-strong);"
>
<div style="max-width: 600px;">
<div class="kicker" style="color: var(--brand-deep);">Aider une personne fragile</div>
<h3 style="margin-top: 6px; color: var(--brand-ink);">🛡️ Registre canicule de la mairie</h3>
<p style="margin-top: 6px; color: var(--ink-2); font-size: 0.95rem;">
Inscrire un proche âgé ou isolé pour qu'il soit contacté par la mairie pendant les épisodes de canicule. Gratuit et confidentiel.
</p>
</div>
<span class="ic-btn ic-btn-brand">Voir comment s'inscrire →</span>
</a>
)}
{/* Actions */}
<div class="ic-card no-print" style="margin-top: 24px; padding: 24px;">
<h3>Diffuser ce kit</h3>
<p style="color: var(--ink-soft); font-size: 0.92rem; margin-top: 6px;">
Imprimez-le pour l'afficher, ou partagez le lien à un proche.
</p>
<div class="grid gap-3" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); margin-top: 16px;">
<button id="print-btn" type="button" class="ic-btn ic-btn-ghost ic-btn-lg">
🖨 Imprimer
</button>
<button id="share-btn" type="button" class="ic-btn ic-btn-brand ic-btn-lg" data-title={phenomenon.label} data-slug={phenomenon.slug}>
↗ Partager le lien
</button>
<a
href={`mailto:?subject=${encodeURIComponent('Conseils ' + phenomenon.label + ' — Info Canicule')}&body=${encodeURIComponent("Voici un kit pratique pour réagir en cas de " + phenomenon.label.toLowerCase() + " :\n\nhttps://info-canicule.nocleus.com/conseils/" + phenomenon.slug + "\n\nÀ partager si utile.")}`}
class="ic-btn ic-btn-ghost ic-btn-lg"
style="text-decoration: none;"
>
✉ Par e-mail
</a>
</div>
</div>
{/* Cross-link autres phénomènes */}
<section style="margin-top: 32px;" class="no-print">
<div class="kicker" style="margin-bottom: 12px;">Autres kits</div>
<div class="flex flex-wrap gap-2">
{
Object.values(PHENOMENA)
.filter((p) => p.id !== phenomenon.id)
.map((p) => (
<a href={`/conseils/${p.slug}`} class="ic-btn ic-btn-ghost ic-btn-sm" style="text-decoration: none;">
{p.emoji} {p.label}
</a>
))
}
</div>
</section>
</section>
<style>
@media (max-width: 720px) {
.kit-grid { grid-template-columns: 1fr !important; }
}
</style>
<script is:inline>
(function () {
var pb = document.getElementById('print-btn');
if (pb) pb.addEventListener('click', function () { window.print(); });
var sb = document.getElementById('share-btn');
if (sb) sb.addEventListener('click', async function () {
var url = window.location.href;
var title = sb.getAttribute('data-title');
if (navigator.share) {
try { await navigator.share({ title: 'Conseils ' + title, url: url }); }
catch (_) {}
} else if (navigator.clipboard) {
try {
await navigator.clipboard.writeText(url);
sb.textContent = '✓ Lien copié';
setTimeout(function () { sb.textContent = '↗ Partager le lien'; }, 1800);
} catch (_) {}
}
});
})();
</script>
</Base>

View file

@ -1,93 +1,133 @@
--- ---
import Base from '../../layouts/Base.astro'; import Base from '../../layouts/Base.astro';
import { PHENOMENA } from '../../lib/phenomena'; import { PHENOMENA } from '../../lib/phenomena';
import { ADVICE, EMERGENCY_NUMBERS } from '../../lib/advice'; import { EMERGENCY_NUMBERS } from '../../lib/advice';
export const prerender = false; export const prerender = false;
const phenomenaList = Object.values(PHENOMENA).sort((a, b) => // Couleur de "carte" par phénomène — non corrélée à la vigilance courante,
a.id === 6 ? -1 : b.id === 6 ? 1 : a.label.localeCompare(b.label), // c'est juste un repère visuel d'impact typique pour la page conseils.
); const PHENOM_COLOR: Record<number, 'vert' | 'jaune' | 'orange' | 'rouge'> = {
6: 'orange', // canicule
3: 'jaune', // orages
1: 'jaune', // vent
2: 'jaune', // pluie
5: 'vert', // neige
8: 'vert', // avalanches
9: 'jaune', // vagues-submersion
};
const PHENOM_BLURB: Record<number, string> = {
6: "Une vague de chaleur dure plusieurs jours et nuits. Le corps a du mal à se rafraîchir, surtout chez les personnes âgées, nourrissons et malades chroniques.",
3: "Foudre, vent fort, grêle et fortes pluies localisées : dégâts, blessures et coupures de réseau possibles.",
1: "Des rafales fortes peuvent emporter des objets, briser des branches, rendre la conduite dangereuse.",
2: "Des cumuls de pluie importants peuvent provoquer débordements, coulées de boue et coupures de routes.",
5: "Neige et verglas rendent les routes glissantes et peuvent isoler certains lieux.",
8: "Le manteau neigeux peut devenir instable, en particulier après chutes récentes ou redoux.",
9: "Vagues fortes et submersion marine sur le littoral : risques élevés pour les biens et les personnes.",
};
// Ordre : canicule d'abord, puis par impact courant
const phenomenaList = Object.values(PHENOMENA).sort((a, b) => {
if (a.id === 6) return -1;
if (b.id === 6) return 1;
return a.label.localeCompare(b.label);
});
const GLYPHS = { vert: '●', jaune: '▲', orange: '◆', rouge: '■' } as const;
--- ---
<Base <Base
title="Conseils officiels — Vigilance météo" title="Conseils par phénomène — Info Canicule"
description="Conseils officiels du gouvernement et de Météo France en cas d'alerte météorologique (canicule, orages, vent, inondations)." description="Que faire face à la canicule, aux orages, au vent violent, à la pluie, à la neige ou aux avalanches. Kits clairs, imprimables et partageables — sources Météo France et santé.gouv.fr."
> >
<section class="bg-gradient-to-b from-canicule-50 to-white"> <section class="container-tight" style="padding-block: clamp(28px, 5vw, 56px) 24px;">
<div class="container-tight py-8"> <div class="flex flex-col gap-3" style="margin-bottom: 24px;">
<h1 class="text-3xl font-bold sm:text-4xl">Conseils officiels</h1> <div class="kicker">Conseils</div>
<p class="mt-2 max-w-2xl text-slate-600"> <h1>Que faire face à chaque phénomène&nbsp;?</h1>
Recommandations à appliquer en cas d'alerte Vigilance, par type de phénomène. <p style="font-size: clamp(1rem, 0.9rem + 0.4vw, 1.18rem); color: var(--ink-2); max-width: 720px; line-height: 1.55;">
Sources : Météo France, santé.gouv.fr, gouvernement.fr. Choisissez un phénomène : vous accédez à un kit clair, imprimable et partageable.
Idéal pour informer un proche en quelques secondes.
</p> </p>
<div class="mt-4 rounded-lg border border-canicule-200 bg-canicule-50 p-4"> </div>
<p class="text-sm font-semibold text-canicule-900">
🛡️ Aider une personne fragile : <a href="/conseils/registre-canicule" class="font-bold underline"> {/* Bloc registre canicule — utilité publique majeure */}
registre canicule de la mairie <a
</a> href="/conseils/registre-canicule"
</p> class="ic-card ic-card-interactive flex flex-wrap items-center justify-between gap-4"
<p class="mt-1 text-sm text-canicule-800"> style="padding: 22px; margin-bottom: 28px; text-decoration: none; color: inherit; border-color: var(--line-strong); background: var(--brand-tint);"
Dispositif communal gratuit qui permet à un proche âgé, malade ou isolé d'être contacté en >
cas d'alerte. Inscription en quelques minutes via le CCAS. <div style="max-width: 640px;">
<div class="kicker" style="color: var(--brand-deep);">Aider une personne fragile</div>
<h3 style="margin-top: 6px; color: var(--brand-ink);">🛡️ Registre canicule de la mairie</h3>
<p style="margin-top: 6px; color: var(--ink-2); font-size: 0.95rem;">
Dispositif communal gratuit qui permet à un proche âgé, malade ou isolé d'être contacté par la mairie en cas d'alerte. Inscription en quelques minutes via le CCAS.
</p> </p>
</div> </div>
</div> <span class="ic-btn ic-btn-brand">
</section> Voir la fiche →
</span>
</a>
<section class="container-tight py-8"> {/* Cards par phénomène */}
<div class="space-y-12"> <div class="grid gap-4" style="grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));">
{ {
phenomenaList.map((p) => { phenomenaList.map((p) => {
const advice = ADVICE[p.id]; const color = PHENOM_COLOR[p.id];
return ( return (
<article id={p.slug} class="scroll-mt-20"> <a
<h2 class="text-2xl font-bold"> href={`/conseils/${p.slug}`}
<span aria-hidden="true">{p.emoji}</span> {p.label} class={`v-block v-${color} ic-card-interactive`}
</h2> style="display:flex; flex-direction:column; justify-content:space-between; text-decoration:none; min-height:200px;"
<p class="mt-2 text-slate-700">{advice.intro}</p> >
<div>
<div class="mt-4 grid gap-4 sm:grid-cols-2"> <div
{advice.blocks.map((b) => ( style={`width: 48px; height: 48px; border-radius: 50%; background: rgba(255,255,255,0.55); display: flex; align-items: center; justify-content: center; font-size: 1.6rem; color: var(--v-${color}-ink);`}
<div class="rounded-lg border border-slate-200 bg-white p-4"> aria-hidden="true"
<h3 class="font-semibold">{b.title}</h3> >
<ul class="mt-2 list-inside list-disc space-y-1 text-sm text-slate-700"> {p.emoji}
{b.items.map((i) => <li>{i}</li>)}
</ul>
</div>
))}
</div>
{advice.emergency.length > 0 && (
<div class="mt-4 rounded-lg border border-red-200 bg-red-50 p-4">
<h3 class="font-semibold text-red-900">Urgence</h3>
<ul class="mt-1 space-y-1 text-sm text-red-800">
{advice.emergency.map((e) => <li>{e}</li>)}
</ul>
</div> </div>
)} <h3 style={`margin-top: 16px; color: var(--v-${color}-ink);`}>
</article> <span aria-hidden="true" style="margin-right: 6px; font-size: 0.7em;">{GLYPHS[color]}</span>
{p.label}
</h3>
<p style={`margin-top: 8px; color: var(--v-${color}-ink); opacity: 0.85; font-size: 0.92rem; line-height: 1.5;`}>
{PHENOM_BLURB[p.id]}
</p>
</div>
<div style={`display: flex; align-items: center; gap: 6px; margin-top: 16px; color: var(--v-${color}-ink); font-weight: 600;`}>
Voir le kit →
</div>
</a>
); );
}) })
} }
</div> </div>
</section>
<section class="border-t border-slate-200 bg-white"> {/* Numéros d'urgence */}
<div class="container-tight py-8"> <section class="ic-card" style="margin-top: 40px; padding: 28px;">
<h2 class="text-xl font-semibold">Numéros d'urgence</h2> <h3 style="display: flex; align-items: center; gap: 10px;">
<div class="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-3"> <span aria-hidden="true" style="color: var(--v-rouge);">⚠</span>
Numéros d'urgence
</h3>
<p style="color: var(--ink-soft); font-size: 0.92rem; margin-top: 6px;">
Gratuits, joignables 24/24, depuis tout téléphone (fixe, mobile, sans crédit).
</p>
<div class="grid gap-6" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); margin-top: 18px;">
{ {
EMERGENCY_NUMBERS.map((n) => ( EMERGENCY_NUMBERS.map((n) => (
<div class="flex items-baseline gap-2 rounded border border-slate-200 px-3 py-2"> <div>
<a href={`tel:${n.num}`} class="font-mono text-lg font-bold text-canicule-700"> <a
href={`tel:${n.num}`}
style="font-family: var(--font-display); font-weight: 800; font-size: 2rem; color: var(--v-rouge); text-decoration: none; line-height: 1;"
>
{n.num} {n.num}
</a> </a>
<span class="text-sm text-slate-700">{n.label}</span> <div style="color: var(--ink-soft); font-size: 0.92rem; margin-top: 4px;">{n.label}</div>
</div> </div>
)) ))
} }
</div> </div>
</div> </section>
</section> </section>
</Base> </Base>

View file

@ -8,103 +8,136 @@ export const prerender = false;
title="Registre canicule — s'inscrire pour soi ou un proche fragile" title="Registre canicule — s'inscrire pour soi ou un proche fragile"
description="Le registre canicule est un dispositif communal gratuit qui permet d'être contacté par la mairie en cas d'épisode caniculaire. Comment s'y inscrire." description="Le registre canicule est un dispositif communal gratuit qui permet d'être contacté par la mairie en cas d'épisode caniculaire. Comment s'y inscrire."
> >
<section class="bg-gradient-to-b from-canicule-50 to-white"> <section class="container-tight" style="padding-block: clamp(24px, 4vw, 48px);">
<div class="container-tight py-10"> <a href="/conseils" class="ic-btn ic-btn-ghost ic-btn-sm" style="text-decoration: none; margin-bottom: 16px;">
<a href="/conseils" class="text-sm text-canicule-700">← Tous les conseils</a> ← Tous les conseils
<h1 class="mt-2 text-3xl font-bold sm:text-4xl">Registre canicule</h1> </a>
<p class="mt-2 max-w-2xl text-slate-600">
Un dispositif communal, gratuit et confidentiel, qui permet d'être contacté par sa mairie en
cas d'alerte canicule. Conçu en priorité pour les personnes fragiles et isolées.
</p>
</div>
</section>
<section class="container-tight py-8"> <div class="flex flex-col gap-3" style="margin-bottom: 24px;">
<div class="prose prose-slate max-w-none"> <div class="kicker">Dispositif communal · gratuit · confidentiel</div>
<h2>À qui ça s'adresse</h2> <h1>🛡️ Registre canicule</h1>
<p>Le registre nominatif communal est ouvert à toute personne qui le souhaite, mais il est <p style="font-size: clamp(1rem, 0.9rem + 0.4vw, 1.18rem); color: var(--ink-2); max-width: 720px; line-height: 1.55;">
particulièrement utile pour :</p> Un dispositif communal, gratuit et confidentiel, qui permet d'être contacté par sa mairie en cas d'alerte canicule.
<ul> Conçu en priorité pour les personnes fragiles et isolées.
<li>Les <strong>personnes âgées de 65 ans et plus</strong> vivant à domicile</li>
<li>Les <strong>personnes en situation de handicap</strong></li>
<li>Les <strong>personnes adultes isolées</strong> (sans aidant proche)</li>
<li>Les personnes <strong>fragilisées par une maladie chronique</strong></li>
</ul>
<p>
Vous pouvez inscrire un proche (parent, voisin) avec son accord, ou demander une inscription
d'office pour une personne dont vous estimez qu'elle est en danger.
</p>
<h2>Comment ça se passe en cas d'alerte</h2>
<ul>
<li>Quand un département passe en vigilance orange ou rouge canicule, le plan « Plan National
Canicule » (PNC) s'enclenche en mairie.</li>
<li>Les personnes inscrites sur le registre sont <strong>appelées</strong> ou
<strong>visitées</strong> par des agents communaux ou bénévoles (Croix-Rouge, ADMR…).</li>
<li>L'objectif : vérifier qu'elles vont bien, qu'elles ont de quoi s'hydrater et rester au
frais, et alerter si besoin (médecin traitant, 15, famille).</li>
</ul>
<h2>Comment s'inscrire</h2>
<ol>
<li>
Contacter le <strong>CCAS</strong> (Centre Communal d'Action Sociale) de votre commune, ou
directement la mairie. Numéros disponibles via l'annuaire officiel des mairies :
<a href="https://lannuaire.service-public.fr/navigation/mairie" rel="noopener">
lannuaire.service-public.fr/navigation/mairie
</a>
</li>
<li>
Demander le <strong>formulaire d'inscription au registre canicule</strong> (parfois appelé
« registre des personnes vulnérables » ou « plan canicule »).
</li>
<li>
Remplir le formulaire avec : nom, âge, adresse, téléphone, personne à prévenir, médecin
traitant, éventuelles particularités (isolement, mobilité, etc.).
</li>
<li>
Retourner le formulaire à la mairie. <strong>Gratuit et confidentiel</strong> — les données
ne servent qu'au plan canicule, ne sont pas partagées commercialement.
</li>
</ol>
<h2>Bon à savoir</h2>
<ul>
<li>L'inscription est <strong>valable pour toute la saison estivale</strong> (juin à
septembre), à renouveler chaque année si besoin.</li>
<li>Vous pouvez vous <strong>désinscrire à tout moment</strong> par simple courrier ou appel.</li>
<li>
Cadre légal : article L121-6-1 du Code de l'action sociale et des familles + circulaire
annuelle relative au Plan National Canicule.
</li>
</ul>
<div class="not-prose my-6 rounded-lg border border-canicule-200 bg-canicule-50 p-4">
<p class="text-sm font-semibold text-canicule-900">📞 Plateforme téléphonique canicule</p>
<p class="mt-1 text-sm text-canicule-800">
Numéro vert <a href="tel:0800066666" class="font-mono font-bold">0 800 06 66 66</a> (gratuit
depuis un poste fixe). Activé pendant les épisodes de canicule pour informer et conseiller.
</p> </p>
</div> </div>
<h2>Pour aller plus loin</h2> {/* TL;DR coloré pour donner l'essentiel en un coup d'œil */}
<ul> <div class="v-block v-orange" style="margin-bottom: 28px;">
<li> <strong style="color: var(--v-orange-ink); font-size: 1.05rem;">L'essentiel en 30 secondes</strong>
<a href="https://www.sante.gouv.fr/sante-et-environnement/risques-climatiques/article/plan-national-canicule-pnc" rel="noopener"> <ul style="margin-top: 10px; padding-left: 0; list-style: none; color: var(--v-orange-ink);">
Plan National Canicule (santé.gouv.fr) <li style="padding: 6px 0; display: flex; gap: 10px;"><span aria-hidden="true">✓</span><span>S'adresse aux personnes <strong>de 65 ans et plus</strong>, handicapées ou isolées vivant à domicile.</span></li>
</a> <li style="padding: 6px 0; display: flex; gap: 10px;"><span aria-hidden="true">✓</span><span>Pendant une vigilance canicule, des <strong>agents communaux appellent</strong> ou rendent visite aux personnes inscrites.</span></li>
</li> <li style="padding: 6px 0; display: flex; gap: 10px;"><span aria-hidden="true">✓</span><span>Inscription en quelques minutes via le <strong>CCAS</strong> de la mairie. Gratuit et révocable à tout moment.</span></li>
<li> </ul>
<a href="https://solidarites.gouv.fr/sites/solidarite/files/migration/Brochure_canicule_grand_public_2024.pdf" rel="noopener">
Brochure officielle Canicule grand public (PDF)
</a>
</li>
<li>
<a href="https://meteofrance.com/comprendre-meteo/temperature-et-chaleur/canicule" rel="noopener">
Comprendre une canicule (Météo France)
</a>
</li>
</ul>
</div> </div>
{/* Cartes par section */}
<div class="grid gap-4" style="grid-template-columns: 1fr;">
<div class="ic-card">
<h2>À qui ça s'adresse</h2>
<p style="margin-top: 8px;">
Le registre nominatif communal est ouvert à toute personne qui le souhaite, mais il est particulièrement utile pour&nbsp;:
</p>
<ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>Les <strong>personnes âgées de 65 ans et plus</strong> vivant à domicile.</li>
<li>Les <strong>personnes en situation de handicap</strong>.</li>
<li>Les <strong>personnes adultes isolées</strong> (sans aidant proche).</li>
<li>Les personnes <strong>fragilisées par une maladie chronique</strong>.</li>
</ul>
<p style="margin-top: 12px; color: var(--ink-2);">
Vous pouvez inscrire un proche (parent, voisin) avec son accord, ou demander une inscription d'office pour une personne dont vous estimez qu'elle est en danger.
</p>
</div>
<div class="ic-card">
<h2>Comment ça se passe en cas d'alerte</h2>
<ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>Quand un département passe en vigilance orange ou rouge canicule, le <em>Plan National Canicule</em> (PNC) s'enclenche en mairie.</li>
<li>Les personnes inscrites sont <strong>appelées</strong> ou <strong>visitées</strong> par des agents communaux ou bénévoles (Croix-Rouge, ADMR…).</li>
<li>L'objectif&nbsp;: vérifier qu'elles vont bien, qu'elles ont de quoi s'hydrater et rester au frais, et alerter si besoin (médecin traitant, 15, famille).</li>
</ul>
</div>
<div class="ic-card">
<h2>Comment s'inscrire (4 étapes)</h2>
<ol style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>
<strong>Contacter le CCAS</strong> (Centre Communal d'Action Sociale) de votre commune, ou directement la mairie.
Annuaire officiel&nbsp;:
<a href="https://lannuaire.service-public.fr/navigation/mairie" rel="noopener" style="color: var(--brand-deep);">lannuaire.service-public.fr/navigation/mairie</a>.
</li>
<li>
Demander le <strong>formulaire d'inscription au registre canicule</strong> (parfois appelé «&nbsp;registre des personnes vulnérables&nbsp;» ou «&nbsp;plan canicule&nbsp;»).
</li>
<li>
Remplir avec&nbsp;: nom, âge, adresse, téléphone, personne à prévenir, médecin traitant, éventuelles particularités (isolement, mobilité, etc.).
</li>
<li>
Retourner le formulaire à la mairie. <strong>Gratuit et confidentiel</strong> — les données ne servent qu'au plan canicule, jamais à des fins commerciales.
</li>
</ol>
</div>
<div class="ic-card">
<h2>Bon à savoir</h2>
<ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>L'inscription est <strong>valable pour toute la saison estivale</strong> (juin à septembre), à renouveler chaque année si besoin.</li>
<li>Vous pouvez vous <strong>désinscrire à tout moment</strong> par simple courrier ou appel.</li>
<li>Cadre légal&nbsp;: article L121-6-1 du Code de l'action sociale et des familles + circulaire annuelle relative au Plan National Canicule.</li>
</ul>
</div>
</div>
{/* Numéro vert canicule */}
<div class="v-block v-jaune" style="margin-top: 28px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap;">
<span aria-hidden="true" style="font-size: 1.8rem; line-height: 1;">📞</span>
<div style="flex: 1; min-width: 260px;">
<strong style="color: var(--v-jaune-ink); font-size: 1.05rem;">Plateforme téléphonique canicule</strong>
<p style="margin-top: 4px; color: var(--v-jaune-ink);">
Numéro vert
<a href="tel:0800066666" style="font-family: var(--font-mono); font-weight: 700; color: inherit;">0&nbsp;800&nbsp;06&nbsp;66&nbsp;66</a>
(gratuit depuis un poste fixe). Activé pendant les épisodes de canicule pour informer et conseiller.
</p>
</div>
</div>
{/* Pour aller plus loin */}
<section style="margin-top: 32px;">
<h2>Pour aller plus loin</h2>
<ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>
<a href="https://www.sante.gouv.fr/sante-et-environnement/risques-climatiques/article/plan-national-canicule-pnc" rel="noopener" style="color: var(--brand-deep);">
Plan National Canicule (santé.gouv.fr)
</a>
</li>
<li>
<a href="https://solidarites.gouv.fr/sites/solidarite/files/migration/Brochure_canicule_grand_public_2024.pdf" rel="noopener" style="color: var(--brand-deep);">
Brochure officielle Canicule grand public (PDF)
</a>
</li>
<li>
<a href="https://meteofrance.com/comprendre-meteo/temperature-et-chaleur/canicule" rel="noopener" style="color: var(--brand-deep);">
Comprendre une canicule (Météo France)
</a>
</li>
</ul>
</section>
{/* Lien vers le kit canicule */}
<a
href="/conseils/canicule"
class="ic-card ic-card-interactive flex flex-wrap items-center justify-between gap-4"
style="padding: 22px; margin-top: 32px; text-decoration: none; color: inherit;"
>
<div style="max-width: 600px;">
<div class="kicker">Conseils pratiques</div>
<h3 style="margin-top: 6px;">Que faire en cas de canicule&nbsp;?</h3>
<p style="margin-top: 6px; color: var(--ink-soft); font-size: 0.95rem;">
Les bons gestes pour se protéger soi-même et veiller sur ses proches.
</p>
</div>
<span class="ic-btn ic-btn-brand">Voir le kit canicule →</span>
</a>
</section> </section>
</Base> </Base>

View file

@ -8,115 +8,125 @@ export const prerender = false;
title="Mentions légales — Info Canicule" title="Mentions légales — Info Canicule"
description="Mentions légales, éditeur, hébergeur, traitement des données personnelles d'Info Canicule." description="Mentions légales, éditeur, hébergeur, traitement des données personnelles d'Info Canicule."
> >
<section class="bg-gradient-to-b from-canicule-50 to-white"> <section class="container-tight" style="padding-block: clamp(28px, 5vw, 56px) 32px;">
<div class="container-tight py-10"> <div class="flex flex-col gap-3" style="margin-bottom: 32px; max-width: 720px;">
<h1 class="text-3xl font-bold sm:text-4xl">Mentions légales</h1> <div class="kicker">Conformes à la LCEN</div>
<p class="mt-2 text-slate-600">Conformes à la LCEN (loi pour la confiance dans l'économie numérique).</p> <h1>Mentions légales</h1>
<p style="color: var(--ink-2);">Édition, hébergement, données personnelles, sources, responsabilité.</p>
</div> </div>
</section>
<section class="container-tight py-8"> <div class="grid gap-4" style="grid-template-columns: 1fr;">
<div class="prose prose-slate max-w-none"> <section class="ic-card">
<h2>Éditeur du site</h2> <h2>Éditeur du site</h2>
<p> <p style="margin-top: 8px;">
Site édité <strong>à titre personnel, sans but lucratif</strong>, par : Site édité <strong>à titre personnel, sans but lucratif</strong>, par&nbsp;:
</p> </p>
<ul> <ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>Florian Bouchet — personne physique</li> <li>Florian Bouchet — personne physique</li>
<li>Contact : <a href="mailto:florian@nocleus.com">florian@nocleus.com</a></li> <li>Contact&nbsp;: <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a></li>
</ul> </ul>
<p> <p style="margin-top: 12px;">
Info Canicule n'a <strong>aucune vocation commerciale</strong> : aucune publicité, aucun chiffre Info Canicule n'a <strong>aucune vocation commerciale</strong>&nbsp;: aucune publicité, aucun chiffre d'affaires,
d'affaires, aucune collecte de données à des fins de monétisation. aucune collecte de données à des fins de monétisation.
</p> </p>
<p> <div class="v-block v-jaune" style="margin-top: 16px;">
<strong>Distinction importante</strong> : l'éditeur exerce par ailleurs une activité de <strong style="color: var(--v-jaune-ink);">Distinction importante</strong>
développement sous le statut de micro-entreprise « <em>Nocleus</em> ». Cette activité commerciale <p style="margin-top: 6px; color: var(--v-jaune-ink);">
est <strong>totalement indépendante</strong> du site Info Canicule, qui est édité hors cadre L'éditeur exerce par ailleurs une activité de développement sous le statut de micro-entreprise «&nbsp;<em>Nocleus</em>&nbsp;».
professionnel, sur fonds propres, à titre purement personnel et bénévole. Aucun service de la Cette activité commerciale est <strong>totalement indépendante</strong> du site Info Canicule, qui est édité hors cadre
micro-entreprise n'est financé, promu ou rattaché à ce site. professionnel, sur fonds propres, à titre purement personnel et bénévole. Aucun service de la micro-entreprise n'est
</p> financé, promu ou rattaché à ce site.
</p>
</div>
</section>
<h2>Hébergement</h2> <section class="ic-card">
<p> <h2>Hébergement</h2>
<strong>OVH SAS</strong> — 2 rue Kellermann, 59100 Roubaix, France. <p style="margin-top: 8px;">
<br /> <strong>OVH SAS</strong> — 2 rue Kellermann, 59100 Roubaix, France.<br />
Téléphone : 1007 (numéro non surtaxé) — <a href="https://www.ovh.com/" rel="noopener">ovh.com</a> Téléphone&nbsp;: 1007 (numéro non surtaxé) —
</p> <a href="https://www.ovh.com/" rel="noopener" style="color: var(--brand-deep);">ovh.com</a>.
<p> </p>
Serveur VPS mutualisé hébergeant plusieurs projets personnels du même éditeur. <p style="margin-top: 12px; color: var(--ink-soft);">
</p> Serveur VPS mutualisé hébergeant plusieurs projets personnels du même éditeur.
</p>
</section>
<h2>Données personnelles</h2> <section class="ic-card">
<p> <h2>Données personnelles</h2>
Info Canicule <strong>ne collecte aucune donnée personnelle</strong> de ses visiteurs. <p style="margin-top: 8px;">
</p> Info Canicule <strong>ne collecte aucune donnée personnelle</strong> de ses visiteurs.
<ul> </p>
<li>Pas de compte utilisateur, pas de formulaire de contact direct (mail uniquement).</li> <ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>Pas de cookies de session ni de tracking.</li> <li>Pas de compte utilisateur, pas de formulaire de contact direct (mail uniquement).</li>
<li> <li>Pas de cookies de session ni de tracking publicitaire.</li>
<strong>Statistiques de fréquentation</strong> : assurées par <li>
<a href="https://umami.is/" rel="noopener">Umami</a>, solution d'analytics auto-hébergée, <strong>Statistiques de fréquentation</strong>&nbsp;: assurées par
RGPD-compatible et sans cookies. Les données collectées (pays, navigateur, page visitée) sont <a href="https://umami.is/" rel="noopener" style="color: var(--brand-deep);">Umami</a>,
agrégées et anonymes. Aucun identifiant individuel n'est stocké. solution d'analytics auto-hébergée, RGPD-compatible et sans cookies. Les données collectées (pays, navigateur, page visitée)
</li> sont agrégées et anonymes. Aucun identifiant individuel n'est stocké.
<li> </li>
<strong>Logs serveur</strong> : adresses IP conservées 14 jours dans les logs Caddy pour des <li>
raisons techniques (debug, détection d'abus via CrowdSec). Pas d'exploitation au-delà. <strong>Logs serveur</strong>&nbsp;: adresses IP conservées 14 jours dans les logs Caddy pour des raisons techniques
</li> (debug, détection d'abus via CrowdSec). Pas d'exploitation au-delà.
</ul> </li>
<p> </ul>
Vos droits RGPD (accès, rectification, suppression, opposition) peuvent être exercés en écrivant à <p style="margin-top: 12px; color: var(--ink-soft);">
<a href="mailto:florian@nocleus.com">florian@nocleus.com</a>. Vos droits RGPD (accès, rectification, suppression, opposition) peuvent être exercés en écrivant à
</p> <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>.
</p>
</section>
<h2>Sources des données</h2> <section class="ic-card">
<p> <h2>Sources des données</h2>
Les alertes Vigilance et données climatologiques affichées proviennent de : <p style="margin-top: 8px;">
</p> Les alertes Vigilance et données climatologiques affichées proviennent de&nbsp;:
<ul> </p>
<li> <ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<strong>Météo France</strong> via le portail <li>
<a href="https://meteo.data.gouv.fr/" rel="noopener">meteo.data.gouv.fr</a> <strong>Météo France</strong> — API officielle (portail météo-France) et
et la rediffusion <a href="https://meteo.data.gouv.fr/" rel="noopener" style="color: var(--brand-deep);">meteo.data.gouv.fr</a>,
<a href="https://public.opendatasoft.com/" rel="noopener">Opendatasoft</a>. avec rediffusion <a href="https://public.opendatasoft.com/" rel="noopener" style="color: var(--brand-deep);">Opendatasoft</a> en filet de secours.
</li> </li>
<li> <li>
Diffusées sous Diffusées sous
<a href="https://www.etalab.gouv.fr/licence-ouverte-open-licence/" rel="noopener">Licence Ouverte 2.0</a> <a href="https://www.etalab.gouv.fr/licence-ouverte-open-licence/" rel="noopener" style="color: var(--brand-deep);">Licence Ouverte 2.0</a>
(Etalab). (Etalab).
</li> </li>
</ul> </ul>
<p> <p style="margin-top: 12px; color: var(--ink-soft);">
Les conseils officiels sont repris des publications de Météo France, santé.gouv.fr et Les conseils officiels sont repris des publications de Météo France, santé.gouv.fr et gouvernement.fr (informations publiques).
gouvernement.fr (informations publiques). </p>
</p> </section>
<h2>Limitation de responsabilité</h2> <section class="ic-card">
<p> <h2>Limitation de responsabilité</h2>
Info Canicule est un service d'information à titre indicatif. Il ne remplace en aucun cas les <p style="margin-top: 8px;">
sources officielles. En cas d'événement météorologique dangereux, suivre les consignes de la Info Canicule est un service d'information à titre indicatif. Il ne remplace en aucun cas les sources officielles.
<strong>Préfecture</strong> et appeler les services d'urgence si nécessaire ( En cas d'événement météorologique dangereux, suivre les consignes de la <strong>Préfecture</strong> et appeler les services d'urgence si nécessaire
<a href="tel:15">15</a>, <a href="tel:18">18</a>, <a href="tel:112">112</a>). (<a href="tel:15" style="color: var(--brand-deep); font-weight: 600;">15</a>,
</p> <a href="tel:18" style="color: var(--brand-deep); font-weight: 600;">18</a>,
<p> <a href="tel:112" style="color: var(--brand-deep); font-weight: 600;">112</a>).
L'éditeur ne saurait être tenu responsable d'un retard ou d'une indisponibilité de </p>
l'information, ni de toute conséquence directe ou indirecte de l'usage des informations affichées <p style="margin-top: 12px;">
sur ce site. L'éditeur ne saurait être tenu responsable d'un retard ou d'une indisponibilité de l'information, ni de toute conséquence
</p> directe ou indirecte de l'usage des informations affichées sur ce site.
</p>
</section>
<h2>Propriété intellectuelle</h2> <section class="ic-card">
<p> <h2>Propriété intellectuelle</h2>
Le code source du site est disponible sur demande à <p style="margin-top: 8px;">
<a href="mailto:florian@nocleus.com">florian@nocleus.com</a>. Les données affichées sont sous Le code source du site est disponible sur demande à
Licence Ouverte 2.0 et réutilisables librement, y compris commercialement, à condition de citer <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>.
Météo France et la licence. Les données affichées sont sous Licence Ouverte 2.0 et réutilisables librement, y compris commercialement, à condition de citer Météo France et la licence.
</p> </p>
<p> <p style="margin-top: 12px;">
Pour consulter la Vigilance Météo France de manière programmatique, utilisez directement Pour consulter la Vigilance Météo France de manière programmatique, utilisez directement
l'<a href="https://portail-api.meteofrance.fr/web/fr/api/DonneesPubliquesVigilance" rel="noopener">API officielle Météo France</a> l'<a href="https://portail-api.meteofrance.fr/web/fr/api/DonneesPubliquesVigilance" rel="noopener" style="color: var(--brand-deep);">API officielle Météo France</a>
(gratuite après inscription). (gratuite après inscription).
</p> </p>
</section>
</div> </div>
</section> </section>
</Base> </Base>

View file

@ -1,23 +0,0 @@
import type { APIRoute } from 'astro';
import { DEPARTEMENTS } from '../lib/departements';
export const prerender = false;
const SITE = 'https://info-canicule.nocleus.com';
export const GET: APIRoute = () => {
const today = new Date().toISOString().split('T')[0];
const urls = DEPARTEMENTS.map(
(d) =>
` <url><loc>${SITE}/departement/${d.code}</loc><lastmod>${today}</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>`,
).join('\n');
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls}
</urlset>
`;
return new Response(xml, {
status: 200,
headers: { 'Content-Type': 'application/xml; charset=utf-8', 'Cache-Control': 'public, max-age=3600' },
});
};