尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Site vitrine + espace membre, réécrit avec Next.js 15 (App Router, Server Actions) et PostgreSQL. Conçu pour tourner sur Vercel avec une base Neon (offre gratuite). La version PHP historique reste dans le dossier NexoraTV/ (elle n'est pas compatible Vercel). • Node.js 18.18+ (ou 20+) — • Un compte Vercel — • Une base PostgreSQL gratuite — le plus simple : Neon (), ou l'intégration « Postgres » depuis le tableau de bord Vercel. Trois variables d'environnement sont nécessaires (plus deux facultatives) :檢視完整 README ↗
Site vitrine + espace membre, réécrit avec Next.js 15 (App Router, Server Actions) et PostgreSQL. Conçu pour tourner sur Vercel avec une base Neon (offre gratuite).
La version PHP historique reste dans le dossier
NexoraTV/(elle n'est pas compatible Vercel).
Trois variables d'environnement sont nécessaires (plus deux facultatives) :
| Variable | Rôle |
|---|---|
DATABASE_URL | Chaîne de connexion PostgreSQL (utilisez la version « pooled »). |
AUTH_SECRET | Secret de signature des sessions (JWT). |
ENCRYPTION_KEY | Clé AES-256 (64 caractères hexadécimaux) pour chiffrer les identifiants d'abonnement. |
RESEND_API_KEY | (facultatif) clé API Resend pour l'e-mail de réinitialisation de mot de passe. Sans elle, le lien est écrit dans les logs. |
MAIL_FROM | (facultatif) expéditeur des e-mails, ex. NexoraTV <[email protected]>. |
APP_URL | (facultatif) URL publique du site, pour les liens dans les e-mails. |
GOLDENOTT_API_KEY | (facultatif) token du compte revendeur GoldenOTT. Active le provisioning automatique des abonnements (voir §10). Sans elle, seule la saisie manuelle d'identifiants est disponible. |
GOLDENOTT_API_URL | (facultatif) base de l'API GoldenOTT. Défaut : https://goldenott.net/api. |
CRON_SECRET | (facultatif) secret partagé pour la route de synchronisation planifiée /api/cron/goldenott-sync. |
Le fichier .env.local fourni contient déjà un AUTH_SECRET et un
ENCRYPTION_KEY générés. Il ne reste qu'à renseigner DATABASE_URL.
Pour régénérer les secrets :
node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))" # AUTH_SECRET
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" # ENCRYPTION_KEY
npm install
# renseignez DATABASE_URL dans .env.local
npm run dev
Ouvrez http://localhost:3000. Le schéma de base de données est créé automatiquement au premier chargement d'une page. Aucun compte administrateur n'est créé automatiquement — voir « Devenir administrateur » ci-dessous.
git init
git add .
git commit -m "NexoraTV — Next.js"
git branch -M main
git remote add origin https://github.com/VOTRE-COMPTE/nexoratv.git
git push -u origin main
DATABASE_URL, AUTH_SECRET,
ENCRYPTION_KEY.Aucun compte admin n'est créé automatiquement (par sécurité). Pour promouvoir un compte :
/inscription.UPDATE users SET role = 'admin' WHERE email = '[email protected]';
/admin est maintenant accessible depuis le menu de
compte.💡 Base de données : dans Vercel, l'onglet Storage → Create Database → Postgres (Neon) crée la base et injecte
DATABASE_URLautomatiquement dans le projet.
| Page | Route | Accès |
|---|---|---|
| Accueil | / | public |
| Avis | /avis | public |
| Tuto | /tuto | public |
| Contact | /contact | public |
| Connexion | /connexion | public |
| Inscription | /inscription | public |
| Mot de passe oublié | /mot-de-passe-oublie | public |
| Réinitialisation | /reinitialiser-mot-de-passe | public (lien e-mail) |
| Mon profil | /profil | connecté |
| Administration | /admin | admin |
| Mentions légales | /mentions-legales | public |
| Confidentialité | /confidentialite | public |
| Conditions d'utilisation | /conditions | public |
| Cookies | /cookies | public |
| 404 | toute URL inconnue | — |
/inscription)./admin, choisit le client, et ajoute ses
identifiants d'abonnement (libellé, URL du serveur, utilisateur, mot de
passe, date d'expiration, statut, note)./profil, avec boutons
Afficher / Copier. Le statut (actif / suspendu / expiré) est affiché.Un client peut avoir plusieurs abonnements. Le premier compte créé devient automatiquement administrateur s'il n'en existe aucun.
HttpOnly + SameSite=Lax
Secure en production.dangerouslySetInnerHTML).next.config.mjs).middleware.ts bloque l'accès à /profil et /admin sans session valide.[entre crochets]).RESEND_API_KEY, MAIL_FROM,
domaine vérifié) : la réinitialisation de mot de passe passe par lib/mail.ts.
Sans clé, le lien de réinitialisation est écrit dans les logs.
Le formulaire de contact (actions/contact-actions.ts) reste à brancher
sur le même helper.DATABASE_URL pointe bien vers la connexion pooled.L'API revendeur GoldenOTT permet de créer, prolonger, rembourser et synchroniser les abonnements IPTV directement depuis NexoraTV, au lieu de les saisir à la main dans le panel.
GOLDENOTT_API_KEY (.env.local et Vercel →
Settings → Environment Variables).La clé ne quitte jamais le serveur (lib/goldenott.ts est server-only).
Chaque appel sensible est tracé dans la table goldenott_events
(visible en bas de /admin).
| Type | Identifiant client | Route API |
|---|---|---|
Ligne M3U (line) | utilisateur + mot de passe | /v1/lines |
Boîtier MAG (mag) | adresse MAC | /v1/mags |
Code d'activation (code) | code à saisir dans l'appli | /v1/active-codes |
/admin → un client → Ajouter un abonnement → onglet GoldenOTT :
choix du forfait (chargé en direct depuis l'API, avec son coût en crédits),
template de bouquets optionnel, identifiants générés automatiquement si laissés
vides. À la validation, l'abonnement est créé sur GoldenOTT et enregistré
localement (identifiants chiffrés) puis rattaché au client.
Sur chaque abonnement GoldenOTT : ↻ Sync (rafraîchit statut + expiration),
Prolonger (choix d'un forfait → extend), Rembourser (crédite le compte
revendeur, mass_refund optionnel).
/admin/offres : l'admin emballe un forfait GoldenOTT sous un nom
commercial + un prix en euros (table iptv_offers). Pour les lignes M3U, on
peut autoriser le client à choisir son nombre d'écrans (1 → 5) avec un
supplément par écran (défaut +3 €) ; le prix se met à jour en direct sur
/commander et le total est figé dans la commande./commander : le client choisit une offre → une commande est créée
(iptv_orders, statut pending). Le paiement s'insère ici plus tard./admin/commandes : l'admin valide → provisioning GoldenOTT →
abonnement rattaché, commande fulfilled. Ou refuse avec un motif.lib/order-mail.ts, via Resend) : à la commande
→ confirmation au client + notification à l'équipe (ORDER_NOTIFY_EMAIL
ou l'e-mail du 1er admin) ; à la validation → « abonnement actif » au
client ; au refus → e-mail avec le motif. Nécessite RESEND_API_KEY +
MAIL_FROM sur un domaine vérifié./profil, le client peut demander le renouvellement d'un abonnement
existant (→ commande de type renouvellement → l'admin valide → extend).vercel.json déclare un Cron Job Vercel sur /api/cron/goldenott-sync
(protégé par CRON_SECRET). Il met à jour l'expiration et le statut de tous
les abonnements GoldenOTT (200 max par passage, les plus anciennement
synchronisés d'abord).
0 3 * * * (03:00 UTC). Le cron ne s'exécute que sur le déploiement
Production.0 */6 * * * (toutes les 6 h) ou plus.Vercel envoie automatiquement l'en-tête Authorization: Bearer $CRON_SECRET
si la variable CRON_SECRET existe dans le projet. Appel manuel :
curl -H "Authorization: Bearer $CRON_SECRET" https://<site>/api/cron/goldenott-sync
Mise en place :
# 1. déclarer le secret côté Vercel (Production)
echo "<valeur-de-CRON_SECRET>" | vercel env add CRON_SECRET production
# 2. déployer — le cron apparaît alors dans Vercel → Project → Cron Jobs
git push # (déclenche le déploiement)
| Fichier | Rôle |
|---|---|
lib/goldenott.ts | client HTTP de l'API (auth, parsing, erreurs typées) |
lib/goldenott-catalog.ts | chargement mutualisé profil + forfaits + templates |
lib/goldenott-provision.ts | logique métier : créer / prolonger / rembourser / synchroniser + journal |
actions/goldenott-actions.ts | Server Actions admin |
actions/offer-actions.ts / order-actions.ts | offres et commandes |
app/api/cron/goldenott-sync/route.ts | synchronisation planifiée |
nexoratv-vercel/
├── app/
│ ├── layout.tsx globals.css page.tsx not-found.tsx manifest.ts
│ ├── icon.png apple-icon.png favicon.ico
│ ├── avis/ tuto/ contact/ connexion/ inscription/
│ ├── profil/ (page + NameForm + PasswordForm + RenewButton)
│ ├── commander/ (page + OrderForm — self-service client)
│ ├── admin/ (page + SubscriptionForm + ProviderActions)
│ │ ├── offres/ (catalogue d'offres vendables)
│ │ └── commandes/ (validation des commandes clients)
│ ├── api/cron/goldenott-sync/ (synchronisation planifiée)
│ └── mentions-legales/ confidentialite/ conditions/ cookies/
├── actions/
│ ├── auth-actions.ts (inscription, connexion, déconnexion)
│ ├── profile-actions.ts (nom, mot de passe)
│ ├── admin-actions.ts (abonnements manuels, rôles, suppression)
│ ├── goldenott-actions.ts (provision / extend / refund / sync)
│ ├── offer-actions.ts (CRUD des offres)
│ ├── order-actions.ts (commandes clients + validation admin)
│ └── contact-actions.ts
├── components/ (NavBar, SiteHeader/Footer, Faq, CopyButton, SecretValue…)
├── lib/
│ ├── db.ts (PostgreSQL + création du schéma + admin initial)
│ ├── auth.ts (sessions JWT, rôles, hash bcrypt)
│ ├── crypto.ts (AES-256-GCM + identifiants aléatoires)
│ ├── data.ts (requêtes abonnements / utilisateurs / offres / commandes)
│ ├── goldenott.ts (client API GoldenOTT, server-only)
│ ├── goldenott-catalog.ts (profil + forfaits + templates, mutualisé)
│ ├── goldenott-provision.ts (logique métier + journal d'audit)
│ ├── validation.ts types.ts
├── middleware.ts (protection des routes /profil et /admin)
├── next.config.mjs (en-têtes de sécurité + CSP)
└── .env.local / .env.example