diff --git a/.env.example b/.env.example index ad7fdf1..5448648 100644 --- a/.env.example +++ b/.env.example @@ -12,3 +12,7 @@ VIGILANCE_PROVIDER=opendatasoft # TTL du cache Vigilance en secondes (Vigilance se met à jour 2x/jour, 15min raisonnable) VIGILANCE_CACHE_TTL=900 + +# Umami analytics (optionnel — laisser vide pour désactiver) +UMAMI_WEBSITE_ID= +UMAMI_SRC=https://analytics.nocleus.com/script.js diff --git a/.env.tmpl b/.env.tmpl index ef0787e..ab3f80f 100644 --- a/.env.tmpl +++ b/.env.tmpl @@ -7,3 +7,10 @@ REDIS_URL=redis://info-canicule:{{ pass://Infra/Valkey — info-canicule/passwor VIGILANCE_PROVIDER=opendatasoft VIGILANCE_CACHE_TTL=900 + +# Umami analytics (RGPD, auto-hébergé — analytics.nocleus.com) +UMAMI_WEBSITE_ID={{ pass://Infra/Umami — info-canicule/website_id }} +UMAMI_SRC=https://analytics.nocleus.com/script.js + +# GlitchTip (optionnel — si vide, pas d'envoi Sentry) +SENTRY_DSN={{ pass://Infra/Info Canicule — secrets/SENTRY_DSN }} diff --git a/astro.config.mjs b/astro.config.mjs index 95481d4..b178ada 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,11 +1,20 @@ import { defineConfig } from 'astro/config'; import node from '@astrojs/node'; import tailwind from '@astrojs/tailwind'; +import sitemap from '@astrojs/sitemap'; export default defineConfig({ output: 'server', adapter: node({ mode: 'standalone' }), - integrations: [tailwind({ applyBaseStyles: false })], + integrations: [ + tailwind({ applyBaseStyles: false }), + sitemap({ + filter: (page) => + !page.includes('/api/') && + !page.includes('/departement/'), + // /departement/* est dynamique pour les 96 dépts — généré dans /sitemap-departements.xml.ts à part. + }), + ], server: { host: '0.0.0.0', port: 4321 }, site: 'https://info-canicule.nocleus.com', vite: { diff --git a/package.json b/package.json index 398705c..2606ec4 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ }, "dependencies": { "@astrojs/node": "^9.2.2", + "@astrojs/sitemap": "^3.6.0", "@astrojs/tailwind": "^6.0.2", + "@tailwindcss/typography": "^0.5.16", "astro": "^5.7.0", "ioredis": "^5.6.0", "tailwindcss": "^3.4.17" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da60f1d..c35a180 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,15 @@ importers: '@astrojs/node': specifier: ^9.2.2 version: 9.5.5(astro@5.18.1(@types/node@22.19.19)(ioredis@5.10.1)(jiti@1.21.7)(rollup@4.60.4)(typescript@5.9.3)(yaml@2.9.0)) + '@astrojs/sitemap': + specifier: ^3.6.0 + version: 3.7.2 '@astrojs/tailwind': specifier: ^6.0.2 version: 6.0.2(astro@5.18.1(@types/node@22.19.19)(ioredis@5.10.1)(jiti@1.21.7)(rollup@4.60.4)(typescript@5.9.3)(yaml@2.9.0))(tailwindcss@3.4.19(yaml@2.9.0)) + '@tailwindcss/typography': + specifier: ^0.5.16 + version: 0.5.19(tailwindcss@3.4.19(yaml@2.9.0)) astro: specifier: ^5.7.0 version: 5.18.1(@types/node@22.19.19)(ioredis@5.10.1)(jiti@1.21.7)(rollup@4.60.4)(typescript@5.9.3)(yaml@2.9.0) @@ -76,6 +82,9 @@ packages: resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==} engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + '@astrojs/sitemap@3.7.2': + resolution: {integrity: sha512-PqkzkcZTb5ICiyIR8VoKbIAP/laNRXi5tw616N1Ckk+40oNB8Can1AzVV56lrbC5GKSZFCyJYUVYqVivMisvpA==} + '@astrojs/tailwind@6.0.2': resolution: {integrity: sha512-j3mhLNeugZq6A8dMNXVarUa8K6X9AW+QHU9u3lKNrPLMHhOQ0S7VeWhHwEeJFpEK1BTKEUY1U78VQv2gN6hNGg==} peerDependencies: @@ -769,6 +778,11 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@tailwindcss/typography@0.5.19': + resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} @@ -793,6 +807,12 @@ packages: '@types/node@22.19.19': resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} + '@types/node@24.12.4': + resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==} + + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1721,6 +1741,10 @@ packages: peerDependencies: postcss: ^8.2.14 + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + postcss-selector-parser@6.1.2: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} @@ -1890,6 +1914,11 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + sitemap@9.0.1: + resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==} + engines: {node: '>=20.19.5', npm: '>=10.8.2'} + hasBin: true + smol-toml@1.6.1: resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} engines: {node: '>= 18'} @@ -1908,6 +1937,9 @@ packages: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} + stream-replace-string@2.0.0: + resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2021,6 +2053,9 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -2348,6 +2383,9 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -2434,6 +2472,12 @@ snapshots: dependencies: prismjs: 1.30.0 + '@astrojs/sitemap@3.7.2': + dependencies: + sitemap: 9.0.1 + stream-replace-string: 2.0.0 + zod: 4.4.3 + '@astrojs/tailwind@6.0.2(astro@5.18.1(@types/node@22.19.19)(ioredis@5.10.1)(jiti@1.21.7)(rollup@4.60.4)(typescript@5.9.3)(yaml@2.9.0))(tailwindcss@3.4.19(yaml@2.9.0))': dependencies: astro: 5.18.1(@types/node@22.19.19)(ioredis@5.10.1)(jiti@1.21.7)(rollup@4.60.4)(typescript@5.9.3)(yaml@2.9.0) @@ -2904,6 +2948,11 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} + '@tailwindcss/typography@0.5.19(tailwindcss@3.4.19(yaml@2.9.0))': + dependencies: + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.19(yaml@2.9.0) + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -2930,6 +2979,14 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/node@24.12.4': + dependencies: + undici-types: 7.16.0 + + '@types/sax@1.2.7': + dependencies: + '@types/node': 22.19.19 + '@types/unist@3.0.3': {} '@ungap/structured-clone@1.3.1': {} @@ -4148,6 +4205,11 @@ snapshots: postcss: 8.5.15 postcss-selector-parser: 6.1.2 + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 @@ -4418,6 +4480,13 @@ snapshots: sisteransi@1.0.5: {} + sitemap@9.0.1: + dependencies: + '@types/node': 24.12.4 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.6.0 + smol-toml@1.6.1: {} source-map-js@1.2.1: {} @@ -4428,6 +4497,8 @@ snapshots: statuses@2.0.2: {} + stream-replace-string@2.0.0: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -4557,6 +4628,8 @@ snapshots: undici-types@6.21.0: {} + undici-types@7.16.0: {} + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -4839,4 +4912,6 @@ snapshots: zod@3.25.76: {} + zod@4.4.3: {} + zwitch@2.0.4: {} diff --git a/public/og-image.svg b/public/og-image.svg new file mode 100644 index 0000000..765d1b3 --- /dev/null +++ b/public/og-image.svg @@ -0,0 +1,15 @@ + + + + + + + + + + 🌡️ Info + Canicule + Vigilance Météo France en temps réel + Carte interactive · 96 départements · conseils officiels + Gratuit · sans publicité · non lucratif · données ouvertes + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..a87ef5a --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Allow: / +Disallow: /api/ + +Sitemap: https://info-canicule.nocleus.com/sitemap-index.xml diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index 0f389e4..d133787 100644 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -4,12 +4,43 @@ import '../styles/global.css'; interface Props { title?: string; description?: string; + canonical?: string; + ogImage?: string; + noindex?: boolean; } +const SITE = 'https://info-canicule.nocleus.com'; const { - title = 'Info Canicule — Vigilance météo en temps réel', - description = 'Suivi en temps réel des alertes Vigilance Météo France et conseils officiels en cas de canicule, orages, tempêtes.', + title = 'Info Canicule — Vigilance météo France en temps réel', + description = 'Suivi gratuit et sans publicité des alertes Vigilance Météo France (canicule, orages, tempêtes), avec carte interactive par département et conseils officiels.', + canonical, + ogImage = '/og-image.svg', + noindex = false, } = Astro.props; + +const canonicalUrl = canonical ?? new URL(Astro.url.pathname, SITE).toString(); +const fullOgImage = ogImage.startsWith('http') ? ogImage : `${SITE}${ogImage}`; +const umamiId = import.meta.env.UMAMI_WEBSITE_ID; +const umamiSrc = import.meta.env.UMAMI_SRC ?? 'https://analytics.nocleus.com/script.js'; + +const jsonLd = { + '@context': 'https://schema.org', + '@type': 'WebSite', + name: 'Info Canicule', + url: SITE, + description, + inLanguage: 'fr-FR', + publisher: { + '@type': 'Person', + name: 'Florian Bouchet', + url: 'https://nocleus.com', + }, + potentialAction: { + '@type': 'SearchAction', + target: `${SITE}/departement/{code}`, + 'query-input': 'required name=code', + }, +}; --- @@ -18,24 +49,46 @@ const { - + {noindex ? : } + + {title} + + - + + + + + + + + + + + + + + )}
-
+
@@ -44,22 +97,37 @@ const { diff --git a/src/pages/a-propos.astro b/src/pages/a-propos.astro new file mode 100644 index 0000000..9d9a72d --- /dev/null +++ b/src/pages/a-propos.astro @@ -0,0 +1,91 @@ +--- +import Base from '../layouts/Base.astro'; + +export const prerender = false; +--- + + +
+
+

À propos d'Info Canicule

+

+ Pourquoi ce site existe, comment il fonctionne, ce qu'il ne fait pas. +

+
+
+ +
+

Pourquoi ce site ?

+

+ Les épisodes de canicule, d'orages violents ou de fortes pluies tuent des dizaines de personnes + chaque année en France. Les informations existent — Météo France publie des bulletins Vigilance + 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. +

+

+ Info Canicule 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. +

+ +

Comment ça marche

+ + +

Ce que ce site n'est pas

+ + +

Statut juridique

+

+ Info Canicule est édité à titre personnel, sans but lucratif, 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 + Licence Ouverte 2.0. +

+

+ Voir aussi : mentions légales, + dépendances logicielles, + soutenir le projet. +

+ +

Code source

+

+ Le site est entièrement open source. Le code est disponible sur + git.nocleus.com/florian/info-canicule + (instance Forgejo personnelle). Contributions, signalements de bugs et améliorations bienvenus. +

+ +

Contact

+

+ Mail : florian@nocleus.com — pour toute question, + remarque ou correction (typo, erreur dans un conseil, donnée incohérente). +

+
+ diff --git a/src/pages/dependances.astro b/src/pages/dependances.astro new file mode 100644 index 0000000..fde0d83 --- /dev/null +++ b/src/pages/dependances.astro @@ -0,0 +1,215 @@ +--- +import Base from '../layouts/Base.astro'; +import pkg from '../../package.json'; + +export const prerender = false; + +const deps = Object.entries(pkg.dependencies as Record).sort(([a], [b]) => + a.localeCompare(b), +); +const devDeps = Object.entries(pkg.devDependencies as Record).sort(([a], [b]) => + a.localeCompare(b), +); + +// Catalogue manuel : description + license + URL pour chaque dépendance principale. +const META: Record = { + astro: { + desc: "Framework web orienté contenu (rendu serveur, île d'interactivité).", + license: 'MIT', + url: 'https://astro.build/', + }, + '@astrojs/node': { + desc: 'Adapter Astro pour exécution sur Node.js (mode standalone).', + license: 'MIT', + url: 'https://docs.astro.build/en/guides/integrations-guide/node/', + }, + '@astrojs/tailwind': { + desc: 'Intégration TailwindCSS pour Astro.', + license: 'MIT', + url: 'https://docs.astro.build/en/guides/integrations-guide/tailwind/', + }, + tailwindcss: { + desc: 'Framework CSS utility-first.', + license: 'MIT', + url: 'https://tailwindcss.com/', + }, + ioredis: { + desc: 'Client Redis/Valkey performant pour Node.js (cache du snapshot Vigilance).', + license: 'MIT', + url: 'https://github.com/redis/ioredis', + }, + '@astrojs/check': { + desc: 'Type checker officiel Astro (utilisé en CI / dev).', + license: 'MIT', + url: 'https://docs.astro.build/en/reference/cli-reference/#astro-check', + }, + '@types/node': { + desc: 'Types TypeScript pour les API Node.js.', + license: 'MIT', + url: 'https://www.npmjs.com/package/@types/node', + }, + typescript: { + desc: 'Compilateur TypeScript (vérification de types).', + license: 'Apache-2.0', + url: 'https://www.typescriptlang.org/', + }, +}; + +const DATA_SOURCES = [ + { + name: 'France GeoJSON', + desc: "Polygones des départements français (utilisés pour la carte SVG).", + license: 'Licence Ouverte 2.0', + url: 'https://github.com/gregoiredavid/france-geojson', + }, + { + name: 'Météo France — Vigilance', + desc: 'Bulletin Vigilance en temps réel via Opendatasoft.', + license: 'Licence Ouverte 2.0', + url: 'https://public.opendatasoft.com/explore/dataset/weatherref-france-vigilance-meteo-departement/', + }, + { + name: 'Météo France — Climatologie', + desc: 'Données climatologiques de base quotidiennes (températures, précipitations).', + license: 'Licence Ouverte 2.0', + url: 'https://www.data.gouv.fr/datasets/donnees-climatologiques-de-base-quotidiennes', + }, +]; + +const INFRA = [ + { name: 'Node.js 22', desc: "Runtime serveur.", license: 'MIT', url: 'https://nodejs.org/' }, + { name: 'Docker', desc: 'Containerisation.', license: 'Apache-2.0', url: 'https://www.docker.com/' }, + { name: 'Caddy', desc: 'Reverse proxy + TLS automatique.', license: 'Apache-2.0', url: 'https://caddyserver.com/' }, + { name: 'Valkey', desc: 'Fork ouvert de Redis (cache).', license: 'BSD-3-Clause', url: 'https://valkey.io/' }, + { name: 'Umami', desc: 'Analytics RGPD-friendly (auto-hébergé).', license: 'MIT', url: 'https://umami.is/' }, + { name: 'Forgejo', desc: 'Forge git auto-hébergée + CI/CD.', license: 'MIT', url: 'https://forgejo.org/' }, +]; +--- + + +
+
+

Dépendances

+

+ Transparence sur ce qui fait tourner Info Canicule : code, données, infrastructure. + Tout est open source ou en données ouvertes. +

+
+
+ +
+
+

Sources de données

+ + + + + + + + + + {DATA_SOURCES.map((s) => ( + + + + + + ))} + +
SourceDescriptionLicence
+ {s.name} + {s.desc}{s.license}
+
+ +
+

Bibliothèques applicatives

+ + + + + + + + + + + {deps.map(([name, version]) => { + const m = META[name]; + return ( + + + + + + + ); + })} + +
PackageVersionDescriptionLicence
+ {m ? {name} : name} + {version}{m?.desc ?? '—'}{m?.license ?? '—'}
+
+ +
+

Outillage de développement

+ + + + + + + + + + {devDeps.map(([name, version]) => { + const m = META[name]; + return ( + + + + + + ); + })} + +
PackageVersionLicence
+ {m ? {name} : name} + {version}{m?.license ?? '—'}
+
+ +
+

Infrastructure

+ + + + + + + + + + {INFRA.map((i) => ( + + + + + + ))} + +
ComposantDescriptionLicence
+ {i.name} + {i.desc}{i.license}
+
+ +

+ Code source du site : + + git.nocleus.com/florian/info-canicule + +

+
+ diff --git a/src/pages/mentions-legales.astro b/src/pages/mentions-legales.astro new file mode 100644 index 0000000..f8340c0 --- /dev/null +++ b/src/pages/mentions-legales.astro @@ -0,0 +1,113 @@ +--- +import Base from '../layouts/Base.astro'; + +export const prerender = false; +--- + + +
+
+

Mentions légales

+

Conformes à la LCEN (loi pour la confiance dans l'économie numérique).

+
+
+ +
+

Éditeur du site

+

+ Site édité à titre personnel, sans but lucratif, par : +

+
    +
  • Florian Bouchet — développeur indépendant
  • +
  • Contact : florian@nocleus.com
  • +
  • Statut : personne physique (pas d'entreprise immatriculée, pas d'association)
  • +
+

+ Le site n'a aucune vocation commerciale. Aucun chiffre d'affaires, aucune publicité, aucune + collecte de données à des fins de monétisation. +

+ +

Hébergement

+

+ OVH SAS — 2 rue Kellermann, 59100 Roubaix, France. +
+ Téléphone : 1007 (numéro non surtaxé) — ovh.com +

+

+ Serveur VPS mutualisé hébergeant plusieurs projets personnels du même éditeur. +

+ +

Données personnelles

+

+ Info Canicule ne collecte aucune donnée personnelle de ses visiteurs. +

+
    +
  • Pas de compte utilisateur, pas de formulaire de contact direct (mail uniquement).
  • +
  • Pas de cookies de session ni de tracking.
  • +
  • + Statistiques de fréquentation : assurées par + Umami, solution d'analytics auto-hébergée, + RGPD-compatible et sans cookies. Les données collectées (pays, navigateur, page visitée) sont + agrégées et anonymes. Aucun identifiant individuel n'est stocké. +
  • +
  • + Logs serveur : adresses IP conservées 14 jours dans les logs Caddy pour des + raisons techniques (debug, détection d'abus via CrowdSec). Pas d'exploitation au-delà. +
  • +
+

+ Vos droits RGPD (accès, rectification, suppression, opposition) peuvent être exercés en écrivant à + florian@nocleus.com. +

+ +

Sources des données

+

+ Les alertes Vigilance et données climatologiques affichées proviennent de : +

+ +

+ Les conseils officiels sont repris des publications de Météo France, santé.gouv.fr et + gouvernement.fr (informations publiques). +

+ +

Limitation de responsabilité

+

+ Info Canicule est un service d'information à titre indicatif. Il ne remplace en aucun cas les + sources officielles. En cas d'événement météorologique dangereux, suivre les consignes de la + Préfecture et appeler les services d'urgence si nécessaire ( + 15, 18, 112). +

+

+ L'éditeur ne saurait être tenu responsable d'un retard ou d'une indisponibilité de + l'information, ni de toute conséquence directe ou indirecte de l'usage des informations affichées + sur ce site. +

+ +

Propriété intellectuelle

+

+ Le code source du site est sous licence libre ( + repo Forgejo + ). 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. +

+

+ L'endpoint /api/vigilance diffuse le snapshot courant en JSON (CORS *), pour + réutilisation par tout site ou application qui le souhaite. +

+
+ diff --git a/src/pages/sitemap-departements.xml.ts b/src/pages/sitemap-departements.xml.ts new file mode 100644 index 0000000..3342aa3 --- /dev/null +++ b/src/pages/sitemap-departements.xml.ts @@ -0,0 +1,23 @@ +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) => + ` ${SITE}/departement/${d.code}${today}daily0.7`, + ).join('\n'); + const xml = ` + +${urls} + +`; + return new Response(xml, { + status: 200, + headers: { 'Content-Type': 'application/xml; charset=utf-8', 'Cache-Control': 'public, max-age=3600' }, + }); +}; diff --git a/src/pages/soutenir.astro b/src/pages/soutenir.astro new file mode 100644 index 0000000..cbfd507 --- /dev/null +++ b/src/pages/soutenir.astro @@ -0,0 +1,74 @@ +--- +import Base from '../layouts/Base.astro'; + +export const prerender = false; +--- + + +
+
+

