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>
</div>
{/* Pourquoi */}
<section style="margin-bottom: 56px;">
<h2 style="margin-bottom: 20px;">Pourquoi&nbsp;?</h2>
<div class="grid gap-4" style="grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));">
{why.map((b) => (
<div class="ic-card-soft">
<h3>{b.title}</h3>
<p style="margin-top: 8px; line-height: 1.5; color: var(--ink-soft);">{b.text}</p>
</div>
))}
</div>
</section>
{/* Comment ça marche */}
<section style="margin-bottom: 56px;">
<h2 style="margin-bottom: 16px;">Comment ça marche</h2>
<div class="ic-card">
<ul style="padding-left: 20px; line-height: 1.75;">
<li>
<strong>Vigilance</strong> · API officielle Météo France (et Opendatasoft en filet de secours).
Bulletin officiel publié deux fois par jour (~6h et ~16h), avec cache court côté serveur pour amortir les pics de trafic.
</li>
<li>
<strong>Températures observées</strong> · réseau SYNOP, station ouverte la plus proche du département. Données horaires.
</li>
<li>
<strong>Climatologie quotidienne</strong> · 365 derniers jours via
<a href="https://meteo.data.gouv.fr/" rel="noopener" style="color: var(--brand-deep);">meteo.data.gouv.fr</a>
(jeu de données <em>Données climatologiques de base — quotidiennes</em>).
</li>
<li>
<strong>Normales climatologiques</strong> · WMO 19912020, indexées par département × jour de l'année.
</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>
{/* Engagement accessibilité */}
<section style="margin-bottom: 56px;">
<h2 style="margin-bottom: 16px;">Notre engagement accessibilité</h2>
<div class="grid gap-3" style="grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));">
{a11y.map((claim) => (
<div class="ic-card flex items-start gap-3" style="padding: 16px;">
<span style="color: var(--v-vert); flex-shrink: 0; font-weight: 700;" aria-hidden="true">✓</span>
<span style="font-size: 0.95rem; line-height: 1.45;">{claim}</span>
</div>
))}
</div>
</section>
{/* Ce que ce site n'est pas */}
<section style="margin-bottom: 56px;">
<h2 style="margin-bottom: 16px;">Ce que ce site n'est pas</h2>
<div class="ic-card">
<ul style="padding-left: 20px; line-height: 1.75;">
<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>
<li><strong>Pas un site commercial.</strong> Aucune publicité, aucune monétisation, aucune affiliation, aucune vente de données.</li>
<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>
</ul>
</div>
</section>
{/* Statut juridique */}
<section style="margin-bottom: 56px;">
<h2 style="margin-bottom: 16px;">Statut juridique</h2>
<div class="ic-card">
<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> </p>
</div> </div>
</section> </section>
<section class="container-tight py-8"> {/* À venir */}
<div class="prose prose-slate max-w-none"> <section style="margin-bottom: 56px;">
<h2>Pourquoi ce site ?</h2> <div class="kicker">À venir</div>
<p> <h2 style="margin-top: 8px; margin-bottom: 16px;">Prochaines étapes</h2>
Les épisodes de canicule, d'orages violents ou de fortes pluies tuent des dizaines de personnes <p style="color: var(--ink-soft); max-width: 640px; margin-bottom: 20px;">
chaque année en France. Les informations existent — Météo France publie des bulletins Vigilance 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.
détaillés, le gouvernement diffuse des conseils — mais elles sont éparpillées, parfois difficiles
à trouver, souvent enfouies sous des bannières publicitaires sur les sites grand public.
</p>
<p>
<strong>Info Canicule</strong> est un site d'utilité publique qui ne fait qu'une chose :
afficher clairement, gratuitement, sans publicité ni traceurs commerciaux, la Vigilance Météo
France en temps réel et les conseils officiels à appliquer.
</p> </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>
<h2>Comment ça marche</h2> {/* Code source + Contact */}
<ul> <section style="margin-bottom: 24px;">
<li> <h2 style="margin-bottom: 16px;">Code source &amp; contact</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
par jour (matin et après-midi).
</li>
<li>
<strong>Données climatologiques</strong> : températures journalières des 30 derniers jours,
récupérées depuis <a href="https://meteo.data.gouv.fr/" rel="noopener">meteo.data.gouv.fr</a>
(jeu de données <em>Données climatologiques de base — quotidiennes</em>), agrégées en moyenne
sur toutes les stations du département.
</li>
<li>
<strong>Conseils officiels</strong> : repris des publications de
<a href="https://www.meteofrance.fr/" rel="noopener">Météo France</a>,
<a href="https://sante.gouv.fr/" rel="noopener">santé.gouv.fr</a> et
<a href="https://www.gouvernement.fr/" rel="noopener">gouvernement.fr</a>.
</li>
</ul>
<h2>Ce que ce site n'est pas</h2>
<ul>
<li><strong>Pas un service officiel</strong>. En cas d'urgence, suivre les consignes de la Préfecture (
<a href="tel:112">112</a>).</li>
<li><strong>Pas un site commercial</strong>. Aucune publicité, aucune monétisation, aucun affiliation,
aucune vente de données.</li>
<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>
</ul>
<h2>Statut juridique</h2>
<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. Les données affichées sont publiques et réutilisables sous
<a href="https://www.etalab.gouv.fr/licence-ouverte-open-licence/" rel="noopener">Licence Ouverte 2.0</a>.
</p>
<p>
Voir aussi : <a href="/mentions-legales">mentions légales</a>,
<a href="/dependances">dépendances logicielles</a>,
<a href="/soutenir">soutenir le projet</a>.
</p>
<h2>Code source</h2>
<p> <p>
Le code est disponible sur demande à Le code est disponible sur demande à
<a href="mailto:florian@nocleus.com">florian@nocleus.com</a> (contributions, signalements de <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>
bugs et améliorations bienvenus). — contributions, signalements de bug et améliorations bienvenus.
</p> </p>
<p style="margin-top: 12px;">
<h2>Contact</h2> Pour toute question, remarque ou correction (typo, erreur dans un conseil, donnée incohérente)&nbsp;:
<p> <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>.
Mail : <a href="mailto:florian@nocleus.com">florian@nocleus.com</a> — pour toute question,
remarque ou correction (typo, erreur dans un conseil, donnée incohérente).
</p> </p>
</div> </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.
</p> Idéal pour informer un proche en quelques secondes.
<div class="mt-4 rounded-lg border border-canicule-200 bg-canicule-50 p-4">
<p class="text-sm font-semibold text-canicule-900">
🛡️ Aider une personne fragile : <a href="/conseils/registre-canicule" class="font-bold underline">
registre canicule de la mairie
</a>
</p>
<p class="mt-1 text-sm text-canicule-800">
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.
</p> </p>
</div> </div>
</div>
</section>
<section class="container-tight py-8"> {/* Bloc registre canicule — utilité publique majeure */}
<div class="space-y-12"> <a
href="/conseils/registre-canicule"
class="ic-card ic-card-interactive flex flex-wrap items-center justify-between gap-4"
style="padding: 22px; margin-bottom: 28px; text-decoration: none; color: inherit; border-color: var(--line-strong); background: var(--brand-tint);"
>
<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>
</div>
<span class="ic-btn ic-btn-brand">
Voir la fiche →
</span>
</a>
{/* Cards par phénomène */}
<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>
))} <h3 style={`margin-top: 16px; color: var(--v-${color}-ink);`}>
<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>
<div style={`display: flex; align-items: center; gap: 6px; margin-top: 16px; color: var(--v-${color}-ink); font-weight: 600;`}>
{advice.emergency.length > 0 && ( Voir le kit →
<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>
)} </a>
</article>
); );
}) })
} }
</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 <div class="flex flex-col gap-3" style="margin-bottom: 24px;">
cas d'alerte canicule. Conçu en priorité pour les personnes fragiles et isolées. <div class="kicker">Dispositif communal · gratuit · confidentiel</div>
<h1>🛡️ Registre canicule</h1>
<p style="font-size: clamp(1rem, 0.9rem + 0.4vw, 1.18rem); color: var(--ink-2); max-width: 720px; line-height: 1.55;">
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> </p>
</div> </div>
</section>
<section class="container-tight py-8"> {/* TL;DR coloré pour donner l'essentiel en un coup d'œil */}
<div class="prose prose-slate max-w-none"> <div class="v-block v-orange" style="margin-bottom: 28px;">
<strong style="color: var(--v-orange-ink); font-size: 1.05rem;">L'essentiel en 30 secondes</strong>
<ul style="margin-top: 10px; padding-left: 0; list-style: none; color: var(--v-orange-ink);">
<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>
<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 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>
</ul>
</div>
{/* Cartes par section */}
<div class="grid gap-4" style="grid-template-columns: 1fr;">
<div class="ic-card">
<h2>À qui ça s'adresse</h2> <h2>À qui ça s'adresse</h2>
<p>Le registre nominatif communal est ouvert à toute personne qui le souhaite, mais il est <p style="margin-top: 8px;">
particulièrement utile pour :</p> Le registre nominatif communal est ouvert à toute personne qui le souhaite, mais il est particulièrement utile pour&nbsp;:
<ul>
<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> </p>
<ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<h2>Comment ça se passe en cas d'alerte</h2> <li>Les <strong>personnes âgées de 65 ans et plus</strong> vivant à domicile.</li>
<ul> <li>Les <strong>personnes en situation de handicap</strong>.</li>
<li>Quand un département passe en vigilance orange ou rouge canicule, le plan « Plan National <li>Les <strong>personnes adultes isolées</strong> (sans aidant proche).</li>
Canicule » (PNC) s'enclenche en mairie.</li> <li>Les personnes <strong>fragilisées par une maladie chronique</strong>.</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> </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>
<h2>Comment s'inscrire</h2> <div class="ic-card">
<ol> <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> <li>
Contacter le <strong>CCAS</strong> (Centre Communal d'Action Sociale) de votre commune, ou <strong>Contacter le CCAS</strong> (Centre Communal d'Action Sociale) de votre commune, ou directement la mairie.
directement la mairie. Numéros disponibles via l'annuaire officiel des mairies : Annuaire officiel&nbsp;:
<a href="https://lannuaire.service-public.fr/navigation/mairie" rel="noopener"> <a href="https://lannuaire.service-public.fr/navigation/mairie" rel="noopener" style="color: var(--brand-deep);">lannuaire.service-public.fr/navigation/mairie</a>.
lannuaire.service-public.fr/navigation/mairie
</a>
</li> </li>
<li> <li>
Demander le <strong>formulaire d'inscription au registre canicule</strong> (parfois appelé Demander le <strong>formulaire d'inscription au registre canicule</strong> (parfois appelé «&nbsp;registre des personnes vulnérables&nbsp;» ou «&nbsp;plan canicule&nbsp;»).
« registre des personnes vulnérables » ou « plan canicule »).
</li> </li>
<li> <li>
Remplir le formulaire avec : nom, âge, adresse, téléphone, personne à prévenir, médecin Remplir avec&nbsp;: nom, âge, adresse, téléphone, personne à prévenir, médecin traitant, éventuelles particularités (isolement, mobilité, etc.).
traitant, éventuelles particularités (isolement, mobilité, etc.).
</li> </li>
<li> <li>
Retourner le formulaire à la mairie. <strong>Gratuit et confidentiel</strong> — les données Retourner le formulaire à la mairie. <strong>Gratuit et confidentiel</strong> — les données ne servent qu'au plan canicule, jamais à des fins commerciales.
ne servent qu'au plan canicule, ne sont pas partagées commercialement.
</li> </li>
</ol> </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>
</div> </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> <h2>Pour aller plus loin</h2>
<ul> <ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li> <li>
<a href="https://www.sante.gouv.fr/sante-et-environnement/risques-climatiques/article/plan-national-canicule-pnc" rel="noopener"> <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) Plan National Canicule (santé.gouv.fr)
</a> </a>
</li> </li>
<li> <li>
<a href="https://solidarites.gouv.fr/sites/solidarite/files/migration/Brochure_canicule_grand_public_2024.pdf" rel="noopener"> <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) Brochure officielle Canicule grand public (PDF)
</a> </a>
</li> </li>
<li> <li>
<a href="https://meteofrance.com/comprendre-meteo/temperature-et-chaleur/canicule" rel="noopener"> <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) Comprendre une canicule (Météo France)
</a> </a>
</li> </li>
</ul> </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> </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 class="grid gap-4" style="grid-template-columns: 1fr;">
<section class="ic-card">
<h2>Éditeur du site</h2>
<p style="margin-top: 8px;">
Site édité <strong>à titre personnel, sans but lucratif</strong>, par&nbsp;:
</p>
<ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>Florian Bouchet — personne physique</li>
<li>Contact&nbsp;: <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a></li>
</ul>
<p style="margin-top: 12px;">
Info Canicule n'a <strong>aucune vocation commerciale</strong>&nbsp;: aucune publicité, aucun chiffre d'affaires,
aucune collecte de données à des fins de monétisation.
</p>
<div class="v-block v-jaune" style="margin-top: 16px;">
<strong style="color: var(--v-jaune-ink);">Distinction importante</strong>
<p style="margin-top: 6px; color: var(--v-jaune-ink);">
L'éditeur exerce par ailleurs une activité de développement sous le statut de micro-entreprise «&nbsp;<em>Nocleus</em>&nbsp;».
Cette activité commerciale est <strong>totalement indépendante</strong> du site Info Canicule, qui est édité hors cadre
professionnel, sur fonds propres, à titre purement personnel et bénévole. Aucun service de la micro-entreprise n'est
financé, promu ou rattaché à ce site.
</p>
</div> </div>
</section> </section>
<section class="container-tight py-8"> <section class="ic-card">
<div class="prose prose-slate max-w-none">
<h2>Éditeur du site</h2>
<p>
Site édité <strong>à titre personnel, sans but lucratif</strong>, par :
</p>
<ul>
<li>Florian Bouchet — personne physique</li>
<li>Contact : <a href="mailto:florian@nocleus.com">florian@nocleus.com</a></li>
</ul>
<p>
Info Canicule n'a <strong>aucune vocation commerciale</strong> : aucune publicité, aucun chiffre
d'affaires, aucune collecte de données à des fins de monétisation.
</p>
<p>
<strong>Distinction importante</strong> : l'éditeur exerce par ailleurs une activité de
développement sous le statut de micro-entreprise « <em>Nocleus</em> ». Cette activité commerciale
est <strong>totalement indépendante</strong> du site Info Canicule, qui est édité hors cadre
professionnel, sur fonds propres, à titre purement personnel et bénévole. Aucun service de la
micro-entreprise n'est financé, promu ou rattaché à ce site.
</p>
<h2>Hébergement</h2> <h2>Hébergement</h2>
<p> <p style="margin-top: 8px;">
<strong>OVH SAS</strong> — 2 rue Kellermann, 59100 Roubaix, France. <strong>OVH SAS</strong> — 2 rue Kellermann, 59100 Roubaix, France.<br />
<br /> Téléphone&nbsp;: 1007 (numéro non surtaxé) —
Téléphone : 1007 (numéro non surtaxé) — <a href="https://www.ovh.com/" rel="noopener">ovh.com</a> <a href="https://www.ovh.com/" rel="noopener" style="color: var(--brand-deep);">ovh.com</a>.
</p> </p>
<p> <p style="margin-top: 12px; color: var(--ink-soft);">
Serveur VPS mutualisé hébergeant plusieurs projets personnels du même éditeur. Serveur VPS mutualisé hébergeant plusieurs projets personnels du même éditeur.
</p> </p>
</section>
<section class="ic-card">
<h2>Données personnelles</h2> <h2>Données personnelles</h2>
<p> <p style="margin-top: 8px;">
Info Canicule <strong>ne collecte aucune donnée personnelle</strong> de ses visiteurs. Info Canicule <strong>ne collecte aucune donnée personnelle</strong> de ses visiteurs.
</p> </p>
<ul> <ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li>Pas de compte utilisateur, pas de formulaire de contact direct (mail uniquement).</li> <li>Pas de compte utilisateur, pas de formulaire de contact direct (mail uniquement).</li>
<li>Pas de cookies de session ni de tracking.</li> <li>Pas de cookies de session ni de tracking publicitaire.</li>
<li> <li>
<strong>Statistiques de fréquentation</strong> : assurées par <strong>Statistiques de fréquentation</strong>&nbsp;: assurées par
<a href="https://umami.is/" rel="noopener">Umami</a>, solution d'analytics auto-hébergée, <a href="https://umami.is/" rel="noopener" style="color: var(--brand-deep);">Umami</a>,
RGPD-compatible et sans cookies. Les données collectées (pays, navigateur, page visitée) sont solution d'analytics auto-hébergée, RGPD-compatible et sans cookies. Les données collectées (pays, navigateur, page visitée)
agrégées et anonymes. Aucun identifiant individuel n'est stocké. sont agrégées et anonymes. Aucun identifiant individuel n'est stocké.
</li> </li>
<li> <li>
<strong>Logs serveur</strong> : adresses IP conservées 14 jours dans les logs Caddy pour des <strong>Logs serveur</strong>&nbsp;: adresses IP conservées 14 jours dans les logs Caddy pour des raisons techniques
raisons techniques (debug, détection d'abus via CrowdSec). Pas d'exploitation au-delà. (debug, détection d'abus via CrowdSec). Pas d'exploitation au-delà.
</li> </li>
</ul> </ul>
<p> <p style="margin-top: 12px; color: var(--ink-soft);">
Vos droits RGPD (accès, rectification, suppression, opposition) peuvent être exercés en écrivant à Vos droits RGPD (accès, rectification, suppression, opposition) peuvent être exercés en écrivant à
<a href="mailto:florian@nocleus.com">florian@nocleus.com</a>. <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>.
</p> </p>
</section>
<section class="ic-card">
<h2>Sources des données</h2> <h2>Sources des données</h2>
<p> <p style="margin-top: 8px;">
Les alertes Vigilance et données climatologiques affichées proviennent de : Les alertes Vigilance et données climatologiques affichées proviennent de&nbsp;:
</p> </p>
<ul> <ul style="margin-top: 12px; padding-left: 20px; line-height: 1.7;">
<li> <li>
<strong>Météo France</strong> via le portail <strong>Météo France</strong> — API officielle (portail météo-France) et
<a href="https://meteo.data.gouv.fr/" rel="noopener">meteo.data.gouv.fr</a> <a href="https://meteo.data.gouv.fr/" rel="noopener" style="color: var(--brand-deep);">meteo.data.gouv.fr</a>,
et la rediffusion avec rediffusion <a href="https://public.opendatasoft.com/" rel="noopener" style="color: var(--brand-deep);">Opendatasoft</a> en filet de secours.
<a href="https://public.opendatasoft.com/" rel="noopener">Opendatasoft</a>.
</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>
<section class="ic-card">
<h2>Limitation de responsabilité</h2> <h2>Limitation de responsabilité</h2>
<p> <p style="margin-top: 8px;">
Info Canicule est un service d'information à titre indicatif. Il ne remplace en aucun cas les Info Canicule est un service d'information à titre indicatif. Il ne remplace en aucun cas les sources officielles.
sources officielles. En cas d'événement météorologique dangereux, suivre les consignes de la 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
<strong>Préfecture</strong> et appeler les services d'urgence si nécessaire ( (<a href="tel:15" style="color: var(--brand-deep); font-weight: 600;">15</a>,
<a href="tel:15">15</a>, <a href="tel:18">18</a>, <a href="tel:112">112</a>). <a href="tel:18" style="color: var(--brand-deep); font-weight: 600;">18</a>,
<a href="tel:112" style="color: var(--brand-deep); font-weight: 600;">112</a>).
</p> </p>
<p> <p style="margin-top: 12px;">
L'éditeur ne saurait être tenu responsable d'un retard ou d'une indisponibilité de L'éditeur ne saurait être tenu responsable d'un retard ou d'une indisponibilité de l'information, ni de toute conséquence
l'information, ni de toute conséquence directe ou indirecte de l'usage des informations affichées directe ou indirecte de l'usage des informations affichées sur ce site.
sur ce site.
</p> </p>
</section>
<section class="ic-card">
<h2>Propriété intellectuelle</h2> <h2>Propriété intellectuelle</h2>
<p> <p style="margin-top: 8px;">
Le code source du site est disponible sur demande à Le code source du site est disponible sur demande à
<a href="mailto:florian@nocleus.com">florian@nocleus.com</a>. Les données affichées sont sous <a href="mailto:florian@nocleus.com" style="color: var(--brand-deep);">florian@nocleus.com</a>.
Licence Ouverte 2.0 et réutilisables librement, y compris commercialement, à condition de citer 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.
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' },
});
};