diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index a547bf3..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
diff --git a/index.html b/index.html
index fa46007..ec77368 100644
--- a/index.html
+++ b/index.html
@@ -2,14 +2,22 @@
-
+
+
+
-
+
+
+
+
Skori
diff --git a/nginx.conf b/nginx.conf
index 0b309c1..716d53e 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -5,21 +5,29 @@ server {
index index.html;
# Important pour les Single Page Applications (React Router)
- # Si le fichier n'existe pas, on redirige vers index.html
location / {
try_files $uri $uri/ /index.html;
}
- # Mise en cache agressive pour les assets statiques
- location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|webp)$ {
+ # Mise en cache agressive pour les assets statiques fingerprintés
+ location ~* \.(?:css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|webp|ico|pdf)$ {
expires 6M;
access_log off;
add_header Cache-Control "public, max-age=15552000, immutable";
}
- # Ne pas mettre en cache le service worker pour que la PWA se mette à jour
+ # Jamais de cache sur les fichiers pilotant les mises à jour PWA
+ location = /index.html {
+ add_header Cache-Control "no-cache, must-revalidate";
+ }
location = /sw.js {
- expires -1;
- add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
+ add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
+ }
+ location = /manifest.webmanifest {
+ add_header Cache-Control "no-cache, must-revalidate";
+ types { } default_type application/manifest+json;
+ }
+ location ~* ^/workbox-.*\.js$ {
+ add_header Cache-Control "public, max-age=15552000, immutable";
}
}
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 0000000..597f744
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/favicon-32.png b/public/favicon-32.png
new file mode 100644
index 0000000..1915de8
Binary files /dev/null and b/public/favicon-32.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..00f251b
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/pwa-192x192.png b/public/pwa-192x192.png
new file mode 100644
index 0000000..896b0ff
Binary files /dev/null and b/public/pwa-192x192.png differ
diff --git a/public/pwa-512x512.png b/public/pwa-512x512.png
new file mode 100644
index 0000000..63e5340
Binary files /dev/null and b/public/pwa-512x512.png differ
diff --git a/public/pwa-maskable-512x512.png b/public/pwa-maskable-512x512.png
new file mode 100644
index 0000000..6b47dcb
Binary files /dev/null and b/public/pwa-maskable-512x512.png differ
diff --git a/vite.config.ts b/vite.config.ts
index 2d6afa2..d8d86aa 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -8,15 +8,20 @@ export default defineConfig({
react(),
VitePWA({
registerType: "autoUpdate",
- includeAssets: ["favicon.ico", "apple-touch-icon.png", "mask-icon.svg"],
+ includeAssets: ["favicon.ico", "apple-touch-icon.png"],
manifest: {
- name: "Skori",
+ name: "Skori — Scores de jeux de société",
short_name: "Skori",
description:
"Application Web de gestion des scores pour jeux de société",
- theme_color: "#ffffff",
- background_color: "#ffffff",
+ lang: "fr",
+ start_url: "/",
+ scope: "/",
display: "standalone",
+ orientation: "portrait",
+ theme_color: "#0f766e",
+ background_color: "#ffffff",
+ categories: ["games", "utilities"],
icons: [
{
src: "pwa-192x192.png",
@@ -29,13 +34,35 @@ export default defineConfig({
type: "image/png",
},
{
- src: "pwa-512x512.png",
+ src: "pwa-maskable-512x512.png",
sizes: "512x512",
type: "image/png",
- purpose: "any maskable",
+ purpose: "maskable",
},
],
},
+ workbox: {
+ // Précache le shell de l'app + les logos/bannières (légers, en webp)
+ globPatterns: ["**/*.{js,css,html,ico,png,svg,webp,woff2}"],
+ // Les PDF de règles (jusqu'à 12 Mo) ne sont PAS précachés :
+ // ils sont mis en cache à la demande, à la première consultation.
+ runtimeCaching: [
+ {
+ urlPattern: /\/games-assets\/.*\.pdf$/,
+ handler: "CacheFirst",
+ options: {
+ cacheName: "rules-pdf",
+ expiration: {
+ maxEntries: 10,
+ maxAgeSeconds: 60 * 60 * 24 * 90, // 90 jours
+ },
+ cacheableResponse: { statuses: [0, 200] },
+ },
+ },
+ ],
+ navigateFallback: "/index.html",
+ cleanupOutdatedCaches: true,
+ },
}),
],
resolve: {