Soutenir Info Canicule

+

+ Le site est gratuit, sans publicité et sans traceurs commerciaux. Si vous le trouvez utile, + vous pouvez aider à couvrir l'hébergement (~7 €/mois mutualisés sur plusieurs projets perso). +

+
+
+ +
+

Don libre via Ko-fi

+

+ Le moyen le plus simple : un don libre, sans inscription, par carte bancaire ou PayPal, via + ko-fi.com/daelwizhit. + Les dons sont anonymes par défaut et entièrement optionnels. +

+ + + +

Ce que les dons financent

+
    +
  • Location du VPS OVH qui héberge le site (~7 €/mois, mutualisés avec d'autres projets perso).
  • +
  • Nom de domaine annuel.
  • +
  • Café pour les soirées de maintenance 🥲.
  • +
+

+ Ce site n'a aucune vocation commerciale. Aucun chiffre d'affaires, aucun salaire + versé. Les dons couvrent les frais techniques ou, en cas d'excédent, financent d'autres petits + projets d'utilité publique du même développeur. +

+ +

Autres manières d'aider

+
    +
  • + Signaler un bug ou une typo : par mail à + florian@nocleus.com ou via une issue sur le + repo Forgejo. +
  • +
  • + Partager le site autour de vous, en particulier auprès de personnes fragiles + (proches âgés, personnes isolées) pour qui les conseils canicule peuvent faire une vraie + différence. +
  • +
  • + Réutiliser les données : l'endpoint /api/vigilance diffuse le + snapshot en JSON (CORS *), réutilisable librement sous Licence Ouverte 2.0. +
  • +
+ +

+ Pour les questions juridiques (mention de l'éditeur, statut), voir les + mentions légales. +

+
+ diff --git a/tailwind.config.mjs b/tailwind.config.mjs index c4a3807..2dc1f99 100644 --- a/tailwind.config.mjs +++ b/tailwind.config.mjs @@ -1,3 +1,6 @@ +import { createRequire } from 'node:module'; +const require = createRequire(import.meta.url); + /** @type {import('tailwindcss').Config} */ export default { content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], @@ -24,5 +27,5 @@ export default { }, }, }, - plugins: [], + plugins: [require('@tailwindcss/typography')], };