diff --git a/.env.example b/.env.example index ace6a89..0eab434 100644 --- a/.env.example +++ b/.env.example @@ -9,8 +9,10 @@ # Nom de domaine public de l'app sur le VPS. Un seul domaine sert à la fois # l'écran et le navigateur : le callback OIDC, l'URL d'image envoyée au panneau # et les liens du README en dépendent tous. Doit rester cohérent avec AUTH_URL. -APP_DOMAIN=horaires.loxi.ch -# Port publié en local (dev). En production, Traefik s'en charge : aucun port publié. +APP_DOMAIN=horaires.ita-ito.com +# Port publié sur l'hôte. 3000 est déjà pris par la stack facture_ocr sur la +# machine de développement, d'où 3010 ; en production Traefik s'en charge et +# aucun port n'est publié. APP_PORT=3010 APP_BIND=127.0.0.1 TZ=Europe/Zurich @@ -34,7 +36,7 @@ TEST_DATABASE_URL= # # URI de redirection à déclarer dans Authentik (correspondance stricte) : # /api/auth/callback/authentik -AUTH_URL=https://horaires.loxi.ch +AUTH_URL=https://horaires.ita-ito.com # Générer avec : openssl rand -base64 33 AUTH_SECRET= diff --git a/.env.swp b/.env.swp deleted file mode 100644 index 48d7bb2..0000000 Binary files a/.env.swp and /dev/null differ diff --git a/PLAN.md b/PLAN.md index f859746..0014246 100644 --- a/PLAN.md +++ b/PLAN.md @@ -47,7 +47,7 @@ par deux chemins qui ne se croisent jamais. │ GET /api/device/image/.bmp ← non devinable, immuable, cacheable ▼ ┌─────────────────────────────────────────────────────┐ - │ Next.js 16 (App Router, TS strict) trmnl.loxi.ch │ + │ Next.js 16 (App Router, TS strict) horaires.ita-ito.com │ │ │ │ lib/schedule/resolver.ts ← pur, sans I/O, 100 % testé │ lib/screen/viewmodel.ts ← Prisma → ScreenPayload (schema 1) @@ -250,7 +250,7 @@ e2e/*.spec.ts ← Playwright | `GET /api/device/image/.bmp` | — | l'image, `Cache-Control: immutable` | **Appairage** (README, pas de reflash) : maintenir le bouton ~5 s → portail captif → Wi-Fi → -*Advanced > Custom Server > Yes* → `https://trmnl.loxi.ch` **sans slash final**. +*Advanced > Custom Server > Yes* → `https://horaires.ita-ito.com` **sans slash final**. `refresh_rate` adaptatif, calculé à chaque `/api/display` : `refreshRateOpenSec` (600) si la boutique est ouverte ou ouvre dans l'heure, `refreshRateClosedSec` (7200) sinon, et raccourci @@ -314,7 +314,7 @@ change pas, badge + bouton « Réessayer ». ``` DATABASE_URL POSTGRES_USER / PASSWORD / DB -APP_DOMAIN # ex. trmnl.loxi.ch — callback OIDC + image_url ← À CONFIRMER +APP_DOMAIN # ex. horaires.ita-ito.com — callback OIDC + image_url ← À CONFIRMER NEXTAUTH_URL NEXTAUTH_SECRET AUTHENTIK_ISSUER # https://auth.loxi.ch/application/o// ← À CONFIRMER AUTHENTIK_CLIENT_ID AUTHENTIK_CLIENT_SECRET @@ -412,8 +412,8 @@ npm run lint && npm run typecheck && npm run test -- --coverage # 3. Contrat d'affichage, sans appareil npm run screen:preview # → aperçu 800×480 dans le navigateur -curl -s localhost:3000/api/display -H "Access-Token: " | jq -curl -s localhost:3000/api/device/image/.bmp -o /tmp/screen.bmp +curl -s localhost:3010/api/display -H "Access-Token: " | jq +curl -s localhost:3010/api/device/image/.bmp -o /tmp/screen.bmp file /tmp/screen.bmp # attendu : PC bitmap, 800 x 480 x 1 # 4. Non-régression horaires (le test qui compte) @@ -431,7 +431,7 @@ du jour, une modification faite depuis un téléphone apparaît au réveil suiva ## Points à confirmer -1. **Domaine public** de l'app sur le VPS (`trmnl.loxi.ch` ?) — nécessaire au callback OIDC +1. **Domaine public** de l'app sur le VPS (`horaires.ita-ito.com` ?) — nécessaire au callback OIDC et à l'`image_url` servie à l'appareil. 2. **Slug de l'application Authentik** et **nom du groupe admin**. 3. **Clé API `llk_…`** pour `api.loxi.ch`, et confirmation que l'instance est bien joignable diff --git a/lib/config.ts b/lib/config.ts index 4712c76..99aafb8 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -29,7 +29,7 @@ export function publicBaseUrl(request?: Request): string { return domain.startsWith('http') ? domain.replace(/\/$/, '') : `https://${domain}`; } - return 'http://localhost:3000'; + return 'http://localhost:3010'; } /** diff --git a/lib/screen/__snapshots__/viewmodel.test.ts.snap b/lib/screen/__snapshots__/viewmodel.test.ts.snap index 405f3d2..0bd45d7 100644 --- a/lib/screen/__snapshots__/viewmodel.test.ts.snap +++ b/lib/screen/__snapshots__/viewmodel.test.ts.snap @@ -8,7 +8,7 @@ exports[`buildScreenPayload > matches the frozen payload contract 1`] = ` "text_fr": "Fermeture exceptionnelle jeudi après-midi", }, "generated_at": "2026-09-22T12:00:00+02:00", - "logo_url": "https://trmnl.loxi.ch/brand/logo-eink.png", + "logo_url": "https://horaires.ita-ito.com/brand/logo-eink.png", "schema": 1, "shop_name": "ITA ITO", "today": { diff --git a/lib/screen/render.test.ts b/lib/screen/render.test.ts index 8b4150f..8b82657 100644 --- a/lib/screen/render.test.ts +++ b/lib/screen/render.test.ts @@ -9,7 +9,7 @@ const PAYLOAD: ScreenPayload = { schema: 1, generated_at: '2026-09-22T12:00:00+02:00', shop_name: 'ITA ITO', - logo_url: 'https://trmnl.loxi.ch/brand/logo-eink.png', + logo_url: 'https://horaires.ita-ito.com/brand/logo-eink.png', today: { date_fr: 'Mardi 22 septembre', date_en: 'Tuesday 22 September', diff --git a/lib/screen/viewmodel.test.ts b/lib/screen/viewmodel.test.ts index 1d00159..86c34de 100644 --- a/lib/screen/viewmodel.test.ts +++ b/lib/screen/viewmodel.test.ts @@ -37,7 +37,7 @@ function input(overrides: Partial[0]> = {} now: new Date('2026-09-22T10:00:00Z'), ctx: context(), shopName: 'ITA ITO', - logoUrl: 'https://trmnl.loxi.ch/brand/logo-eink.png', + logoUrl: 'https://horaires.ita-ito.com/brand/logo-eink.png', messages: [] as MessageCandidate[], ...overrides, }; diff --git a/package.json b/package.json index ee07b99..e702a42 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "dev": "next dev --port 3010", "build": "next build", - "start": "next start", + "start": "next start --port ${PORT:-3010}", "lint": "eslint . --max-warnings 0", "typecheck": "tsc --noEmit", "test": "vitest run", diff --git a/scripts/preview.ts b/scripts/preview.ts index 0807bcc..034bf8e 100644 --- a/scripts/preview.ts +++ b/scripts/preview.ts @@ -61,7 +61,7 @@ function payload(): ScreenPayload { now: new Date('2026-09-23T10:30:00Z'), ctx: CONTEXT, shopName: 'ITA ITO', - logoUrl: 'https://trmnl.loxi.ch/brand/logo-eink.png', + logoUrl: 'https://horaires.ita-ito.com/brand/logo-eink.png', messages: [ { textFr: 'Fermeture exceptionnelle jeudi matin',